Part of cluster-wide BeaconV3 sweep: #5
Context
packages/protocol/beacon.yaml declares 2 ACVP invariants (ASPIRATIONAL — tests/acvp/ directory doesn't exist) + 1 sealed_schema path that doesn't exist yet.
The proof material for event_completeness IS implemented in src/completeness.ts (buildEnvelopeLive returns complete: "degraded" on fail, never complete: true) and exercised by tests/live-smoke.test.ts + tests/live-ownership.test.ts — but not yet bound under tests/acvp/.
Gaps
1. tests/acvp/event_completeness.test.ts (lift from live-smoke)
Invariant: The completeness envelope {as_of_block, holder_count, source, complete} accurately reflects whether the response is complete.
Test approach:
- Given a wallet with N known token balances at block B (use a fixture wallet on Berachain with stable holdings)
- Call
buildEnvelopeLive(wallet, block=B)
- Assert:
complete: true AND as_of_block >= B AND holder_count === N
- Degraded-path test: when sonar client is mocked to throw, assert
complete: "degraded" (NEVER true)
- Source of proof: lift the assertions from
tests/live-smoke.test.ts into a new tests/acvp/event_completeness.test.ts
2. tests/acvp/idempotency.test.ts
Invariant: Same wallet + block input → byte-identical response.
Test approach:
- Call
buildEnvelopeLive(wallet, block=B) twice with identical inputs
- Assert:
JSON.stringify(canonicalize(r1)) === JSON.stringify(canonicalize(r2))
- Use a JCS-canonical-JSON helper (mirror
loa-freeside/packages/beacon-schema/lib/jcs.sh pattern)
3. Externalize packages/protocol/inventory-snapshot.schema.json
Why: beacon.yaml sealed_schemas[0].path declares this file, but it doesn't exist on disk. Until externalized, freeside-cli doctor cannot recompute the sha256 hash.
Approach:
- Emit JSON Schema from the
HoldingsResponse shape in src/types.ts (Effect.Schema → JSON Schema via Schema.JSONSchema.make)
- Write to
packages/protocol/inventory-snapshot.schema.json
- Add a test:
tests/contract/inventory-snapshot-schema.test.ts that ajv2020-validates a known fixture against the emitted schema
Acceptance criteria
Part of cluster-wide BeaconV3 sweep: #5
Context
packages/protocol/beacon.yamldeclares 2 ACVP invariants (ASPIRATIONAL —tests/acvp/directory doesn't exist) + 1 sealed_schema path that doesn't exist yet.The proof material for
event_completenessIS implemented insrc/completeness.ts(buildEnvelopeLivereturnscomplete: "degraded"on fail, nevercomplete: true) and exercised bytests/live-smoke.test.ts+tests/live-ownership.test.ts— but not yet bound undertests/acvp/.Gaps
1.
tests/acvp/event_completeness.test.ts(lift from live-smoke)Invariant: The completeness envelope
{as_of_block, holder_count, source, complete}accurately reflects whether the response is complete.Test approach:
buildEnvelopeLive(wallet, block=B)complete: trueANDas_of_block >= BANDholder_count === Ncomplete: "degraded"(NEVERtrue)tests/live-smoke.test.tsinto a newtests/acvp/event_completeness.test.ts2.
tests/acvp/idempotency.test.tsInvariant: Same wallet + block input → byte-identical response.
Test approach:
buildEnvelopeLive(wallet, block=B)twice with identical inputsJSON.stringify(canonicalize(r1)) === JSON.stringify(canonicalize(r2))loa-freeside/packages/beacon-schema/lib/jcs.shpattern)3. Externalize
packages/protocol/inventory-snapshot.schema.jsonWhy: beacon.yaml
sealed_schemas[0].pathdeclares this file, but it doesn't exist on disk. Until externalized,freeside-cli doctorcannot recompute the sha256 hash.Approach:
HoldingsResponseshape insrc/types.ts(Effect.Schema → JSON Schema viaSchema.JSONSchema.make)packages/protocol/inventory-snapshot.schema.jsontests/contract/inventory-snapshot-schema.test.tsthat ajv2020-validates a known fixture against the emitted schemaAcceptance criteria
tests/acvp/event_completeness.test.tsPASSEStests/acvp/idempotency.test.tsPASSESpackages/protocol/inventory-snapshot.schema.jsonexists; structure matchesHoldingsResponseASPIRATIONALflags; remove "this file does NOT exist yet" caveat from sealed_schemasfreeside-cli doctor(when T2a ships) — beacon.yaml validates with real sha256 hashes