feat(m5): deferred-items sweep — pre-accept WS auth, vault envelopes, idempotent write retries, honest RPC taxonomy#6
Merged
Conversation
… idempotent write retries, honest RPC taxonomy
Closes out every deliberately-deferred item plus the known cosmetic/noise
quirks, and performs the first real deploy:
- backend: routeAgentRequest onBeforeConnect/onBeforeRequest reject
unauthorized upgrades 401/404 at the Worker edge (in-DO onConnect gate
kept as defense in depth); onClose only stamps status for connections
that were authorized (a rejected socket can no longer mark a pending
session detached)
- backend: dispatch/fillSecret return a typed DispatchOutcome instead of
throwing across the DO RPC boundary — kills workerd's
'Uncaught (in promise)' instrumentation noise at the root and upgrades
the taxonomy (503 not-connected, 503 resynced-mid-command, 504 timeout,
409 duplicate-in-flight; unknown errors still 500)
- vault: AES-256-GCM envelope encryption over KV (v1.<iv>.<ct>, fresh IV)
under a VAULT_MASTER_KEY Worker secret; EncryptedKvVault behind the
VaultBinding seam; scripts/vault-put.mjs seeds envelopes (plaintext via
stdin); legacy plaintext values fail closed
- idempotent write retries end to end: protocol exports
WRITE_COMMAND_TYPES (single classification source, connector's act union
pinned to it at compile time); connector derives write commandIds from
the breakwater idempotency key (ik_<key>); the session DO records
completed write Events (cap 100) and replays repeats; the extension
keeps its own replay record (cap 50, storage.session) for the
service-timed-out-after-execution case
- cdp-spike: attended OOPIF probe (Target.setAutoAttach{flatten:true} +
session-scoped commands) with bundled cross-origin-iframe test page and
runbook — retires the M0-deferred unknown when run
- packaging/CI: CHANGELOG.md in both packages' files arrays; changeset
(protocol minor, connector minor); engines asymmetry documented;
actions/checkout@v5, setup-node@v5, pnpm/action-setup@v6 (node24
runtimes); pnpm peerDependencyRules for workers-types-5 / ai-sdk-zod-4
peer noise
- deploy: first wrangler deploy to
https://understudy-backend.gcharang.workers.dev with real minted
secrets and the VAULT namespace; live smoke verified (health, 401,
mint, fail-fast 503, WS-gate 401, encrypted vault seed); runbook in
apps/backend/README.md
173 tests green across the workspace; zero unhandled-rejection lines.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- .gitignore: add .secrets* (operator-local secret backups; the deployed worker is canonical). Specific prefix so the tracked .dev.vars.example is unaffected. - README Secrets section: per-secret table (what it is / regenerate / rotation impact), when to rotate, and the re-push paths (per-secret put or bulk). - The actual values live in apps/backend/.secrets.production.env, gitignored and never committed — Cloudflare never shows a secret again after put, so that file is the only readable backup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes out every deliberately-deferred M5 item plus the known cosmetic/noise quirks, and performs understudy's first real deploy. 184 tests green across the workspace (protocol 21 / extension 49 / connector 24 / backend 90); zero unhandled-rejection lines.
What changed
Security & correctness
routeAgentRequest'sonBeforeConnect/onBeforeRequestreject unauthorized upgrades at the Worker edge (401 bad token / 404 cross-tenant, no existence oracle) before the DO accepts them. The in-DOonConnectgate stays as defense in depth.onCloseauth-gating — a never-authorized socket's close can no longer stamp a pending sessiondetached.dispatch/fillSecretreturn a typedDispatchOutcomeinstead of throwing across the DO RPC boundary (workerd logs every server-side RPC rejection asUncaught (in promise)even when handled). Route mapping: 503 not-connected / 503 resynced-mid-command / 504 timeout / 409 duplicate-in-flight; genuine bugs still 500 (with anassertNeverexhaustiveness backstop).v1.<iv>.<ct>AES-256-GCM envelopes under aVAULT_MASTER_KEYWorker secret (src/vault.ts);scripts/vault-put.mjsseeds them; a legacy/corrupt at-rest value fails closed with a scrubbedok:false.Idempotent write retries (end to end)
@understudy/protocolexportsWRITE_COMMAND_TYPESas the single classification source and reclassifiesscroll/switch_tabas writes — they're user-visible side effects, so a dry-run now simulates them (previously a dry-runswitch_tabactually switched the tab) and a retry replays them (a relative-dyscrollno longer double-scrolls). This collapses the old connector⇄protocol divergence.commandIdfrom the breakwater idempotency key (ik_<key>); the service caches completed write Events (completedWrites, cap 100) and replays repeats (409 for a concurrent duplicate); the extension keeps a matching cap-100 replay and in-flight record so a duplicate that arrives while the original is still executing is dropped, not re-run — closing a silent-double-execution race under a backend-timeout.Probes, packaging, CI, deploy
apps/cdp-spike(Target.setAutoAttach{flatten:true}+ session-scoped commands + a bundled cross-origin-iframe page + runbook) — retires the M0-deferred unknown when run (attended, Chrome ≥125).files; changeset (protocol + connector minor); engines asymmetry documented.peerDependencyRulesinpnpm-workspace.yamlfor the workers-types-5 / ai-sdk-zod-4 peer warnings.https://understudy-backend.gcharang.workers.devwith real minted secrets + the VAULT namespace; live smoke verified (health, 401, mint, fail-fast 503, WS-gate 401, encrypted vault seed). Runbook inapps/backend/README.md.Quality gate
Three parallel review lanes (clean-code / architecture / QA) ran on the branch. They caught two real blocking bugs the initial 173-test suite missed — silent double-execution under a timeout race, and the
scroll/switch_tabdry-run/replay gap — both fixed at root and folded into this commit; a re-review round signed both off, and one further non-blocking straggler-record race (session change mid-execution) was closed with aremember()in-flight guard.🤖 Generated with Claude Code