Docs/Self-Hosting an OBEP Relay raw .md

Self-Hosting an OBEP Relay

OBEP is self-hostable: the reference relay in obep/relay-reference is a conformant relay you can run yourself. You do not need OpenErrand.

#Run the reference relay

corepack enable && pnpm install
PORT=8787 pnpm --filter @obep/relay-reference start
# ws://localhost:8787   health: http://localhost:8787/health

Front it with a TLS-terminating reverse proxy (nginx/Caddy) for wss:// in production; the reference relay speaks ws:// and trusts the proxy.

#REST surface

Endpoint Auth Purpose
GET /health none liveness
GET /relay-key none the relay's Ed25519 public key (for task-token verification)
POST /pairing-tokens Bearer <apiKey> issue a single-use pairing token for { userId }
GET /audit/:tenantId Bearer <apiKey> that tenant's audit records (cross-tenant ⇒ 403)

WebSocket (/) speaks the OBEP wire protocol (hello/pair/task.start/command/context/status).

#Provisioning

The reference relay keeps tenants, API keys, playbooks, and bindings in memory (see Registry). For production, implement the AuditStore interface against Postgres and add durable tenant/key/playbook storage — the protocol contract is unchanged. Register programmatically:

import { startRelay } from "@obep/relay-reference";
const relay = await startRelay({ port: 8787 });
relay.registry.registerTenant("tenantA", tenantPublicKeyB64);
await relay.registry.registerApiKey("tenantA", apiKey);
relay.registry.registerPlaybook(signedPlaybook);

Authoring playbooks (sign with the tenant key; the relay holds only the public key):

P=obep/cli/src/index.ts
node --import tsx $P keygen --out keys
node --import tsx $P sign examples/playbooks/portal-upload.json --key keys/tenant.key --out signed.json

#Prove your relay is conformant

Implement RelayProvisioner against your relay and run the open conformance suite — it must pass all checks (see runConformance). This is how a customer's security team verifies any relay without trusting it.

#Enterprise installs

Pin the relay endpoint via Chrome managed config (chrome.storage.managed.relayUrl) so a compromised page can't redirect the extension to a rogue relay. See Enterprise deployment for managed config and auto-pairing.