ab3c62e85e3b3e9a0dc2ad9fb14a1ca82a94b607sealed 76781dcf ✓The key log a verifier replays is now served over HTTP
Until today every signed document on this platform was a file. bend wrote
three of them into a directory and scripts/verify.mjs checked them with no
network and no dependencies, which is the right foundation and not yet a
platform. There is now a database behind it and three endpoints in front of it.
GET /api/v1/identities/{did-or-handle}/keys returns an account's key log —
every device it has ever enrolled or revoked, hash-linked and signed by the
identity key. It needs no authentication, because everything in it is checkable
by the person reading it, and it answers to the handle or to the did:key. The
two writes are POST /api/v1/identities, which creates an account from a signed
create_identity event, and POST /api/v1/identities/{did}/key-events, which
appends an enrollment or a revocation. Neither is authenticated by a session or
a token: the document arrives already signed by a key the platform has never
held, and that signature is the credential.
The exit criterion was a byte comparison, and it is the part worth stating
plainly: the response to that GET is byte-for-byte the file bend wrote
offline. Not the same information — the same bytes, so that a verifier handed a
file and a verifier handed a URL are running the same code over the same input.
CI proves it on every push from a cold database: three HTTP calls with curl,
one diff, and then the clean-room verifier run against the response body
rather than the file.
The server checks an incoming event by replaying the whole log through the same code a verifier runs, so it can never store a log it would later refuse — and a fork, a replay, a broken chain and a bad signature each come back with the verifier's own word for what is wrong. Signup is invite-only, by a code the operator inserts by hand, until the anti-abuse work exists.