controller v0.68.0: storage lifecycle on intermediary model (H2/H3/M1/M3 + boot-id)

H2 decommission UI button (migrate / anyway); H3 one-click re-enroll of a
decommissioned drive; M1 default reassignment (auto-promote + block-if-none);
M3 migrate re-asserts 2775 setgid on userdata dirs; deterministic guest-reboot
recreate via agent boot_id (replaces the timed sample). Fixes the {path}/{where}
H1 JS bug. Non-hollow tests + companions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 19:26:02 +02:00
parent bc41acf4da
commit 42f69dadda
10 changed files with 293 additions and 46 deletions
+30
View File
@@ -1,5 +1,35 @@
## Changelog
### v0.68.0 — storage lifecycle on the intermediary model: H2/H3/M1/M3 + deterministic boot-id (2026-06-15)
Pairs with agent v0.36.0. Finishes the storage lifecycle on the new mount model.
- **Boot-id determinism (kills the 1/8 race).** `processGuestBootChange` replaces the fragile
container-uptime sample: the agent reports `guest_boot_id` (changes per guest boot, stable across a
controller-only restart), persisted in settings (`LastGuestBootID`). On a change, every deployed
drive-backed app whose drive is present and that docker brought back (`shouldRecreateOnBoot`: state not
stopped/not_deployed) is DETERMINISTICALLY recreated onto the populated path. Respects user-stop;
gate-stopped apps stay the gate's job.
- **H2 — decommission UI button** (settings.html): a "Leszerelés" button on every connected drive →
migrate-then-decommission (uses the inline target select) OR decommission-anyway (type-to-confirm the
drive name). Both modes were already server-side; the new model never touches the parent mp.
- **H3 — one-click re-enroll/reconnect.** `handleStorageReconnect` now also handles a DECOMMISSIONED
drive: clears the soft marker + schedulable, re-attaches under the parent, restarts apps (re-discovered
via `appsOnStoragePath` since decommission-anyway doesn't persist StoppedStacks). New
"Visszacsatlakoztatás" button on decommissioned drives.
- **M1 — default reassignment.** `defaultPromotionTarget` + `finalizeDecommissionWith`: decommissioning
the DEFAULT auto-promotes another schedulable drive (preferring the migrate target); if NONE exists the
decommission is BLOCKED with a clear message (never zero default).
- **M3 — userdata setgid on migrate.** The merge-walk now RE-ASSERTS 2775-setgid/gid-1000
(`EnsureUserdataDir`) on the userdata tree (`isUserdataDir`) instead of merely preserving the source
mode — so a pre-existing stale 755 target dir (e.g. import/calibre) is corrected.
- Fix: the H1 disconnect/reconnect/restart-apps JS sent `{path}` but the handler decodes `{where}`
(always 400); response keys realigned (`restarted`). New buttons use `{where}`.
Tests (non-hollow + companions): `TestShouldRecreateOnBoot` (old sample missed a healthy-stale app),
`TestDefaultPromotionTarget`, `TestIsUserdataDir`.
### v0.67.5 — gate: startup recreate waits for stack scan + handles exited apps (2026-06-15)
Adds a bounded wait for the stack scan (GetStacks is empty at NewServer time, so the recreate found no