mirror of
https://github.com/PR0M3TH3AN/bitgate.git
synced 2026-10-27 08:31:00 +00:00
feat: rename to BitGate and close the drop-in gap
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.
This commit is contained in:
1 parent
7f70a64d61
commit
adeba151b8
63 files changed
+2774
-401
No files matched your search
@@ -15,7 +15,7 @@ The core defines the *vocabulary* — target types, capabilities, effect ladders
|
||||
reason identifiers, aggregation and precedence rules — and no thresholds.
|
||||
Applications supply a `PolicyDefinition` of named profiles with category
|
||||
thresholds. The characterized reference values live in
|
||||
`@nostr-governance/bitvid-compat` as one application's profile.
|
||||
`@bitgate/bitvid-compat` as one application's profile.
|
||||
|
||||
`NEUTRAL_POLICY` is the fallback: it enforces administrative denial and applies
|
||||
no trust thresholds, so the generic engine never hides content merely because
|
||||
|
||||
@@ -11,8 +11,8 @@ meant to have no dependencies and no encoding opinions.
|
||||
|
||||
## Decision
|
||||
|
||||
`@nostr-governance/core` accepts 64-character hex only. Decoding lives in
|
||||
`@nostr-governance/nostr` (`normalizePubkeyInput`, `normalizeEventIdInput`),
|
||||
`@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
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# ADR 0005 — Rename to BitGate
|
||||
|
||||
**Status:** accepted (supersedes the repository-name decision in §5.1 of the
|
||||
migration plan)
|
||||
|
||||
## Context
|
||||
|
||||
The project shipped as `nostr-governance`, a name chosen while it was still a
|
||||
specification exercise. Three problems emerged once it became a product.
|
||||
|
||||
"Governance" means something specific and different to this audience. In Nostr
|
||||
and crypto circles it reads as DAO voting and token-weighted proposals. The
|
||||
project is a moderation and access-control policy engine; the word misdirects.
|
||||
|
||||
It named a category rather than a product. It could not be verbed, and it gave
|
||||
no signal that BitVid and BitRoad compose with it.
|
||||
|
||||
It named the mechanism rather than the benefit. The sibling project BitLogin is
|
||||
not called "Nostr Portable Auth" — it is called BitLogin, because *login* is
|
||||
what people want.
|
||||
|
||||
## Decision
|
||||
|
||||
Rename to **BitGate**, joining the existing `bit-` family (BitVid, BitRoad,
|
||||
BitLogin, BitUnlock). Gates open and close, which maps onto the allow/deny
|
||||
ladder, and "gate your app" is a natural verb.
|
||||
|
||||
- npm scope: `@nostr-governance/*` → `@bitgate/*`
|
||||
- custom elements: `governance-*` → `bitgate-*`
|
||||
- custom events: `governance:*` → `bitgate:*`
|
||||
- storage key prefix: `nostr-governance:` → `bitgate:`
|
||||
- consumer entry points: `createGovernanceRuntime` → `createBitGate`,
|
||||
`defineGovernanceElements` → `defineBitGateElements`
|
||||
|
||||
Domain vocabulary is unchanged. `GovernanceDecision`, `GovernanceTarget`, and
|
||||
`GovernanceRuntime` keep their names: the product is BitGate, the subject
|
||||
matter is still governance.
|
||||
|
||||
The migration plan and the `.hermes` execution plan are left as written. They
|
||||
record decisions as they were made; this ADR records the change rather than
|
||||
rewriting history.
|
||||
|
||||
## Consequences
|
||||
|
||||
Done at 0.1.0, unpublished, with no external consumers — the cheapest this
|
||||
could ever be. The storage key prefix changed, which would have invalidated
|
||||
caches had anything been deployed.
|
||||
|
||||
The `bit-` prefix signals membership in one author's suite, which is a mild
|
||||
cost for infrastructure intended for wider adoption. BitLogin carries the same
|
||||
cost and it has not hurt it; the composability signal is worth more, especially
|
||||
since BitLogin and BitGate are designed to be used together.
|
||||
@@ -0,0 +1,50 @@
|
||||
# ADR 0006 — Ship a built, self-contained widget
|
||||
|
||||
**Status:** accepted
|
||||
|
||||
## Context
|
||||
|
||||
BitGate was a well-factored SDK that was not droppable into a page. Adopting it
|
||||
required supplying a transport adapter, authoring a policy definition, and
|
||||
wiring every element in JavaScript. BitLogin sets a much higher bar: copy two
|
||||
files, add one script tag and one element.
|
||||
|
||||
Testing the widget in a real browser exposed a failure no unit test could
|
||||
catch. `packages/widget/src/index.js` imports `@bitgate/core` and
|
||||
`@bitgate/runtime` as bare specifiers. Node and the test runner resolve those
|
||||
through `node_modules`; a browser cannot resolve them at all. The source worked
|
||||
everywhere except the one place the widget exists to serve.
|
||||
|
||||
## Decision
|
||||
|
||||
Three pieces close the gap.
|
||||
|
||||
1. **`createRelayTransport(urls)`** — a small WebSocket transport, so nobody
|
||||
writes an adapter to get started. It speaks enough of the protocol to load
|
||||
state, subscribe, and publish; it is not a general-purpose relay client.
|
||||
|
||||
2. **Policy presets** — `social`, `commerce`, `admin-only`, addressable by name.
|
||||
The engine still carries no thresholds: these are application policies that
|
||||
happen to ship in the box, and every number in them is documented as a
|
||||
starting point.
|
||||
|
||||
3. **`<bitgate-provider>`** — configuration in markup. Descendants find the
|
||||
runtime by firing a bubbling context-request event rather than walking up
|
||||
the DOM, which would break across shadow boundaries.
|
||||
|
||||
Plus a build step (`npm run build:widget`) producing a single self-contained
|
||||
`dist/bitgate.js` via esbuild.
|
||||
|
||||
## Consequences
|
||||
|
||||
A static page needs one script tag and one element, matching BitLogin.
|
||||
|
||||
The build output is deliberately **not** committed. Consumers build from
|
||||
reviewed source and self-host the result, as BitLogin instructs, because a
|
||||
moderation widget is exactly the kind of artifact where reading the source
|
||||
matters and trusting a prebuilt minified blob does not.
|
||||
|
||||
The provider exposes `ready` as a promise as well as an event. The event fires
|
||||
during element upgrade — before a page that calls `defineBitGateElements()`
|
||||
after parsing could attach a listener — so an event alone was a race that
|
||||
silently lost. This was found by running the demo, not by a test.
|
||||
+1
-1
@@ -35,7 +35,7 @@ Trusted spam-report hide threshold: 5
|
||||
Trusted mute validity window: 60 days
|
||||
```
|
||||
|
||||
These live in `@nostr-governance/bitvid-compat` as one application's profile,
|
||||
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
|
||||
|
||||
@@ -25,7 +25,7 @@ revision was bad. Most objects want both.
|
||||
## 2. Write an adapter
|
||||
|
||||
```js
|
||||
import { createApplicationAdapter } from "@nostr-governance/core";
|
||||
import { createApplicationAdapter } from "@bitgate/core";
|
||||
|
||||
export const productAdapter = createApplicationAdapter({
|
||||
applicationId: "my-shop",
|
||||
@@ -64,7 +64,7 @@ A policy is a set of named **profiles**, one per surface. Profiles read the same
|
||||
evidence and are free to reach different conclusions.
|
||||
|
||||
```js
|
||||
import { createPolicyDefinition } from "@nostr-governance/core";
|
||||
import { createPolicyDefinition } from "@bitgate/core";
|
||||
|
||||
export const policy = createPolicyDefinition({
|
||||
id: "my-shop",
|
||||
@@ -145,13 +145,13 @@ A signer (`getPublicKey`, `signEvent`) and storage (`read`, `write`, `remove`)
|
||||
follow the same injection pattern. In-memory versions ship for testing:
|
||||
|
||||
```js
|
||||
import { createMemoryTransport, createMemoryStorage } from "@nostr-governance/runtime";
|
||||
import { createMemoryTransport, createMemoryStorage } from "@bitgate/runtime";
|
||||
```
|
||||
|
||||
## 5. Wire the pipeline
|
||||
|
||||
```js
|
||||
import { collectTargets, evaluateObject } from "@nostr-governance/core";
|
||||
import { collectTargets, evaluateObject } from "@bitgate/core";
|
||||
|
||||
runtime.setViewer(viewerPubkey); // do this FIRST — it clears viewer state
|
||||
runtime.trust.setContacts(followList); // then seed trust
|
||||
@@ -178,7 +178,7 @@ seed contacts, blocks, and overrides *after* it, never before.
|
||||
Roles are application-defined bundles over a fixed capability vocabulary:
|
||||
|
||||
```js
|
||||
import { createRoleDefinition } from "@nostr-governance/core";
|
||||
import { createRoleDefinition } from "@bitgate/core";
|
||||
|
||||
const roles = {
|
||||
listing_moderator: createRoleDefinition("listing_moderator", [
|
||||
@@ -227,7 +227,7 @@ systems are deliberately separate.
|
||||
The conformance harness takes JSON fixtures and asserts decisions:
|
||||
|
||||
```js
|
||||
import { runConformanceCase } from "@nostr-governance/testing/conformance";
|
||||
import { runConformanceCase } from "@bitgate/testing/conformance";
|
||||
|
||||
const { passed, mismatches } = runConformanceCase(fixture, policy);
|
||||
```
|
||||
|
||||
@@ -23,11 +23,11 @@ Until a lawyer-ready SPDX audit is done, treat the repository as:
|
||||
|
||||
| Package | Intention |
|
||||
| --- | --- |
|
||||
| `@nostr-governance/core` | Clean API surface + pure evaluator. Avoid BitVid names. |
|
||||
| `@nostr-governance/nostr` | Codecs. Legacy BitVid codec is provenance-sensitive. |
|
||||
| `@nostr-governance/runtime` | Transport/storage orchestration. |
|
||||
| `@nostr-governance/bitvid-compat` | Explicit BitVid-facing adapter. Most provenance-exposed. |
|
||||
| `@nostr-governance/testing` | Fakes and fixture loaders. |
|
||||
| `@bitgate/core` | Clean API surface + pure evaluator. Avoid BitVid names. |
|
||||
| `@bitgate/nostr` | Codecs. Legacy BitVid codec is provenance-sensitive. |
|
||||
| `@bitgate/runtime` | Transport/storage orchestration. |
|
||||
| `@bitgate/bitvid-compat` | Explicit BitVid-facing adapter. Most provenance-exposed. |
|
||||
| `@bitgate/testing` | Fakes and fixture loaders. |
|
||||
|
||||
## Rules
|
||||
|
||||
|
||||
Reference in new issue
Block a user