Controller v0.314.0 released under decision 250: floor 0.314.0 raised by CC's token at 13:11 UTC after the three test boxes
gates / gates (push) Successful in 6m45s

- 09 §3 decision 253: a restore puts the setup gate back as it was (R-1057 P2); 07 (what a per-app backup carries); 15 §6
  (Prowlarr links itself; Plex by address).
- Evidence audits/gate-restore-2026-10-15/: 9202 live proofs (R-1057, R-1058), the release (per-customer floors, Tester 1
  rc.1 -> 0.314.0 by itself, box walk, global floor, read-back), Plex fake-code check on 9201, red-proofs.
- Register: R-1023, R-1053, R-1057, R-1058 closed; R-1061 filed (P4); R-1060 narrowed; R-1052 blocked (customer creation
  is session only). STATUS, CONTEXT, the build skill's release steps, Prowlarr's website card.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-15 15:21:28 +02:00
parent bd478afe14
commit 15cb62097c
40 changed files with 945 additions and 22 deletions
@@ -886,6 +886,8 @@ both. Files written under different pins (a failed leg) make the unit `mixed`.
**[DESIGN] What a restore keeps from the app it replaces (controller v0.276.0, R-697).** The restore writes a fresh `app.yaml` from the unit — env, locked fields, and the pin from the unit's definition — but keeps the records of the app's life on this box: the household's `desired_state`, the kept pre-conversion copies (`conversion_copy`, `earlier_conversion_copies` — a restore does not remove the volume, so it must not forget it), and the ladder history (`failed_update_step`, `last_update_undone`, `last_auto_update`). Not kept: `installed_images` (what ran before, maybe another version). **A drive move is not a restore:** it changes `HDD_PATH` and nothing else (R-700 — before v0.276.0 it dropped the pin, and the syncer then gave the app the catalog's newest version at its next start). Pinned by `internal/stacks/r700_records_carried_test.go`.
**[DESIGN] The setup gate travels with the backup (controller v0.314.0, R-1057, `09` §3 decision 253).** The recovery unit's `app.yaml` carries `setup_gate:` (state, and who opened it) as it stood at the backup — the only life record the unit carries, because it decides who may reach the restored data. The restore's gate step runs inside the same write, before anything starts: closed then → closed now (the traefik gate file first, also over an installed app); open then → open; a unit with no record (made before v0.314.0) of a removed gated app → closed until the app's probe or the household's „Kész" opens it. Never open by default. An ungated app's unit bytes are unchanged (the checksum-skip guard). Code: `internal/stacks/restore_gate.go`; pinned by `restore_gate_test.go` and `internal/backup/r1057_unit_gate_test.go`.
**[DESIGN] The jump guard.** An installed version that matches no ladder entry's `from` jumps to the catalog's
current definition when a PERSON presses Update (`ladder.go`, measured live on vikunja 2.5.0, `09` §6.4 part 5);
the AUTOMATIC leg never presses it (`LegSkipOlderThanLadder`, and a template without a ladder is
@@ -948,6 +948,24 @@ its length, and both fixes cost something the household would notice — operato
**Extended the same day (operator, R-1059 = A):** the off-site and PBS-DR re-issues (they mint a household
credential for the box) are session only too; „Off-site: write" keeps the windows and freeze.
### 2026-10-15 (afternoon) — a restore puts the setup gate back as it was (operator brief, R-1057 raised to P2)
253. **A restore puts the setup gate back exactly as it was when the backup was taken.** *Operator brief 2026-10-15
(„A restored app never comes back open"); R-1057 raised to P2 by the reviewer the same day, seen by the operator.*
Narrows decision 46's restore clause („no prior record = no gate: the data comes back with its admin"), whose
assumption fails for a backup made before the household's first setup (measured on 9202: a stranger's `/ping` 200
after the restore of a Prowlarr backed up before its setup).
1. The per-app backup records the gate (`setup_gate:` in the unit's `app.yaml`: closed / open, and by whom; an app
installed before gates existed is recorded open, as it was).
2. **Closed then → closed now**, also over an installed app (the data it gets back has no admin); the gate file is
written BEFORE anything starts (decision 46 F2); the probe or „Kész, beállítottam" opens it as at install.
3. **Open then → open** (the rule's intent, unchanged); an app re-gated since (a reinstall) is opened again.
4. **No record** (a backup made before controller 0.314.0) of a REMOVED gated app → closed; the gate's loop opens it at
once if the app's own probe says the setup is done; without a probe (Plex) the household's „Kész" opens it.
**Never open by default.** An installed app restored from a no-record backup keeps its own record.
Built in controller v0.314.0 (`internal/stacks/restore_gate.go`); pinned by `restore_gate_test.go` and
`r1057_unit_gate_test.go` (ten mutations each seen failing). Proof: `audits/gate-restore-2026-10-15/9202/`.
### 2026-10-15 (07:48–08:20) — bake first; Plex through its own key; HSTS one day (recorded before the media build)
247. ~~**Bake first.** A controller version is RELEASED only when its golden is baked.~~ **REVERSED by decision 250,
@@ -141,6 +141,13 @@ directory) with that tag. Facts the link code needs:
name (`http://sonarr:8989`, `http://radarr:7878`, `prowlarrUrl http://prowlarr:9696`); both entries pass Prowlarr's own
connection test; the sync command completes (measured with zero indexers — the push of a real one waits for the
household's own). It needs no drive and no media folder. FlareSolverr only for an indexer that asks for it.
**When the link is made (controller v0.314.0, R-1058):** in every wiring run — a `media_library` app coming up, the media
restart, „Bekötés most" — and, since v0.314.0, Prowlarr's own start (`linkOnlyApps`): installed after Sonarr/Radarr it
links itself within the 60 s debounce, with no button (before: no link until a press, measured on demo-hp 9201,
`audits/prowlarr-2026-10-15/box9201/`). Idempotent: a link already there is not written again.
**Plex is called by its ADDRESS (v0.314.0, R-1060)**: Plex refuses the Host name `plex` as non-local (its claim
answered 401), so every call — claim, identity, library wiring, sessions — goes to the container's address, resolved at
each call (`mediawire.PlexURL`).
- **Call the apps with `Host: <container name>`**: once the household sets „Allowed hosts”, Sonarr/Radarr answer a bare
IP with 400 „Invalid Hostname” (measured).
- **A setting made through Transmission's RPC is lost on a power cut** (it writes `settings.json` only on a clean exit):