Files
bitgate/docs/adr/0002-capabilities-resolve-at-merge-time.md
thePR0M3TH3AN 2beb7a7bb5 feat: adapter contract, commerce proof-of-fit, and reusability docs
Proves the engine did not stay video-specific during extraction.

- application adapter contract in core (createApplicationAdapter,
  evaluateObject, collectTargets): an object names the targets that govern it
  and the strictest verdict reaching any of them wins, so denying a seller
  takes their whole catalogue down with no cascade logic in the application
- examples/commerce: a marketplace on the public API covering all ten
  proof-of-fit behaviors the plan requires, including that no core change was
  needed. One product, one snapshot, four surfaces, four different verdicts.
- README, integration guide, per-example README, CHANGELOG, four ADRs, and
  GPL-3.0-or-later LICENSE (the license was listed in Phase 1 but missing)
- checkpoints rewritten to reflect actual state and to say plainly which
  migration-plan phases belong to the consumer repos rather than here

Fixes a real gap found by the proof-of-fit: composeDecisions kept only the
first decision's evidence, so an object governed by several targets lost the
evidence that drove its verdict. Evidence now merges — counts summed,
contributor lists unioned, flags or-ed.

556 tests; lint, typecheck, and per-package type build clean.
2026-08-09 17:57:09 -04:00

1.4 KiB

ADR 0002 — Capabilities resolve at merge time

Status: accepted

Context

The reference application treated moderator status as a UI permission: an editor list gated which buttons appeared, but the resulting events carried no cryptographic authority. Anyone could publish the same event.

Revocation is the hard part. If a contribution's validity is decided when it is ingested, revoking a role later requires finding and undoing everything that actor ever contributed.

Decision

Contributions are stored as-published, keyed by (actor, kind). Effective state is derived by reduceAdminState, which resolves each actor's capabilities against the current authority state every time it runs.

Consequences

Revocation is immediate and requires no rewriting: drop the role, recompute, and that actor's entries are gone. A revoked moderator's stored contributions become inert rather than needing deletion.

Reduction cost is proportional to total contributions rather than to the change. For realistic list sizes this is far cheaper than maintaining incremental invalidation, and the store only recomputes when something actually changed.

An actor's contributions can also come back if their role is restored, which is the correct behavior for a mistaken revocation but must be understood when reasoning about "permanent" removal — permanence lives in the contribution being retracted, not in the role.