every.channel/evolution/proposals/ECP-0059-bootstrap-api-durable-object.md
2026-02-15 16:17:27 -05:00

1.7 KiB

ECP-0059: Bootstrap API as Durable Object (No Containers)

Status: Draft

Goal

Keep https://every.channel deployable with the smallest possible Cloudflare surface area while still supporting:

  • a global "directory" of live offers (short-lived),
  • one-shot answers for WebRTC rendezvous,
  • no secrets in-repo (use Forgejo/CI secrets),
  • minimal operational dependencies (avoid Docker/containers for deploy).

Non-Goals

  • This is not a long-term global index.
  • This is not spam-resistant.
  • This is not the eventual mesh transport (MoQ / iroh / etc).

Proposal

Replace the Cloudflare Containers-backed bootstrap API (ECP-0048) with a single Durable Object class:

  • EcApiContainer remains the binding name for compatibility, but becomes a standard Durable Object.
  • The Worker routes /api/* to a single instance name "global".

Endpoints (unchanged):

  • GET /api/health -> { ok: true }
  • GET /api/directory -> { now_ms, entries[] } (sorted by recency)
  • POST /api/announce -> { ok, ttl_ms, entry }
  • POST /api/answer -> { ok: true }
  • GET /api/answer?stream_id=... -> one-shot answer (consumed on first read)

State constraints:

  • Offers TTL clamped to [5s, 60s]
  • Answers TTL ~2m
  • Hard caps: <=200 offers, <=500 answers (prune by recency)

Rationale

Cloudflare Containers in CI adds Docker/build complexity and increases the number of moving parts. For a bootstrap rendezvous, a Durable Object is sufficient and simpler to deploy and audit.

Rollout / Reversibility

  • No UI changes required.
  • Keep existing durable object class name to avoid binding churn.
  • Reversible: we can reintroduce Containers later if justified by load/compute needs.