A three-source conformance checker for AT Protocol Personal Data Servers (spec + lexicons + reference behavior). Pre-alpha.

Firehose breadth: event field checks, cursor semantics, sequencing #5

Closed katsuricata.com
Closed opened by and assigned to katsuricata.com

Tier 2 currently has two checks: sync.firehose.commit-event-schema and sync.lifecycle.creation-event-order. Missing firehose coverage:

  • #account, #identity, #sync field-level schema checks
  • Cursor semantics: future cursor → error + close; too-old cursor → #info then replay from oldest; seq monotonicity within a connection
  • Size-limit edges (5 MB frame / 2 MB blocks / 1 MB record / 200 ops); at least the assertable producer-side ones
  • No #commit events for non-active accounts (needs lifecycle teardown; see the lifecycle-checks issue)

Observation model is settled: connect with cursor: 0 and replay the backfill window rather than racing the live stream (see docs/interop-traps.md). The harness (src/firehose.ts, collectFirehose) already supports this.

Done when: the above checks exist and pass against the oracle.

Done in 2879d36 (pushed to main).

Three new tier-2 checks, all passing against the oracle (pnpm e2e green, exit 0):

  • sync.firehose.event-schemas: field-level schema for #identity, #account, #sync. Includes the lexicon-required consistency that #sync rev/did match the signed commit block in blocks, plus the 5 MB frame and 10k sync-blocks size limits. (Probed the oracle first: the reference emits a 285-byte commit-only CAR for #sync, spec-conformant.)
  • sync.firehose.cursor-semantics: future cursor -> FutureCursor error frame + close (spec must); cursor=2^53-1 as a reference divergence; cursor=0 replay asserts strictly increasing, non-duplicated seq and replay-from-oldest.
  • sync.lifecycle.deactivation-events: deactivate -> #account{active:false, status:deactivated}; write while deactivated refused (401 AccountDeactivated, auth-layer rejection) with no #commit emitted; reactivate -> #account{active:true} + #sync. Post-deletion backfill purge is asserted as a divergence and correctly lands N/A against the reference (deleteAccount needs an emailed token).

Not probed, deliberately: per-record 1 MB / 200-ops enforcement. The write path rejects oversize records before a commit exists, so there is no producer-side firehose behavior to assert; the assertable halves (frame/blocks/ops on observed commits) were already covered by commit-event-schema.

Two undocumented reference behaviors are now in docs/interop-traps.md: deactivated-account writes fail with 401 (not 400), and activateAccount rejects any request body.

Sign up or Sign in to add to the discussion.