Changes touching this path
- day 0: loot hosts loot
f4c30e75 · dbf3dbe6… - evidence: crew minted and verified (#86)
1fada823 · dbf3dbe6…diff - normalize working tree to LF: byte-stable co-located bridge (.gitattributes -text)
e58fdda6 · dbf3dbe6…diff - the relay's grant mailbox authorizes before it parses, and a read addresses only the caller's own (#621)
4b349b72 · dbf3dbe6…diff - 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…diff - a push deposits this identity's own keys: a standing self-grant carries Restricted custody to the second machine, so a same-identity clone opens what it authored (#980)
684f37cb · dbf3dbe6…diff - the docs gate themselves: a land refuses a link that resolves to nothing, five rotted ADR cross-links are fixed, every amended ADR warns in its status, and the artifact sweep retires with its producer
586e3260 · dbf3dbe6…diff - a relay with a push allowlist now gates its reads on it too: every relay read route was unauthenticated while every bundle carries the key for every Internal object (ADR 0011), so an allowlisted relay.millerbyte.com served this private repo to a stranger key in plaintext (#2388). a route is a read when its answer comes from the store, and the store now sits behind Hold, whose only doors are a gated read and a gated write, with the router built from one match over Route that has no wildcard, so a later route cannot answer from the store ungated; the reads today are /negotiate, /offer, /fetch, /wants and /haves, /info stays the one open probe, and the grant lane is unchanged. with no list a relay stays open and unsigned, and loot serve and loot-relayd now warn at startup that anyone who can reach it can clone everything, Internal content included. /info advertises authenticated_reads and a client signs its reads iff it is advertised, so a new client reads an old relay unsigned and an old client gets a 401 naming the upgrade; loot seek records the posture and the SDK signs its reads the same way. no format constant moves. ADR 0011 and 0015 amendments, CONTEXT.md, the forge spec, sdk README and the site cli, guides and concepts pages say it. red under mutation, counts read: gate never on (the stranger clone succeeds), gate admitting any valid key, the 401 without the upgrade wording, /haves filed as open, /info not advertising, client never signs, client signing whenever a list exists, the startup warning dropped, the SDK never signing; each restored to green. workspace suite 4539 passed over 141 binaries, 13 ignored; SDK 145 of 145; site gate green (777). owes a release before loot serve users get it; the live relay stays stopped (#2389)
f6b5ecc7 · 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.