mirror of
https://github.com/PR0M3TH3AN/bitgate.git
synced 2026-10-27 08:31:00 +00:00
Renames the project and makes it as easy to adopt as BitLogin, which was the stated bar and which it did not previously meet. Rename (ADR 0005): @nostr-governance/* -> @bitgate/*, governance-* elements -> bitgate-*, createGovernanceRuntime -> createBitGate. "Governance" reads as DAO voting to this audience and named a category rather than a product; BitGate names the benefit and joins the bit- family that BitVid and BitRoad compose with. Domain types keep their names — the product is BitGate, the subject matter is still governance. The migration plan is left as written; this ADR records the change rather than rewriting history. Drop-in distribution (ADR 0006): adopting BitGate meant supplying a transport, authoring a policy, and wiring every element in JavaScript. Now: - createRelayTransport(urls) — WebSocket transport with reconnection, backoff, subscription replay, and cross-relay dedupe - policy presets (social, commerce, admin-only) addressable by name; the engine still carries no thresholds of its own - <bitgate-provider> — configuration in markup, with descendants finding the runtime through a bubbling context event rather than DOM walking, which breaks across shadow boundaries - npm run build:widget — a self-contained dist/bitgate.js That last one came from running it in a browser rather than from a test. Bare specifiers resolve in Node and vitest but not in a browser, so the widget source worked everywhere except a plain static page — the one place it exists to serve. The bundle is not committed: consumers build from reviewed source. Also found by running it: the provider's ready event fires during element upgrade, before a page that defines elements after parsing can attach a listener, so it now exposes `ready` as a promise too. Four bugs fixed along the way, three found by new tests and one by the browser: admin state stayed silent when a roster change altered capabilities but no denials; the relay transport sent every subscription twice on connect; the commerce preset computed a meaningless visibility verdict at checkout and could hide a listing from its own seller; <bitgate-status> threw on an unusable decision. 759 tests; lint, typecheck, and both builds clean.
175 lines
7.7 KiB
Markdown
175 lines
7.7 KiB
Markdown
# 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 `@bitgate/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.
|