docs: customer-claim arc — REPORT/CONTEXT, G9 supersede, tester-agreement claim step, day0 D.3/D.4 gate, drill F-4/F-5 RESOLVED
Claude-Session: https://claude.ai/code/session_01NptTCFtu7dz2Ru89qHRagN
This commit is contained in:
@@ -2,66 +2,37 @@
|
||||
|
||||
> **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).
|
||||
|
||||
## Hub v0.49.0 — Edit tab merge (edit-a), scoped auto-refresh, + two riders — 2026-07-12
|
||||
## Hub v0.50.0 — customer-claim password arc (closes DRILL-day0-vm F-4/F-5) — 2026-07-12
|
||||
|
||||
**⚠ VERSION NOTE (deviation from the spec):** the task targeted **v0.48.0**, but hub v0.48.0
|
||||
(`app_start_failed` allowlist, CAMPAIGN-3 Task D) had **already shipped and was the live manifest
|
||||
tag** when this train started. A published tag is never re-pointed (pinned-version discipline), so
|
||||
this train shipped as **v0.49.0**. Everything else is per spec.
|
||||
Hub half of the customer-owned dashboard-password gate (controller v0.122.0 is the other half).
|
||||
The customer sets + owns the password via a one-time claim code the hub emails to the registered
|
||||
address; the hub stores only `bcrypt(code)`. **DEPLOYED: `felhom-hub:0.50.0` live on k3s (ArgoCD
|
||||
synced/healthy, `Listening on :8080` at 18:47 CEST).**
|
||||
|
||||
### Baseline / commits
|
||||
### What shipped
|
||||
|
||||
- Baseline: `3e949bc` (spec said `0ed87f5`; the one extra commit was docs-only, `git diff 0ed87f5..3e949bc -- hub/` empty — no hub code drift).
|
||||
- `e740147` — Part 1: `config_form_body` sub-template + `configFormData` builder (behavior-neutral).
|
||||
- `2e03de1` — Part 2: Edit tab merge, danger zone, header cleanup, 302, redirect anchors, server-side required fields, Group A/B tests.
|
||||
- `1d94b1a` — Parts 3+4: scoped auto-refresh, style.css cache-bust (all 11 templates), CLAUDE.md `git add -A` ban, Group C/D tests.
|
||||
- `b1ab0ea` — Part 5: CHANGELOG v0.49.0, REUSE.md rows, CONTEXT.md, `manifests/hub.yaml` → 0.49.0.
|
||||
- **`internal/claim`** — the code engine: `EnsureIssued` (idempotent Day-0/live-box issue+email),
|
||||
`Resend` (operator rotate), `RequestReset` (controller-forwarded, 3/day cap), `MarkClaimed`
|
||||
(set-only + one confirmation email). Plaintext code exists ONLY inside the email send.
|
||||
- **`store.customer_claims`** — `RotateClaimCode` (generation bump = single active code; PRESERVES
|
||||
`claimed_at`), `GetClaim`, `MarkClaimed` (set-only), `BumpResetCount`.
|
||||
- **Delivery**: `GET /api/v1/config/{id}` issues the first code + bakes `web.claim_code_*` into the
|
||||
generated controller.yaml; the report ACK serves `claim {code_hash, generation, issued_at}`
|
||||
(allowlisted) + ingests `claimed` (set-only); `POST /api/v1/claim/reset-request` (self-scoped).
|
||||
- **UI**: customer-page Setup tab claim chip + "Kód újraküldése" (`POST /configs/{id}/claim-resend`).
|
||||
- **Emails**: three Hungarian templates (claim / reset / claimed) via the notify dispatcher.
|
||||
- 15 tests (engine, ACK/config, UI); red-proofs for the generation bump + reset-non-DoS proven.
|
||||
|
||||
### Files touched
|
||||
### Live validation
|
||||
|
||||
`hub/internal/web/{configs.go, pbsdr.go}`, `hub/internal/web/templates/{config_form.html, config_form_body.html(new), customer_unified.html, +9 templates (cache-bust line only)}`, tests `{customer_edit_tab_test.go(new), refresh_cachebust_test.go(new), customer_tabs_test.go, pbsdr_test.go}`, docs `{hub/CHANGELOG.md, REUSE.md, CONTEXT.md, CLAUDE.md, REPORT.md}`, `manifests/hub.yaml`.
|
||||
Drill box demo-vm-felhom: on the first report after hub 0.50.0 + controller 0.122.0, the hub issued
|
||||
+ emailed the claim code to the registered address and the ACK delivered the hash — the controller
|
||||
gate flipped ON (proven via the real Cloudflare edge: `/` → 302 claim page, `/api` → 401). Observed:
|
||||
the hub issues a code for EVERY reporting managed customer on first report (peti + demo also received
|
||||
emails) — benign, since a pre-v0.122 controller ignores the ACK claim field and has no gate.
|
||||
|
||||
### Test results (all green: `go build ./... && go vet ./... && go test ./...` per commit)
|
||||
### Version note
|
||||
|
||||
- web package: **54 tests** (43 before → +11 new: Group A ×2, Group B ×3 + 7-case anchor table, Group C ×1, Group D ×1); full repo 13 packages ok.
|
||||
- **Group A** — Edit panel renders form (`action=/configs/c1/edit`) + Controller Update + Geo + Danger zone; forms are siblings (no `<form` inside the config form's extent); stored overrides populate inputs; header has no edit link; Block/Delete **count == 1** page-wide; blocked customer → Unblock.
|
||||
- **Group B** — B1: GET `/configs/{id}/edit` → 302 `/customers/{id}#tab=edit` (unknown id still 404). B2: `/configs/new` chrome + create round-trip unchanged. B3: invalid update → 200 standalone re-render, error shown, **submitted values preserved, stored values absent, nothing saved**. B4/B5: anchor table — update/block/unblock/offsite-reissue/offsite-freeze → `#tab=edit`, regen-password → `#tab=setup`, delete → `/configs?flash=deleted` (pbsdr-reissue also anchored → `#tab=edit`; same surface, noted as a spec+1).
|
||||
- **Group C** — `data-live-tabs="overview,applications,events,host"` on the nav; script pins: `getAttribute('data-live-tabs')`, delegated `input`/`change` dirty listeners, `settings→edit` alias ×2 (tabs + refresh scripts), `(paused)` hint element, 60000/`hub_auto_refresh`/toggle survivors.
|
||||
- **Group D** — six rendered pages carry `/style.css?v=test` and no bare `/style.css"`.
|
||||
|
||||
### Red-proofs (all three ran mutate → FAIL → revert → green)
|
||||
|
||||
1. **B3 typed-values**: error path switched to `nil` overrides → "SUBMITTED value lost / stored value rendered" → FAIL ✓.
|
||||
2. **Header count**: old header Block/Delete restored → count = 2 → FAIL ✓ (Contains alone would have passed).
|
||||
3. **Cache-bust**: `offsite.html` reverted to bare link → both assertions FAIL ✓.
|
||||
|
||||
### Deploy (GitOps)
|
||||
|
||||
- Image `gitea.dooplex.hu/admin/felhom-hub:0.49.0` built+pushed on 180.
|
||||
- ArgoCD hard-refresh → sync: `sync=Synced`, rollout ok, pod image = `felhom-hub:0.49.0`, clean startup log (checkers seeded, `Listening on :8080`) at 17:40:50 CEST.
|
||||
|
||||
### Live validation — DONE (Viktor logged in; claude-in-chrome on hub.felhom.eu, demo-felhom)
|
||||
|
||||
1. **Edit tab renders the merged surface** — populated form (ID readonly, name/domain/email, CF tokens), Edit active in the nav, `(paused)` hint shown (Edit is non-live). ✓
|
||||
2. **Legacy alias** — `#tab=settings` activates the Edit tab (panel + nav highlight). ✓
|
||||
3. **Hint logic** — `(paused)` inline on Edit and while dirty; `display:none` on Overview. ✓
|
||||
4. **Dirty blocks reload** — typed one char into Display Name (15:49:03Z, hint on); at 15:50:46Z (103 s later) the JS window-marker and the typed char were both still present → **no reload**. Field restored via Backspace afterwards. ✓
|
||||
5. **Live tab reloads** — after a fresh load on `#tab=overview` (toggle on, not dirty), the window-marker was gone within ~90 s → the 60 s auto-reload fired; the hash kept Overview active. ✓
|
||||
6. **No-op save** — Save Changes with zero edits → 303 → `?flash=updated#tab=edit`, "Configuration updated." flash, Edit tab active, values intact (offsite/PBS re-apply idempotent as designed). ✓
|
||||
7. **Cache-bust** — hard reload: `GET /style.css?v=0.49.0` → 200 in the network log; the DOM link href matches. ✓
|
||||
|
||||
**Spec-wording caveat:** §13's "clear it → reload resumes next tick" is not how the shipped (and
|
||||
spec-Part-3-mandated) never-reset dirty flag behaves — once dirty, auto-refresh stays paused until
|
||||
the next full page load (manual reload, navigation, or the save redirect), which then re-arms it
|
||||
(validated as probe 5). Clearing the typed character alone does not resume.
|
||||
|
||||
**NOT live-validated** (unit tests only, by design/STOP): Block/Delete flows, the validation-error
|
||||
re-render (no live invalid submit against demo-felhom).
|
||||
|
||||
### Observations (candidates, not done)
|
||||
|
||||
- Customer delete still uses `confirm()` (relocated as-is) — **type-to-confirm retrofit** is the known follow-up.
|
||||
- The customer-keyed report lookup → cluster-mode arc (pre-existing note) unchanged.
|
||||
- `handleConfigUpdate` had NO validation-error path before this task (the spec described it as existing); the required-fields check (Display Name + Domain, the form's `required` twins) was added to give B3 its trigger — `pbsdr_test.postUpdate` amended to supply them.
|
||||
- Workspace-root `E:\git\CLAUDE.md` and the other repos' CLAUDE.md files still carry `git add -A` snippets — flag for their own sessions (out of scope here, per spec).
|
||||
- The hub operator password gate means browser validation always needs a Viktor-logged-in session; consider a read-only CC credential if live UI validation should become routine.
|
||||
Hub was at v0.49.0; this is v0.50.0. Controller v0.122.0 committed + image built. The **floor raise
|
||||
to 0.122.0 is the operator's supervised LAST step** (after the drill/demo claim validation) — a
|
||||
gated controller must never reach a box before its hub can deliver the code hash.
|
||||
|
||||
Reference in New Issue
Block a user