Spike OAuth-on-Workers (passes) and scaffold the v1 workspace master
The ADR 0011 §6 spike verdict: @atproto/oauth-client-node@0.5.2 runs on Cloudflare Workers under nodejs_compat with a three-shim compat layer, all through documented constructor options — HTTP handle resolver, custom did:plc/did:web resolver (the default bakes redirect:'error' into a Request, which workerd rejects at construction), and a fetch that emulates redirect:'error' via 'manual'. A live authorize() against bsky.social returned a real authorization URL from workerd; the @atcute fallback is not needed. Also answered the carried-over ADR 0012 question: site-icon upload needs a separate blob:image/* scope — permission sets cannot carry blob permissions. Findings checkpointed in docs/research/2026-08-03-oauth-workers-spike.md. The scaffold that follows from it: - npm workspaces; Node 22; GitHub Actions CI (check, test, build) - apps/web: SvelteKit (Svelte 5) + adapter-cloudflare + wrangler with nodejs_compat and a D1 binding; the OAuth compat layer from the spike; D1-backed state/session stores with migrations; login → callback → admin routes with an HMAC-signed session cookie; loopback OAuth client in dev, confidential client (client-metadata.json + jwks.json) when OAUTH_PRIVATE_KEY_JWK is set. Smoke-tested on workerd: POST /login returns a bsky.social authorization URL with state persisted in D1. - packages/lexicons: loader + 17 convention tests over lexicons/ (NSID↔path, required createdAt, 10× maxLength rule, permission-set integrity, sample-record validation incl. open-union and negatives). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014mXNfP5m9NhhjVgM5VVJ5E