CC uses its hub token: live C3 proof (floor no-op 303 floor_set, vouch 403, session-only 403); R-1051 closed; skill floor step + prune script on the token; STATUS: change the hub password
gates / gates (push) Successful in 6m33s
gates / gates (push) Successful in 6m33s
Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
This commit is contained in:
@@ -464,7 +464,7 @@ cannot add a custom header without a CORS preflight, which the hub never answers
|
||||
the route switch, so it covers every route at once (38 state-changing routes + an unknown path in
|
||||
`r135_csrf_test.go`); `/login` and the public `/bind/<token>` stay exempt (no operator session to ride; the bind token
|
||||
is the capability). The other choice — dropping browser-usable Basic auth entirely — was not taken: CC's headless runs
|
||||
and the runbooks drive the hub with Basic auth, and the header costs them one flag.
|
||||
and the runbooks drive the hub with Basic auth, and the header costs them one flag. *Since v0.152.0 CC's scripts use a scoped token instead (§17); Basic stays for the operator's own scripts.*
|
||||
|
||||
### 16.2 Secrets at rest in `hub.db` (R-133, R-821)
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
1 floor no-op save: (303, '/configuration?flash=floor_set')
|
||||
2 vouch attempt: (403, '', 'Forbidden: missing scope vouch:write')
|
||||
3 session-only (customer page): (403, '', 'Forbidden: session only — never by a token')
|
||||
3b session-only (reveal): (403, '', 'Forbidden: session only — never by a token')
|
||||
4 read Configuration: 200
|
||||
DB ('min_controller_version', '0.313.0')
|
||||
DB ('min_controller_version_declared_min_agent', '0.313.0=0.155.0')
|
||||
DB token ('cc-releases', '2026-10-15T11:07:33Z', '10.42.0.1')
|
||||
2026/10/15 13:06:06 [INFO] access token "cc-releases" created from 192.168.0.110: scopes overview:read,floor:read,floor:write,customers:read,hosts:read,offsite:read,offsite:write,os:read,os:write, expires 2027-04-13T11:06:06Z
|
||||
2026/10/15 13:07:32 [INFO] Global controller-version floor set to "0.313.0" (declared MinAgent "0.155.0")
|
||||
2026/10/15 13:07:32 [WARN] global floor 0.313.0 does NOT move customer demo-hp: its own floor 0.311.0 wins (set 2026-10-14 15:18 UTC) — clear it on the customer page to let the global floor apply
|
||||
2026/10/15 13:07:32 [INFO] Operator email sent for /floor_raise_skipped
|
||||
2026/10/15 13:07:33 [INFO] access token "cc-releases": POST /configuration/global-floor → 303
|
||||
2026/10/15 13:07:33 [WARN] access token "cc-releases" refused: missing scope vouch:write — POST /configuration/artifacts → 403
|
||||
2026/10/15 13:07:33 [WARN] access token "cc-releases" refused: session only — never by a token — GET /customers/demo-felhom → 403
|
||||
2026/10/15 13:07:33 [WARN] access token "cc-releases" refused: session only — never by a token — POST /hosts/demo-hp-bb76ea/reveal-recovery-credential → 403
|
||||
2026/10/15 13:07:34 [INFO] access token "cc-releases": GET /configuration → 200
|
||||
skill recipe run verbatim 2026-10-15 ~13:20 Budapest (no-op 0.313.0/0.155.0): HTTP/1.1 303, Location: /configuration?flash=floor_set; header file removed
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
| Row | What | Closed | Evidence |
|
||||
|---|---|---|---|
|
||||
| **R-1051** | **CC could not raise the global floor without the operator's own password.** (P3) | CLOSED 2026-10-15 — hub v0.152.0 deployed (operator „yes"); the operator created the token „cc-releases" (2026-10-15 13:06, wider than the task's two scopes: also customers/hosts read, offsite and os read+write — the operator's choice). Live with the token: a no-op floor save 0.313.0/MinAgent 0.155.0 → 303 `flash=floor_set`, read back from the hub DB with its WAL; the vouch → 403 `missing scope vouch:write`; the customer page and a recovery-credential reveal → 403 `session only`. The `felhom-build-deploy` skill's floor step and `gitea-image-prune.sh` now use the token. Full text: `git show e92501f5:documentation/backlog/OPEN-ITEMS.md` | `audits/hub-tokens-2026-10-15/C3-token-live.txt`, `deploy.txt`; `05` §17; `09` §3 decision 251 |
|
||||
| **R-952** | **Nothing failed when a new hub route was added without deciding who may call it.** (P3) | CLOSED 2026-10-15 — **built in hub v0.152.0**, both surfaces: `/api/v1` — `internal/api/routes.go` names each route's caller (public with a reason, customer, host, global, passphrase, appliance, recovery), pinned to the switch from source; every non-public route with no credential, for a household and host that exist, answers 401/403. Web — `internal/web/routes.go` classifies every route for access tokens, pinned the same way. Full text: `git show e92501f5:documentation/backlog/OPEN-ITEMS.md` | `TestAPIRouteTable_MatchesSwitch`, `TestAPIRoutes_NoCredential`, `TestRouteTable_MatchesServeHTTPSwitch` (each red-proved, `REPORT-hub-tokens.md`); `05` §17.3–17.4 |
|
||||
|
||||
## 2026-10-15 (afternoon) — the floor reached 0.313.0
|
||||
|
||||
@@ -260,7 +260,7 @@ stopping line that lies.
|
||||
| **R-1049** | Monitoring & notifications | P3 | **A pulled drive mails the operator „unexpectedly disconnected” (error), and nothing ever mails that it came back.** MEASURED 2026-10-14 night (`audits/media-drive-events-2026-10-14/K8-hub-mails.txt`, the hub DB with its WAL from the running pod, and the mailbox as the second channel): two pulls → two `storage_disconnected` mails; the hub RECEIVED both `storage_reconnected` and both `health_recovered` (severity info) and logged no notification for any of them — they are not in `recoveredPairedDownTypes` (`hub/internal/notify/dispatcher.go`), so the severity gate drops them. The R-97a shape: told it broke, never told it healed — the operator cannot tell a returned drive from one still gone without opening the hub. **BUILT 2026-10-15 — hub v0.151.0 (`12552aca`): both pairs in `recoveredPairedDownTypes`, cooldowns ended by the next loss (`TestR1049_DriveBackMailsBothEdges`, red-proved). Not deployed: the operator's „yes” first (decision 162); the image build waits for it too.** | **WAITING-ON-OPERATOR** — hub v0.151.0 code pushed, not built, not deployed | the operator's „yes” to the hub deploy | On the „yes”: build + deploy hub v0.151.0; read a „came back” mail on the next pull | CC |
|
||||
|
||||
|
||||
## Hub & operator — 13 rows (P3 7, P4 6)
|
||||
## Hub & operator — 12 rows (P3 6, P4 6)
|
||||
|
||||
| ID | Category | Sev | What | State | Blocked on | Next action | Owner |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
@@ -275,7 +275,6 @@ stopping line that lies.
|
||||
| **R-844** | Hub & operator | P4 | **The household's OS-update line exists only on the hub's customer timeline.** 2026-10-04: the box itself has no event surface for agent results (the controller UI shows no timeline), so `os_update_applied` is a hub customer event (info: recorded, never mailed). Its stored text is the hub's English sentence; the hu/en bundle text (`mail.event.os_update_applied`) is used only if it is ever mailed. Fix direction: a controller-side line (the controller already polls the agent's local API) when the box gets a household timeline. `audits/os-guest-lane-2026-10-04/partG/hub-customer-timeline-demo-hp.txt` | **READY — owner: CC** **2026-10-05 (burn-down night): NEEDS A DESIGN** — a household timeline on the box does not exist yet. | — | — | CC |
|
||||
| **R-1002** | Hub & operator | P4 | **A box the household switched off reads ONLINE on the hub's hosts page for its first 45 minutes** (seen live 2026-10-13, R-998 proof, `audits/poweroff-2026-10-13/B-hub-watch.log`: the „Power: Kikapcsolva…" line at 18:53, the KIKAPCSOLVA badge only at 19:38, when the host report turned stale). The customer page read „warn" in part of that gap (seen, not captured). No alarm and no mail fired; the operator page is only slow to say it. | **READY** — filed 2026-10-13 | — | CC: let `hostDisplayStatus` read `deliberate_off_at` before staleness, with a render test per state; next hub release | CC |
|
||||
| **R-1011** | Hub & operator | P3 | **The Day-0 „Agent" list offers step-bundle packages (`0.156.1-step1`, `0.152.0-step1` …) as agent versions; one has no agent binary, so the hub shows the bundle JSON's sha (`FileSHA256` falls back to the first file) and a vouch would point fresh installs at a package with no binary.** Seen 2026-10-14 (`/configuration`: two „0.156.1" entries, `ac83ea41…` is the step bundle). | **READY** — filed 2026-10-14 | — | CC: list only versions whose package holds the `felhom-agent` file (refuse a missing preferred file instead of falling back), with a test; next hub release | CC |
|
||||
| **R-1051** | Hub & operator | P3 | **CC cannot raise the global floor without the operator's own password.** `09` §3 decision 250 lets CC raise the floor after the three test boxes, but the only route was the operator page with the operator password. Operator ruling 2026-10-15 11:38 (`09` §3 decision 251): scoped tokens; until CC's token works, the password for the floor only. | **BLOCKED** — hub v0.152.0 DEPLOYED 2026-10-15 (`05` §17: tokens with groups, CC = `overview:read` + `floor:write`) | the operator creates „cc-releases" and saves it to `~/.felhom-hub/cc-token` | A no-op floor save with the token, read back; a vouch attempt → 403; a session-only route → 403; then close | operator |
|
||||
| **R-1056** | Hub & operator | P4 | **Five operator routes fit no token group, so they are session only until the operator places them:** apps reset-telemetry and dismiss-issues, the Configuration asset re-seed, the off-site WireGuard endpoint save, the off-site abandon-cancel (`05` §17.3). Nothing needs them by token today. | WAITING-ON-OPERATOR — filed 2026-10-15 by the token build | operator decision | Place each in a group, or leave session only | operator |
|
||||
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ The full 0.188.0 run, with the observables: `documentation/audits/tester-gate-go
|
||||
When the Gitea volume fills, `~/git/misc-scripts/gitea-image-prune.sh` (repo `admin/misc-scripts`) prunes old versions.
|
||||
**Dry-run first, always** (`./gitea-image-prune.sh --all prune`, then `--type generic --all prune`): it keeps the newest
|
||||
20 of each package plus every version in use — the floor, the vouched golden, the vouched agent and `min_agent` (read
|
||||
from the hub with `HUB_PW`), the images the vouched golden baked (its `bake.log` here), the hub `manifests/hub.yaml`
|
||||
from the hub with the scoped token `HUB_TOKEN`, `floor:read`), the images the vouched golden baked (its `bake.log` here), the hub `manifests/hub.yaml`
|
||||
runs — and prints each with its reason. It refuses when that list cannot be read. **`--apply` is a person's act**,
|
||||
after reading the dry-run; nothing schedules it. The August 2026 `--keep 7` run (HM-024) predates the rule.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user