Skip to content

ADR-0009 — Ephemeral comparisons as in-process run windows, not container spin-ups

  • Status: accepted
  • Date: 2026-07-02
  • Domain: exhibit mechanics · security · resource sizing

Context

Both sides of both live comparisons cannot run 24/7 on this host (ADR-0006's constraint, made harder by the resize to 4 GB). Comparisons must therefore be on-demand: a viewer triggers a run, it produces numbers, it stands down. The question is what "spin up" means. The literal reading — the trigger starts and stops Docker containers — would hand a public, unauthenticated web endpoint control over the Docker API. CP8 just spent a checkpoint taking that power away from trusted admin tools via the socket proxy; giving it to an internet-facing button would undo the lab's best security decision.

Decision

Comparison services are resident but idle: the streamer container always exists, consuming near-zero CPU outside runs. A trigger opens a bounded run window inside the process — the service starts its tight loop, runs for a fixed duration (max 180 s), and returns to idle. The window deadline is stored in Redis so enforcement survives an API restart: teardown happens even if the trigger path dies mid-window. No public component can start, stop, or create containers.

Consequences

  • Attack surface of the trigger is one rate-limited application endpoint, not the Docker API.
  • Steady-state cost is a small resident container (~10 MB idle) instead of true zero — the price of not owning container lifecycle from a public app. Worth it.
  • "Ephemeral" in the exhibit copy means the workload, not the container. The public page's wording reflects this.
  • Same pattern reused for CP12's fault auto-heal (deadline in Redis, enforced server-side).

Alternatives considered

  • Docker spin-up via socket proxy — rejected: even filtered, it grants a public endpoint container-lifecycle power; one policy mistake away from an incident.
  • Always-on both sides — rejected: doesn't fit RAM, and erases the idle-cost half of the freshness-vs-cost story.
  • Scheduled runs with replayed results — rejected: the viewer no longer causes the run; the bridge from claim to observation weakens.