controller: customer-claim password gate v0.122.0 (closes DRILL-day0-vm F-4/F-5)
The customer sets + owns the dashboard password via a hub-emailed one-time claim code. An unclaimed box (code hash present, no password) serves ONLY the claim page — every other route → claim page (302) or 401, so a Day-0 box is never open on the internet. A set password disables the gate (auth wins). Reset rides the same code engine (login "Elfelejtett jelszó"). Legacy-open (no password, no hash) shows a red transition banner until the hub delivers a hash. Report ACK caches the code state idempotently by generation; report carries claimed (set-only). --print-reset-code root escape hatch. Requires hub v0.50.0. Gate-coverage signature test + 4 red-proofs proven.
This commit is contained in:
@@ -1,5 +1,39 @@
|
||||
## Changelog
|
||||
|
||||
### v0.122.0 — customer-claim password gate (closes DRILL-day0-vm F-4/F-5) (2026-07-12) — MinAgent: 0.81.0
|
||||
|
||||
The customer sets + OWNS the dashboard password; the old "no password → open dashboard" is gone.
|
||||
An unclaimed box (hub-delivered claim-code hash present, no password) serves ONLY the claim page
|
||||
— every other route answers the claim page (302 → `/claim`) or `401` (API), so a Day-0 box is
|
||||
never open on the public internet (closes F-4; F-5's unauthenticated geo toggle closes with it).
|
||||
Requires the hub's v0.50.0 claim engine (code generation + email + ACK/config delivery).
|
||||
|
||||
- **`internal/web/claim.go`** — the gate + pages. `claimGateActive()` (no password + code hash +
|
||||
not claimed), `effectiveClaimCode()` (ACK-cached settings beats the config bake by generation),
|
||||
the claim page (`GET /claim`), submit (`POST /claim`: verify code → set own password → claimed
|
||||
→ consume generation → session), and "kérj új kódot / Elfelejtett jelszó" (`POST
|
||||
/claim/request-new-code` → hub `reset-request`). Code checks: bcrypt match AND generation not
|
||||
yet consumed (single-use) AND ≤ 72 h old. Per-source + global brute-force limiter (5 tries →
|
||||
15-min lockout, fake-clock tested); a lockout raises the allowlisted `claim_lockout` event.
|
||||
Pre-auth CSRF is an HMAC over `web.session_secret` (closes the CTRL-007 bare-double-submit
|
||||
weakness), min password length 12.
|
||||
- **Gate wiring** (`auth.go`, `csrf.go`, `server.go`, `cmd`): the gate sits atop `RequireAuth`; a
|
||||
SET password disables it entirely (password auth wins — claimed boxes never regress). `/claim*`
|
||||
+ `/static/*` stay reachable pre-auth (the code is the strong factor). Legacy-open (no password,
|
||||
no hash) passes through with a red transition banner (`layout.html`) until the hub delivers a
|
||||
hash. Login page gains an "Elfelejtett jelszó" link.
|
||||
- **`internal/report/claim_sync.go`** — caches the ACK's `claim` {hash, generation} into
|
||||
settings.json IDEMPOTENTLY BY GENERATION (offsite-descriptor one-way shape: newer generation
|
||||
advances; same/older/nil never rewrites, a hub outage never clears). The report carries
|
||||
`claimed` (set-only hub-side). `config.web.claim_code_*` baked by the hub gates from first boot.
|
||||
- **`internal/settings`** — `Claimed` (set-only), `ClaimCode*` cache, `ClaimConsumedGeneration`
|
||||
(single-use). **`--print-reset-code`** root escape hatch: prints a one-time local code (a
|
||||
generation above cached/baked/consumed), the same gate consumes it.
|
||||
- Tests: gate-coverage signature test (every route → claim/401, a deploy POST mutates nothing) +
|
||||
happy-path/reuse-refused/expired/lockout+window-reopen; four §10 red-proofs proven
|
||||
(mutate→FAIL→revert): gate skip-line, single-use generation (hub + controller), reset non-DoS,
|
||||
rate-limiter.
|
||||
|
||||
### v0.121.0 — backups page truth pass (dead sections removed, real Tier-3 state, SQLite-honest DB) (2026-07-12) — MinAgent: 0.81.0
|
||||
|
||||
Pure UI/data-plumbing on `/backups`; no backup-engine behavior change, no agent-API change, MinAgent
|
||||
|
||||
Reference in New Issue
Block a user