Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
3.9 KiB
REPORT — hub v0.153.0: no token sends, mints or reveals a household credential or link (2026-10-15)
09 §3 decision 252 (operator 13:20) and R-1059 „A" (same day). Design: 05 §17 (read first).
The previous report (hub v0.152.0, access tokens, deploy and CC's switch to its token):
git show 5d78569b:REPORT-hub-tokens.md.
For the operator — plain words
What I did. Your ruling (13:20, R-1055 = A) is built. No token can now:
- resend a claim code,
- create a customer,
- edit a customer (the edit can change the household's e-mail),
- create a config from a box's report.
These need you, signed in with the browser. Three were already password-only and stay so: the self-bind link, a new passphrase, binding an appliance. „Customers: write" keeps only block, unblock and geo disable.
Did it work? Yes. A new test gives a token with every permission to all seven routes. Each answers 403. The household's e-mail and passphrase stay the same, and no customer is created. I broke the rule on purpose twice; the test failed both times. All hub tests pass.
Off-site (R-1059 = A, same day). No token can re-issue a household's off-site password or PBS-DR token either. „Off-site: write" keeps the windows and freeze.
Is it live? Yes, since 13:39. With CC's token, for a customer that does not exist, all six routes answered „403 session only" (the off-site re-issue too, although the token holds „Off-site: write").
What you do now.
Nothing for this. Still open from before: change the hub password and delete the HUB_PW line.
The Customers-write routes, checked one by one (hub/internal/web/routes.go)
| route | now | reason |
|---|---|---|
POST /configs/{id}/claim-resend |
session only | sends a fresh claim code to the household's e-mail |
POST /configs/{id}/edit |
session only | can change the household's e-mail; a new e-mail auto-mails the self-bind link |
POST /configs/new |
session only | mints the owner passphrase and controller API key; takes the e-mail; mails the self-bind link |
POST /customers/{id}/create-config |
session only | mints the owner passphrase and controller API key |
POST /customers/{id}/selfbind-link |
session only (since v0.152.0) | mints and mails a self-bind capability link |
POST /configs/{id}/regen-password |
session only (since v0.152.0) | mints a new owner passphrase |
POST /appliances/{id}/bind |
session only (since v0.152.0) | delivers the household's passphrase to the box that asks |
POST /configs/{id}/offsite-reissue |
session only (R-1059) | resets the household's off-site password, stages a fresh one-time secret for the box |
POST /configs/{id}/pbsdr-reissue |
session only (R-1059) | re-keys the household's PBS-DR token, stages a fresh one-time secret for the box |
POST /customers/{id}/block, /unblock, /geo/disable |
customers:write |
no credential, link or e-mail |
The GET forms (/configs/new, /configs/{id}/edit) stay customers:read: they show no passphrase or key (checked in
the templates).
Proof
- Test
TestToken_CredentialAndLinkRoutesAreSessionOnly(hub/internal/web/tokens_test.go). - Red-proofs: claim-resend put back in the group → the handler was reached (502, no claim engine in the test);
edit put back → 200; offsite-reissue put back → the handler was reached (502). Files:
documentation/audits/hub-tokens-2026-10-15/red-proof/13-claim-resend.txt,14-config-edit.txt,15-offsite-reissue.txt. go build ./... && go vet ./... && go test ./...inhub/→ rc 0.
Records
09 §3 decision 252; 05 §17.2, §17.3, §17.5; hub CHANGELOG v0.153.0; STATUS.
Register: before 157 · after 156 · opened 1 (R-1059, off-site re-issue) · closed 2 (R-1055, R-1059).
Teardown
Machine and host: nothing provisioned. Hub: v0.153.0 deployed (manifest 1dc1a08); live probes used a customer id
that does not exist, so a broken guard could change nothing real. Evidence: audits/hub-tokens-2026-10-15/C153-live.txt.