Firehose wire vectors #
What a server writes on /firehose, recorded so that a producer and a consumer
built from different repositories can each check themselves against it without
either compiling against the other.
The frame shape is not owned by either side. A server declares it as
didbot_serve::firehose::{AccountFrame, CommitFrame, IdentityFrame, Info};
the index declares its own type, in vibescrobble.com's own repository, and the
two declarations are deliberately not the same: an index that compiled
against a server's types could only read servers built from this one. These
files are what holds the two in step instead.
Each file is one frame:
{ "note": "why this case is here", "event": "commit", "data": { … } }
event is the SSE event name. data is the JSON body of that event. Those
two are the contract a producer and a consumer check themselves against;
note is prose for whoever is reading the file, and can be reworded without
changing what the vector proves.
A producer asserts that serializing its own type yields data. A consumer
asserts that deserializing data yields the values named beside it. Neither
side reads the other's assertions.
commit.json and delete.json are the two things that happen to a record.
They are separate SSE events on purpose: a consumer written before removals
were announced handles commit and nothing else, and giving a removal its own
name leaves that consumer as it was rather than handing it a frame whose
record is null. A consumer that does apply removals reads prev to check
that the record it is dropping is the one the server dropped.
identity.json, identity-no-handle.json, account-active.json,
account-deleted.json and account-deactivated.json are what
com.atproto.sync.subscribeRepos's own #identity and #account look like
once fanned onto this stream — see docs/conformance.md's #identity and
#account for the lifecycle points they go out at, and
crate::subscribe::Repos::with_firehose for the fan-out itself. All three
kinds — commit, identity and account — share this stream's one sequence
space and replay buffer, which is why every data here carries a seq a
consumer can resume from.
Two of these exist to pin a tolerance rather than a shape:
info-unknown-name.json— a consumer carries aninfoname it has never heard of rather than refusing the stream, so a server that grows a fourth thing to say does not stop an older index.commit-sparse.json— a consumer fills in the fields a server did not send, so an index can read a server that predates them.actionis one of them: absent meanswrite, which is all a server that predates removals ever sent. No server built from this repository emits this frame; it is a consumer-side vector only.