Changes touching this path

  • the browser mints the seed and the account binds the key: Clerk in the site's own routes, variant-B onboarding, and the account tier's one producer (#753) Migration 0007 adds account_seed (the passphrase-wrapped envelope, opaque ciphertext the server cannot open) and forge_identity, a NOLOGIN role scoped to exactly the identity tier -- SELECT/INSERT on tenant, SELECT/INSERT plus a column-scoped UPDATE of retired_at on account_key, the full row on account_seed, and nothing else (pinned live by forge_identity_is_scoped_to_the_identity_tier). The producer lives in site/src/server/identity/ behind a verified Clerk session (verifyToken in the site's own route handlers, reusing the millerbyte Clerk instance and pattern, never the gateway service). Registration is one transaction: upsert tenant on the verified clerk_user_id, add the key, store the envelope, retire what rotation names -- and never zero live keys. The Rust service still writes none of the tier; tests/account_tier.rs now guards that boundary instead of a vacancy. Onboarding is #487's variant B, the two-column contract: the app owns the 32 bytes (crypto.getRandomValues -> 24-word BIP39 over the ENTROPY, never the 64-byte derivation -> ed25519 pubkey via @noble/curves, held to the engine's from_seed by the pinned RFC 8032 vector), a WebCrypto PBKDF2+AES-GCM envelope, a .txt download that excludes the passphrase, and two consent checkboxes that no download waives. Clerk mounts only under /account, which joins /k/ on the prerender deny-list; every static surface stays static. Follow-ons filed rather than folded: #926 (CLI raw-seed import, so BIP39 recovery reaches the CLI) and #927 (account-aware may_push, burn entitlement via account, and the #506 historical-key 301s the anonymous read tier deliberately cannot serve today). 278e1886 · dbf3dbe6…
  • the last sweep's fix-up, and the item with teeth was a doc that told its reader to make the edit its own route file forbids: the component said it was exported so the route could load it LAZILY, where the route records that lazy was measured and REJECTED at 581 bytes against 270 and says in as many words not to fix it back without re-measuring. It now carries the route's true reason - so a test can render either half without a router - and marks explicitly that this is not a lazy split, pointing at the route for the readings rather than copying its numbers. The receipt showed eight hex characters wearing the class the module reserves for a FULL fingerprint, on the one surface whose whole purpose is an out-of-band fingerprint comparison, with adjacent copy inviting a comparison eight characters cannot support; it now shows the full fingerprint, derived in the accept from the bytes the apply itself re-verified rather than re-shortened in the surface, so the receipt cannot be rendered from the offer the apply was meant to re-check. Dropping the class and keeping eight was rejected because it would make the receipt say LESS about the one thing being checked. Rendered bytes did not really move - three gate builds read the same surface at 199873, 199872 and 199873 against 199872 recorded, and the whole sixty-route spread is minus seven to plus four - so nothing was re-recorded and the two bytes the ticket asked about turn out to be the instrument rather than an unaccounted byte. CONTEXT.md's list of account_of's consumers stops being a third copy and POINTS at the header that owns it, naming the one consumer #1746's own restatement dropped - which is the lesson of this fix-up, since that restatement was itself the remedy for a count-drift finding and drifted in the same way. The budget note is corrected as PROSE with no ceiling and no measurement touched: uniformly on every one of these surfaces was authored from a single weighing, and one surface moved the other way and had its ceiling LOWERED after its page lost six entries. The decline receipt moves into the register module that owns the vocabulary, with an absent-phrase list and a RENDERING control, because an absent-phrase list over copy that never renders proves nothing. And a count of refusals is removed rather than corrected: the numbers are labels for rules and do not line up with the code, since the first propagates from the walk and the fifth leaves from more than one site with different sentences (#1751) 571d3533 · dbf3dbe6…diff

Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.