# Immutable backend releases — request

**Owner-visible evidence first:** the installed collector unit resolves through a state-owned immutable
`releases/<full-sha>` artifact rather than the mutable deploy checkout. Its authenticated `/health`
response names that exact SHA. An injected bad candidate restores the prior `current` target and prior
healthy process through one shared activation seam.

## Delivery checkpoints

Each checkpoint lands, deploys, and receives installed proof before the next starts.

1. **Collector:** add the shared backend release/activation seam, stage a self-contained collector
   artifact, atomically activate it with typed SHA readiness, and prove rollback plus the permanent
   fd-3 front door.
2. **Controller:** stage and activate a self-contained controller artifact through the same seam; add
   exact-SHA health identity and rollback proof.
3. **Botmaster proxy and Actions Gateway:** move their mutable script/dist runtimes to independently
   activatable releases, preserving their credential and authenticated readiness contracts.
4. Consolidate pruning, degraded post-activation tripwires, and installed per-component rollback
   evidence. Kanboard already owns an immutable plugin release/current/previous seam and is verified
   against the shared contract rather than rebuilt under a second layout.

## Shared contract

- Runtime artifacts live under `${XDG_STATE_HOME:-$HOME/.local/state}/overdeck/backend/<component>/`
  with immutable `releases/<full-sha>` directories and atomic relative `current`/`previous` symlinks.
- A candidate is complete and read-only before activation. Runtime dependencies are inside the
  candidate; no dependency symlink may escape it or point at the deploy clone.
- Activation serializes per component, records the prior target, switches `current`, restarts only the
  declared service, and verifies typed health plus exact full SHA.
- Candidate restart or verification failure restores the old symlink and unit state, restarts the old
  release, and verifies it before returning failure. A failed rollback is named separately and never
  reported as restored.
- First migration stages a bootstrap artifact before switching the installed unit; no service loses its
  currently runnable fallback merely because it has not used this release layout before.
- Component receipts publish only after this activation contract succeeds. The global stamp remains
  the whole-run/request acknowledgement boundary.
- Missing/malformed identities, dangling links, mutable candidates, wrong component/SHA manifests,
  or dependencies escaping the candidate fail closed before activation.
- Post-success observability refresh/notification failures report degraded state without rolling back
  or retriggering already-proved components; delivery/readiness/identity failures remain terminal.

## Collector checkpoint acceptance

- Focused tests prove stage validation, atomic activation, exact-SHA readiness, failed-candidate
  rollback, failed-rollback classification, symlink/path refusal, and serialization. Shared pruning
  lands at checkpoint 4 after every backend uses this release contract.
- Collector tests prove `/health` emits the configured exact deployment SHA and refuses malformed
  deployment identity at startup.
- Deployment failure injection proves a rejected collector candidate leaves the prior `current` target
  and healthy PID serving through the permanent front door.
- Installed evidence records target SHA, resolved runtime path, read-only artifact state, authenticated
  health identity, front-door HTTP 200, and rollback/current/PID results.
