hub v0.42.0: remote "Debug mód" toggle on the customer config editor
Adds a form-level debug-mode checkbox to the customer config editor so an
operator can flip the controller's Logging.Level=debug (/debug menu + verbose
log) remotely, without SSH. Form field (not raw-JSON injection) because
handleConfigUpdate rebuilds ConfigJSON from the form on every save; the
config-version bump makes the controller re-pull + self-restart next cycle.
- buildConfigJSON: debug_mode checked -> "logging":{"level":"debug"};
unchecked -> logging key omitted.
- config_form.html: "Hibakeresési mód (fejlesztői)" section + render state.
- configs_debug_test.go: form->JSON both ways; full-path survival test
(debug lands, offsite descriptor unchanged, foreign-key red-proof); render
state; red-proof exercised.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -2,36 +2,44 @@
|
||||
|
||||
> **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md).
|
||||
|
||||
## TASK — offsite SLICE 4: soft-quota + health monitoring + freeze lever — 2026-07-10 — DEPLOYED
|
||||
## TASK — hub v0.42.0: remote "Debug mód" toggle on the customer config editor — 2026-07-10
|
||||
|
||||
**Shipped (felhom.eu):** hub **v0.41.0** `fad5573` + bump `04826c9` — LIVE (Synced/Healthy, "Offsite
|
||||
checker initialized"). Pairs with controller **v0.109.1** (9201, healthy). The offsite arc's last build
|
||||
item; operator-free (Viktor ran nothing).
|
||||
**Scope:** hub only (`felhom.eu/hub`). Agent/controller unchanged — the controller already honours
|
||||
`Logging.Level=="debug"` (`isDebug()` → `/debug` menu + verbose log). Version 0.41.0 → **0.42.0**.
|
||||
|
||||
**Hub changes:**
|
||||
- **`monitor.OffsiteChecker`** — sibling of StorageFillChecker over the controller report's new `offsite`
|
||||
object: fill warn/crit at 90/95% of `quota_gb` (quota 0 = dedicated, silent) + `offsite_stale` (warning)
|
||||
for enabled+**escrowed** targets with no run >48h/never — the silently-stuck detector (recently-FAILING
|
||||
runs are `backup_failed`'s signal; pending/disabled never alert — **red-proofed**: dropping the
|
||||
escrowed-only filter made the pending customer alert → FAIL). Nil-safe on pre-v0.109 reports;
|
||||
same-second latest-report ties processed once per sweep.
|
||||
- **Freeze lever:** `Provisioner.SetOffsiteFrozen` — flips ONLY `readonly` on the exactly-1 labelled
|
||||
sub-account (SSH preserved — tested; ambiguity refuses); confirm-gated **Freeze/Unfreeze** buttons next
|
||||
to Re-issue (shared only). **MANUAL only, never automatic** — freezing also blocks prune, the customer's
|
||||
only way down from over-quota.
|
||||
### Goal
|
||||
Let an operator enable the controller's debug mode **remotely, without SSH**, from the hub's customer
|
||||
config editor — the support workflow (today: Peti's box). Enabling on any specific customer is a Viktor
|
||||
decision/click; this task does not turn it on for anyone.
|
||||
|
||||
**Live verification (free checks, real pipeline):** the controller deploy's re-apply exercised
|
||||
**key-auth-first live** (re-pinned, zero password consumed) and surfaced a real bug — the re-apply demoted
|
||||
the escrowed demo to pending + wiped runtime status → **fixed as controller v0.109.1** (re-apply preserves
|
||||
custody + status; red-proofed), demo repaired (manual confirm — truthful, same escrowed password — + a
|
||||
run). The next report carried the full offsite object (`escrowed`, 45 MB / 50 GB, fresh run); the
|
||||
**checker held it healthy (0 offsite_* events)**; the `/backups` usage bar renders
|
||||
"Tárhelykeret: 43.2 MB / 50 GB (0%)".
|
||||
### Why a form field, not raw-JSON injection
|
||||
`handleConfigUpdate` rebuilds `ConfigJSON` from the form on every save (`configs.go` → `buildConfigJSON`),
|
||||
so a foreign key poked straight into the stored JSON is dropped on the next save. The toggle is therefore
|
||||
a first-class **form field**, which by construction survives every save. The offsite descriptor survives
|
||||
independently, via the post-save provision-merge — untouched by this change.
|
||||
|
||||
**NOT live-exercised (per the STOP):** the freeze (would write-lock the demo's working offsite) and the
|
||||
100% refusal (demo is at 0.08%) — unit red-proofs cover both.
|
||||
### Changes
|
||||
- `internal/web/configs.go` — `buildConfigJSON`: `debug_mode` checked → `"logging":{"level":"debug"}`;
|
||||
unchecked → the `logging` key is omitted entirely (controller.yaml default stands; no needless `"info"`).
|
||||
- `internal/web/templates/config_form.html` — new collapsible **"Hibakeresési mód (fejlesztői)"** section
|
||||
with the `debug_mode` checkbox + a Hungarian hint (restart-next-cycle + the `/debug` URL + "turn it off
|
||||
after"). Render state parsed from `ConfigJSON`. No emoji, no BOM (consistent with the hub templates).
|
||||
- `internal/web/configs_debug_test.go` — new tests (below).
|
||||
- Untouched, as required: configgen, the offsite provision-merge, the controller. No generic raw-JSON editor.
|
||||
|
||||
**The offsite arc is now build-complete:** provisioning (S1/S2) → hardening (F1–F5, key-auth-first, wipe)
|
||||
→ auto-confirm (S3) → quota + health (S4). **NEXT:** the Peti onboarding runbook (live-exercises
|
||||
auto-confirm + F4 + fresh-provision quota end-to-end), NEW-box restore round-trip → retire the old-box
|
||||
archive.
|
||||
### Tests (non-hollow) — all green
|
||||
- `TestBuildConfigJSON_DebugMode` — checked emits `logging.level=debug`; unchecked omits the `logging` key.
|
||||
- `TestConfigUpdate_DebugSurvivesRebuild_OffsiteUntouched` — full path through `handleConfigUpdate`:
|
||||
(a) the debug key lands, (b) the offsite descriptor (`host/user/repo_path/host_fingerprint/quota_gb`) is
|
||||
unchanged across save + idempotent re-provision, and the **red-proof** that a hand-injected foreign key
|
||||
(`foo`) is gone after one save — the concrete proof of why the switch had to be a form field.
|
||||
- `TestConfigForm_DebugRenderState` — debug-on ConfigJSON renders the checkbox `checked`; plain renders it unchecked.
|
||||
- **Red-proof exercised:** with the `logging` block removed from `buildConfigJSON`, the survival + form tests fail.
|
||||
|
||||
Green gate: `go build ./... && go vet ./... && go test ./...` — all pass.
|
||||
|
||||
### Deploy + live check (operator-free)
|
||||
GitOps: build 0.42.0 on 180 → bump `manifests/hub.yaml` tag → ArgoCD sync → Synced/Healthy. Live proof on
|
||||
the **demo** customer (not Peti): edit → tick debug → save → the demo controller restarts next cycle →
|
||||
`/debug` serves → untick → save → `/debug` 404 again. See the hub CHANGELOG top entry + session notes for
|
||||
the live-validation outcome. Peti-box use (enabling on his config) is Viktor's click — not part of this task.
|
||||
|
||||
Reference in New Issue
Block a user