hub v0.66.0 + ISO v1.20.0: customer self-bind (R-27 slice 1)
Let a customer bind their own freshly-installed appliance without the operator: operator "Send self-bind link" mints a 7-day tokenized capability link, emailed (Hungarian, sibling sender) to the customer, who opens a public /bind/<token> page and proves two factors — the console pairing code shown on the box screen + their retrieval passphrase — and the hub stages the bind via the same BindAppliance (provenance customer_selfbind). The box's ~30s appliance poll delivers. Viktor's three rulings verbatim: console pairing code (no appliance list ever rendered), operator-sent tokenized link, 5-attempt lockout -> "call support". Wrong code == wrong passphrase (one generic failure, no oracle, both factors compared unconditionally); expiry falls back to operator-bind unchanged. THE TRAP: one public prefix /bind/, exempt from auth+CSRF at both /login gate sites via a single isPublicBindPath predicate (tight trailing-slash match; ServeMux ..-cleans; handler rejects '/' in token). 9 tests (Scenarios A-F + F1/F2); 4 red-proofs verified red-then-green (lockout, oracle, widened-prefix, single-active). GC verdict: no appliance GC -> the 7-day TTL stands alone. Controller/agent untouched; R-27b deferred. Green: full hub build/vet/test (17 ok) + bash -n + hub confirm gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qDiBqKKQ5vPB5fXBqu7Kp
This commit is contained in:
+21
@@ -3,6 +3,27 @@
|
||||
> Created with the REUSE.md rollout (2026-07-03). Authoritative history: `hub/CHANGELOG.md` (hub),
|
||||
> `website/CHANGELOG.md`, `scripts/CHANGELOG.md`; end-of-task detail in `REPORT.md`.
|
||||
|
||||
- **2026-07-17 — CUSTOMER SELF-BIND shipped (hub v0.66.0 + ISO scripts v1.20.0, R-27 slice 1).** A
|
||||
customer binds their OWN freshly-installed appliance without the operator. Operator clicks **"Send
|
||||
self-bind link"** on the customer Setup tab → hub mints a **7-day tokenized capability link** →
|
||||
emails it (Hungarian, sibling sender, NOT via the claim engine) → customer opens the **public,
|
||||
Hungarian `/bind/<token>`** page (no login — the URL token IS the auth) → enters the **console
|
||||
pairing code** (shown on the box screen) + their **retrieval passphrase** → hub stages the bind via
|
||||
the same `BindAppliance` (provenance `customer_selfbind`) → the box's ~30 s appliance poll delivers.
|
||||
**Viktor's three rulings, verbatim:** (a) *"only their own visible"* → console pairing code, **no
|
||||
appliance list ever rendered**; (b) *first-box entry* → operator-sent tokenized capability link over
|
||||
Hungarian email; (c) *lockout after 5 failed attempts* → token locks, "call support". Wrong code and
|
||||
wrong passphrase = **one identical generic failure** (no oracle; both factors compared
|
||||
unconditionally); expiry falls back to operator-bind unchanged. **THE TRAP (§9.2):** one public
|
||||
prefix `/bind/`, exempted from auth+CSRF at both `/login` gate sites via a single `isPublicBindPath`
|
||||
predicate (tight trailing-slash match; ServeMux `..`-cleans; handler rejects `/` in the token) — 4
|
||||
red-proofs verified red-then-green (lockout→C1, oracle→B, widened-prefix→E, single-active→C4).
|
||||
**GC verdict:** no appliance-staleness GC exists (`applianceStaleAfter` is a display badge only) → the
|
||||
7-day token TTL stands alone, single-active-per-customer, no reaper needed. **Controller/agent
|
||||
untouched; R-27b (controller second-box dismissable prompt) DEFERRED, mechanism sketched.** Green:
|
||||
full hub `build/vet/test` (17 ok, +9 self-bind tests) + `bash -n`. **LIVE validation pending deploy
|
||||
(this session).** See REPORT.md.
|
||||
|
||||
- **2026-07-17 — PBS DR STORAGE VISIBILITY + Offsite tab split + dual gauges shipped (hub v0.65.0 +
|
||||
tenantsync v1.2.0, R-5), LIVE.** Scoping correction (Viktor): "restic box" and "PBS box" are NOT two
|
||||
Hetzner Storage Boxes — restic = subaccounts on the shared Hetzner box (Hetzner API, v0.64.0); **PBS DR =
|
||||
|
||||
Reference in New Issue
Block a user