# 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.