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.
982 B
ADR 0004 — The core is hex-only
Status: accepted
Context
Administrative lists in the wild contain both hex pubkeys and npub strings,
and the reference implementation normalized them everywhere it touched them.
Doing the same in the core would mean bech32 decoding in a package that is
meant to have no dependencies and no encoding opinions.
Decision
@bitgate/core accepts 64-character hex only. Decoding lives in
@bitgate/nostr (normalizePubkeyInput, normalizeEventIdInput),
and codecs normalize at ingest, so the core only ever sees hex.
Consequences
The core stays dependency-free and runs unchanged in Node and the browser.
The trade-off is a real footgun: normalizePubkey returns "" for a valid
npub rather than throwing. Callers that hand user input straight to the core
will silently get nothing. Anything accepting operator or user input must
normalize through the codec package first — this is called out in the
integration guide.