# Checkpoints Scope note: this repository is the SDK. Migration-plan Phases 6–11 (BitVid shadow mode, cutovers, and duplicate removal) modify the consumer repositories and are tracked there, not here. ## Checkpoint 0 — Repo skeleton (completed) Delivered: npm workspaces monorepo, Node 22 + ESM, Vitest, JSDoc typecheck, GitHub Actions CI, reference import guard, provenance docs. Later additions: GPL-3.0-or-later `LICENSE`, `CHANGELOG.md`, architecture decision records under `docs/adr/`, and a working per-package type build. The `types` fields previously pointed at paths the build never produced, so consumers received no declarations; declarations now emit into each package. ## Checkpoint 1 — Characterization corpus (completed) Delivered: - 34 fixtures under `fixtures/bitvid/cases/`, generated by `scripts/build-characterization-corpus.mjs` - conformance harness (`packages/testing/src/conformance.js`) that builds a snapshot, evaluates it, and diffs against a partial expectation - conformance suite (`tests/conformance/bitvid-fixtures.test.js`) asserting every required behavior, determinism, and input immutability Characterized values, read from the pinned reference commit and cross-checked against the migration plan's baseline section: ```text Trusted report blur threshold: 3 Trusted report autoplay threshold: 3 Trusted mute hide threshold: 20 Trusted spam-report hide threshold: 5 Trusted mute validity window: 60 days ``` These live in `@nostr-governance/bitvid-compat` as one application's profile, not as engine defaults. Provenance: fixtures are authored from the reference source and its documented configuration, not captured from a live relay. They pin the behavior the extraction must reproduce; they are not a recording of production traffic. ## Checkpoint 2 — Pure core (completed) Delivered: identifiers, targets, authority, administrative-state reduction, reasons, evidence, policy engine, fingerprints, evaluator, adapter contract. Acceptance: - identical snapshots produce identical decisions (asserted per fixture) - evaluation performs no I/O and reads an injected clock - evaluation mutates no input (asserted per fixture) - the core imports no browser globals and has no dependencies - the core contains no application-specific terms or thresholds ## Checkpoint 3 — Nostr codecs (completed) Delivered: bech32/NIP-19 (verified against the NIP-19 test vector), canonical v1 on `kind:30078`, NIP-56 reports, NIP-51 mute lists, legacy administrative lists covering all five migration stages, replaceable selection with a deterministic same-timestamp tiebreak, injected signature verification. ## Checkpoint 4 — Runtime stores (completed) Delivered: `GovernanceAdminStore`, `TrustGraphStore`, `ReportStore`, `TrustedMuteStore`, `PolicyStore`, `OverrideStore`, `GovernanceRuntime`. Acceptance: injected transport, storage, and clock; change-only emission; viewer switching clears viewer-scoped state while keeping operator seeds; subscriptions close on destroy; report subscriptions are chunked (200 per filter) rather than opened per target; author evidence is queryable in batches; expired mute lists prune against the injected clock. ### Correction An earlier revision of this file claimed storage acceptance that was not met: storage was injected and then never used, so nothing persisted or hydrated and the characterized cache-fallback behavior existed only at the reduction level. Closed in Checkpoint 8. ## Checkpoint 5 — Public commands (completed) Delivered: contribution, role, policy, community-source, report, and override commands with stable error codes. Acceptance: every command checks capability locally before the signer is invoked, so an unauthorized actor cannot produce a signed mutation; revoked actors' contributions stop affecting effective state; protected actors are refused at the command boundary; first relay acceptance completes the command while remaining relay results stay observable. ## Checkpoint 6 — Reusability proof (completed) Delivered: `examples/commerce`, a marketplace built entirely on the public API, covering the ten proof-of-fit behaviors the migration plan requires — including that no core change was needed. Plus `README.md`, `docs/integration-guide.md`, and `examples/commerce/README.md`. ## Checkpoint 7 — Performance and security fixtures (completed) Delivered: - `tests/performance/large-feed.test.js` — 5,000 targets, 500 authors, 100 trusted muters per author, multiple report categories and administrative contributors, viewer switching, and roster changes - `tests/security/requirements.test.js` — one case per enumerated security requirement testable at this layer Acceptance: - `evaluateMany(5,000)` performs no network access - report subscriptions are chunked, never one per card - updating one report invalidates only that target's decisions - updating one author's mute state invalidates only that author's targets - changing policy, roster, or viewer invalidates everything - destroy leaves no subscriptions or cached decisions This fixture found a real defect: evaluation was quadratic in state size, because the snapshot and its fingerprint were rebuilt per target. A 5,000-target pass took ~47 seconds. After memoizing both, the same pass takes ~85ms cold and ~6ms warm. Requirements 15 and 16 (never export signer secrets, avoid shared moderator keys) are properties of the injected signer and of operational practice rather than of this code; the root-authorized contributor model is what removes the need for a shared moderator key. ## Checkpoint 8 — Runtime wiring (completed) Closes the gaps between interfaces that existed and pipelines that used them. Delivered: - **Storage**: `persist()` / `hydrate()`, hydrate-before-query on load, and last-known-good state retained with a `stale` flag when relays fail. Cache keys are namespaced by root identity — not by the full roster, which would rotate the key every time a moderator was added. - **Signature verification** wired into the load path through an injected verifier, with rejected counts in diagnostics and an explicit `signatureVerification: enabled|disabled` readout. - **Trusted mute-list subscriptions** by author, chunked. Without this the trusted-mute store never populated in a real deployment. - **Community source resolution**: curator lists are fetched and merged with a source marker, still subject to the curator's capabilities. - **Root policy application**: policy documents are now applied rather than merely announced, accepted only from the root, and a malformed document leaves the working policy in place. - **Import/export** (§10.14) exporting contributions rather than conclusions, so an import re-derives effective state against the importing roster. - **Capability queries** (§10.8): `can()`, `capabilitiesOf()`, `viewerCapabilities()`. Design note: the root administrator is now a constructor option, because it is deployment configuration rather than discovered state. Hydration could not otherwise find its own cache — the key derives from the root fingerprint the cache itself would have had to supply. ## Status CI gates green: reference guard, typecheck, 634 tests, per-package type build. Typecheck and the declaration build both pass from a cold checkout with no `dist/` present. ## Not done here Migration-plan Phases 6–11 operate on BitVid and BitRoad: - Phase 6 — BitVid compatibility facade and shadow mode - Phase 7 — cut over BitVid administrative state - Phase 8 — cut over BitVid reports and trust - Phase 9 — cut over BitVid policy - Phase 10 — validate through BitRoad itself - Phase 11 — remove duplicated BitVid logic The commerce example stands in for Phase 10's API-shape validation without touching the BitRoad repository.