Skip to content

storage: @relayburn/server package + HttpAdapter (Phase 4 of #139) #143

@willwashburn

Description

@willwashburn

Phase 4 of #139. Depends on Phase 1 (seam) and Phase 3 (Postgres, used as the server's backing store). Phase 2 (SQLite) is also useful as the server's local-dev backing store.

Goal

Stand up a relayburn collector service so burn instances running on remote/ephemeral hosts can ship their data over HTTP instead of needing direct database credentials. Two pieces:

  1. @relayburn/server — a new package: a minimal Node HTTP service that holds one StorageAdapter instance internally and exposes its operations as a REST API.
  2. HttpAdapter — an adapter inside @relayburn/ledger that talks to that server.

Selected via RELAYBURN_STORAGE=http + RELAYBURN_SERVER_URL=https://… + RELAYBURN_API_KEY=….

@relayburn/server package

packages/server/ — minimal node:http + tiny route table (no Express/Fastify). Uses one of the durable adapters internally (Postgres in production, SQLite for local dev) by reading the same RELAYBURN_STORAGE / RELAYBURN_DATABASE_URL env vars.

  • Auth via static API-key list: RELAYBURN_API_KEYS=key1,key2,…. Authorization: Bearer <key> required on every endpoint; 401 otherwise.
  • CLI entry: relayburn server --port 8080 (wired into packages/cli/src/cli.ts).
  • Endpoints under /v1/:
    • POST /v1/turns, POST /v1/content, POST /v1/compactions, POST /v1/relationships, POST /v1/tool-result-events, POST /v1/user-turns, POST /v1/stamps — append batches; idempotent via content-addressed hashes from index-sidecar.ts.
    • GET /v1/turns?… (and parallel endpoints) — streaming NDJSON response feeding the client's queryTurns async iterable.
    • POST /v1/locks/{name}/acquire + POST /v1/locks/{name}/release — cross-host coordination via the server's underlying adapter withLock.

HttpAdapter

packages/ledger/src/adapters/http-adapter.ts — plain fetch client implementing the StorageAdapter interface.

  • Bearer-token auth from RELAYBURN_API_KEY.
  • Retries with exponential backoff on transient errors (5xx, network).
  • No client-side dedup beyond what the server's underlying adapter applies — keeps the client thin.
  • Streaming reads parse NDJSON line-by-line into the queryTurns async iterable.

Files

  • New package: packages/server/ with src/server.ts, src/routes.ts, src/auth.ts, package.json, tests.
  • New: packages/ledger/src/adapters/http-adapter.ts.
  • Modified: packages/ledger/src/adapters/factory.ts — wire up http branch.
  • Modified: packages/cli/src/cli.ts — add relayburn server subcommand.
  • Modified: root package.json — add packages/server to the workspace.

Verification

  • End-to-end: spin up relayburn server against SQLite locally; run CLI with RELAYBURN_STORAGE=http RELAYBURN_SERVER_URL=http://localhost:8080; ingest a fixture; query results from both client (over HTTP) and server (direct adapter) match exactly.
  • Auth: missing/invalid RELAYBURN_API_KEY → 401.
  • Resilience: kill the server mid-ingest, restart it — no data loss, no duplicates after retry.
  • Parameterized adapter test suite (from Phase 2) passes against the HttpAdapter pointed at an in-process server backed by SQLite.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions