did-btcr2-js

ADR 028: HTTP/REST as an Additive Transport for Aggregation

Status: Accepted

Date: 2026-04-22

Branch / PR: aggregation/http-transport

Context

The aggregation subsystem in @did-btcr2/method (see ADR 020) initially shipped with a single transport implementation: Nostr. A second transport was requested for two reasons:

  1. Operability. Nostr introduces relay pools, NIP-44 envelopes, and relay-discovery semantics. Ops and security-review staff without prior Nostr familiarity spend disproportionate effort on the transport layer vs. the protocol it carries.
  2. Ecosystem reach. Browser participants and third-party wallet apps need a transport they can consume with zero special libraries: fetch + streaming, no relay infrastructure.

The aggregation protocol itself (MuSig2 + cohort formation) is transport-agnostic: runners, state machines, and message factories only see the Transport interface. This meant a second transport could be added without disturbing protocol code.

Options considered

  1. Replace Nostr with HTTP. Smallest surface; loses Nostr entirely.
  2. Add HTTP alongside Nostr. Both transports coexist; users pick.
  3. Wait for DIDComm. DIDComm v2 is an obvious fit semantically but has no mature TypeScript implementation suitable for browsers.
  4. WebSockets instead of REST + SSE. Simpler duplex model; loses standard-REST tooling (curl, OpenAPI).

Decision

Option 2. Add HttpClientTransport and HttpServerTransport as new Transport implementations. Preserve Nostr as-is. Extend the transport factory with a discriminated-union config so callers opt into either transport per deployment.

No changes to AggregationService, AggregationParticipant, AggregationCohort, BeaconSigningSession, runner code, message factories, guards, or constants.

Consequences

Positive

Negative

Neutral

References