Changes touching this path

  • the grant lane is fixed-width and acked, so a deposit frames no length and a read destroys nothing (#818) Closes #818 and #816, deliberately together. Both are hard wire breaks on the same two endpoints, and #818 said so itself: landed separately it buys a second relay-before-clients redeploy for a shape improvement. Landed as one, the grant lane breaks once and comes out uniform. #818 — the deposit body is `[recipient pubkey 32][grantor envelope...]`. `split_deposit` is still the only thing that runs before authorization, and it is now a constant-size slice: no length field, no UTF-8, no hex decode. This was never a vulnerability — the old length was attacker-controlled but correctly bounds-checked, and #621 already moved `Frame::decode` below the gate. What it was is a shape every future reader had to re-verify, and a "the grantee is a key" rule enforced by a validator that a later well-meaning change could relax. A fixed-width field cannot be relaxed. The mailbox index stays hex-keyed on disk, so the relay now mints that hex instead of parsing the caller's spelling. #816 — `/pull-grants` returns the due blobs and keeps them; a new `POST /grants/ack` names the content addresses the caller durably applied and drops exactly those. Handing bytes to a socket was never proof of receipt: the connection can drop, or `apply_sealed_grant` can fail after they arrive, and the grant was then gone from both sides. `loot pull-grants` acks only what it applied or quarantined — anything that hit a `skipping` branch stays pending, or this would be drain-on-read wearing an extra round trip. An ack is scoped to the acker's own mailbox, and since blobs are content-addressed a shared file is unlinked only when no index entry anywhere still refers to it. This also shrinks #621's accepted replay cost: a replayed read envelope now re-reads bytes the holder already had instead of destroying them. Not a format major, in either half — store and bundle formats are untouched and the on-disk mailbox index is unchanged, so a relay carrying pending grants keeps them across the redeploy. Recorded as the second amendment to ADR 0015 (2026-08-07), with CONTEXT.md's grant-allowlist, grant-discovery and forge entries corrected to match; the forge lost one of its four named differences from a relay, because the relay adopted it here. a5e2ffcf · dbf3dbe6…

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.