v0.76.0: campaign-#3 hardening (settings .bak recovery, restore stack_name validation, quiesce marker quarantine)
S1: corrupt settings.json recovers from .bak / safe-defaults+preserve, no crash-loop. F2: validStackName gates restore + export handlers (reject /,\,..,NUL traversal). S3: corrupt quiesce marker logged + quarantined, not silently dropped. Tests T-S1/F2/S3 + red-proofs. Agent/hub untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,26 @@
|
||||
## Changelog
|
||||
|
||||
### v0.76.0 — campaign-#3 hardening: settings recovery, restore-name validation, quiesce-marker quarantine (2026-06-22)
|
||||
|
||||
Three controller findings from chaos campaign #3, all small, all controller-side.
|
||||
|
||||
- **S1 [MEDIUM] — no more crash-loop on a corrupt `settings.json`.** `internal/settings/settings.go`:
|
||||
`save()` now writes a last-known-good `<path>.bak` **after** the primary rename succeeds (best-effort);
|
||||
`Load()` on a JSON-parse error recovers from `.bak` (re-promotes it to primary) and, failing that,
|
||||
**preserves** the corrupt file as `*.corrupt-<ts>` and starts on safe defaults — never returns the
|
||||
error that made `main.go` `Fatalf`/crash-loop. New `Settings.LoadWarning` surfaced as a dashboard
|
||||
banner. (`main.go`'s `Fatalf` stays — now only the genuine IO-unreadable path is fatal.) Recovery is
|
||||
safe: an empty `PasswordHash` falls back to `controller.yaml`, the storage registry re-discovers.
|
||||
- **F2 [MEDIUM, defense-in-depth] — validate `stack_name` against path traversal.** New
|
||||
`web/validate.go` `validStackName` (single segment; rejects `/`, `\`, `..`, NUL). Gated in
|
||||
`backupRestoreHandler` (`handlers.go`) and `apiExportStart` (`handler_export.go`) before any
|
||||
restore/export work. (Storage `where=` was already validated by `gateWhere`.)
|
||||
- **S3 [LOW] — quarantine a corrupt quiesce marker.** `quiesce/quiesce.go` `readMarker` now logs a
|
||||
`[WARN]` + renames a bad-JSON marker to `*.corrupt-<ts>` instead of silently dropping it (still
|
||||
returns "no marker" → no recovery, the correct contract).
|
||||
- Tests: T-S1a-d (settings recovery), T-F2a-c (validation + both handlers), T-S3a/b (quarantine), all
|
||||
red-proofed against the pre-fix code. Agent/hub untouched.
|
||||
|
||||
### v0.75.0 — gate userdata MkdirAll on a live mountpoint (no writes into an absent drive) (2026-06-22)
|
||||
|
||||
**Bugfix — two `MkdirAll`-into-`<drive>/userdata` sites fired without checking the drive was mounted**,
|
||||
|
||||
Reference in New Issue
Block a user