# webapp DO-backed fluent web client factory: site-agnostic. Deploy once; instances are attenuated handles whose **ids are bearer capabilities** — anyone holding the id string can drive the instance; nobody without it can. TODO: this proxy-page flow (see [diigo-cache CONTRIBUTING](../diigo-cache/CONTRIBUTING.md)) vs running webapp as the primary worker (`wrangler dev -c ../webapp/wrangler.jsonc -c ../diigo-cache/wrangler.jsonc`) so its own port serves the mint form directly; reconsider when the UI grows past a form or two. ## HTTP surface - `GET /` — the mint form. Prefill via query string: `?url=…&headers=&msPerCall=…&title=…`; secret header keys (cookie, authorization, proxy-authorization) render **blank** — paste them at mint time; never echoed back. A dedicated `cookie` field is sugar for the `cookie` header (if the JSON also has one, they must agree). - `GET /form?render=1&…` — the same form for a proxying worker (diigo-cache's `/_connect`): the action is left as an `ACTION` placeholder for the proxy to point at its own relay. - `POST /` — mint. Form-encoded (that page) or JSON `{url, headers, msPerCall}` (service-style). Responds `{id}` (and `x-webapp-id`). The id is *not* logged: possession is authority. - `POST /at/` — drive an instance by capability: JSON `{path?, query?, method?, body?}` → the fluent chain → `{status, text}` (or `{error}`; messages carry no header/param values). - `POST /at//cookie` — rotate the instance's cookie in place: JSON `{cookie}` → `{ok: true}`. The id that drives an instance can also replace its cookie; the account owner revokes by logging out. ## RPC surface (same-account workers; binding `entrypoint: "WebAppFactory"`) - `fetch(request)` — the HTTP surface above, over the binding - `newWebApp({url, headers?, msPerCall?})` → `{id, app}` — the fluent stub; promise pipelining makes a whole `pathjoin().query().get()` chain a single round trip - `at(id)` — the fluent stub for a previously-minted instance - `cookies(id)` — the instance's cookie store (a MapStore from [the capsite lib](../lib/src/store.ts) with key shape `"cookie"`): `set("cookie", …)` rotates it under every handle already out ## The cookie store An instance is fixed at creation except for its cookie, which lives in a store rather than in `init`; every send reads it. Instances minted before the store held their cookie in `init.headers`; the first `handle()` moves it over in one transaction. ## Run pnpm test # cookie store + rotation (vitest, workerd pool) npx wrangler dev # → its own ready line (usually :8787 with the # two-config diigo-cache run; standalone, :8788) Status: mint + drive exercised end-to-end in the combined dev run (through diigo-cache's create flow, 2026-10-07); not yet deployed. See ../capsite-checklist.md — the single source for run/connect/deploy instructions.