webapp/ (new, site-agnostic, independently deployable):
- WebApp: fluent client (pathjoin/query/withHeaders/cookies/get/post)
as RpcTarget; flower-style unions cite NuxiNL/flower v0.11 (Jan 2019);
url/headers private (RpcTarget property reads are RPC); Error messages
carry no header/param values; query-stripped URLs only
- WebAppDo: per-instance authority in DO storage (survives eviction);
one-shot configure(), refuses different-url re-configure
- WebAppFactory: newWebApp(init) -> {id, app}, at(id); ids are bearer
capabilities and are not logged
- HTTP surface: GET / mint form (secret header keys render blank),
POST / mint (form or JSON), POST /at/<id> drive-by-capability
- types via wrangler types (worker-configuration.d.ts, gitignored)
diigo-dump/: now a webapp consumer. The diigo knowledge is only the
mint call: url=interact_api/, UA + x-requested-with, cookie, 500ms gate.
- src/webapp.ts, src/diigo-web.ts deleted (webapp's are canonical);
diigo.ts slimmed to dumpBookmarks + PagedGet
- /_connect is state-aware: connect form pre-mint; health check
(count=1 probe) + re-mint path post-mint; home-page link relabeled
- mint success page: narrow field + copy button (attribute-quoting
fixed; id in x-diigo-web-id header for scripts)
- scripts/diigo-login: askpass flow, marked OBSOLETE (page flow is
the primary); speaks the form protocol; writes only DIIGO_WEB_ID —
the cookie lives in DO storage, never on disk
- package.json: dev = wrangler dev -c wrangler.jsonc -c ../webapp/...
(verified: Ready on :8787, GET / 200, /_connect 200);
wrangler ^4.148.0 devDependency after node_modules was cleaned
TODO(webapp) in webapp/README.md: proxy-page vs primary-worker mint
form; reconsider as the UI grows.
Generated-by: opencode (GLM)
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-dump README) vs running webapp as
the primary worker (wrangler dev -c ../webapp/wrangler.jsonc -c ../diigo-dump/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=<urlencoded JSON>&msPerCall=…; secret header keys (cookie, authorization, proxy-authorization) render blank — paste them at mint time; never echoed back.POST /— mint. Form-encoded (that page) or JSON{url, headers, msPerCall}(service-style). Responds{id}(andx-webapp-id). The id is not logged: possession is authority.POST /at/<id>— drive an instance by capability: JSON{path?, query?, method?, body?}→ the fluent chain →{status, text}(or{error}; messages carry no header/param values).
RPC surface (same-account workers; binding entrypoint: "WebAppFactory")
newWebApp({url, headers?, msPerCall?})→{id, app}— the fluent stub; promise pipelining makes a wholepathjoin().query().get()chain a single round tripat(id)— the fluent stub for a previously-minted instance
Run
npx wrangler dev # → http://localhost:8788 (its own wrangler dir)
Status: typechecks; mint + drive not yet exercised end-to-end (needs the combined dev run; see ../diigo-dump/README.md).