Files
felhom.eu/REPORT.md
T

94 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — hub v0.72.0: R-70 + R-71(c) — the offsite last mile becomes visible, burned credentials heal themselves (2026-07-23)
**Spec:** R-70 + R-71(c) prompt (project Claude, 2026-07-23). Companion controller leg: v0.161.0
(see `felhom-controller/REPORT.md`). Origin: `documentation/audits/DIAG-f10-demo-hp-offsite-2026-07-23.md`.
R-71(a) (day-0 ordering) untouched — separate upcoming spec.
## Baselines
| Repo | start | shipped |
|---|---|---|
| felhom.eu | `c801cee6`, hub 0.71.0 | hub **0.72.0** (code + separate manifest chore commit), ArgoCD Synced/Healthy |
| felhom-controller | `0eba37d5`, v0.160.0 | **v0.161.0** (`ce85314`), deployed BOTH boxes, healthy |
## What shipped (one detector, four consumers)
1. **Detector**`internal/offsite/delivery.go` `DeliveryStateFor`: `applied` /
`consumed_awaiting_apply` / `staged_awaiting_consume` / `no_secret` from the secret-row
timestamps × report offsite-presence. Applied wins (the box's own report is the strongest
evidence); applied+unconsumed-staged (demo-felhom) = `applied` + `StaleStagedSince` flag.
New store reads (`GetOneTimeSecretInfo` — timestamps only, value never selected;
`LatestReportOffsitePresence`; `CountReportsOffsiteSince`; `LastEventAt`) + the PBSDR-style
test back-dater.
2. **Customer card**`deliveryViewFor` + `config_form_body.html`: the static "delivered to the
controller once" claim is deleted; the card renders state + age (badge `n-ok/n-warn/n-neutral`,
consumed goes amber past 30 min, stale-staged info line). Render test per branch.
3. **Loud event**`offsite_delivery_stuck` (WARNING) at ≥ 1 h of consumed_awaiting_apply;
24 h/customer cooldown, durable via the events table (restart-proof).
4. **Self-heal (R-71c)**`monitor.OffsiteDeliveryChecker` on the shared 60 s ticker invokes
`web.Server.ReissueOffsiteForCustomer` behind the narrow `monitor.OffsiteReissuer` interface
(pbsdrheal precedent; armed only when the provisioner exists — else a restaged event would
lie about a silent no-op). Trigger: consumed ≥ 1 h + ≥ 4 consecutive offbox-less reports +
zero offbox evidence since consume. One restage/customer/24 h (durable); every firing emits
`offsite_credential_restaged` (WARNING). **R-39(a) guard**: the heal re-reads the secret row
immediately before acting and refuses over an unconsumed row — the store's
`SaveOneTimeSecret` clobber semantics are untouched (Re-issue depends on supersede; the guard
lives in the caller, exactly as specced).
## Red-proofs (run, observed, restored — verbatim failures)
1. **THE CLOBBER RED-PROOF** — R-39(a) guard block removed from `maybeHeal`; the TOCTOU test
(operator Re-issue staged mid-tick via the onEvent hook) failed with:
`reissue calls = 1, want 0 — the R-39(a) guard must refuse over an unconsumed secret`
— i.e. the operator's fresh unconsumed secret would have been clobbered
(the fake reissuer mimics the production `SaveOneTimeSecret` side effect, so the clobber is
observed on the row, not inferred). Guard restored → green.
2. **Heal rate-limit**`LastEventAt`/`healCooldown` check removed; failed with:
`reissue calls after recurrence = 2, want STILL 1 (one restage per customer per 24h)`. Restored.
3. **Stuck-event cooldown** — cooldown check removed; failed with:
`stuck events = 2, want exactly 1 (24h per-customer cooldown)`. Restored.
Plus: the full-Check demo-felhom-shape test (applied + stale staged → zero events, zero calls,
row byte-untouched), evidence gates (<4 reports → no heal but stuck event still fires; mixed
offbox history → no heal), young-consumed silence, disabled/blocked skip, dispatcher severity
tests (warning routes operator-only; an info variant would be silent — pinned beside the v0.71.0
guard, `severityNotifies` untouched), 5 card render tests + `deliveryViewFor` amber derivation.
Green gates: hub 17 packages ok + `hub_confirm_gate.py`; controller 25 packages ok + all template
gates (the pre-existing R-29 `docker_run_volume_path_gate` red noted, untouched).
## Live validation (read-only, both fixtures intact)
- **Checker silence:** 10 min of 60 s ticks on the live fleet → **0** `offsite-delivery` log
lines, **0** detector events in the DB — both fixtures are healthy and the detector agrees.
- **Fixture states from live data** (fresh DB copy, shredded after):
demo-hp `latest_report_offsite=True, secret consumed 09:53:41`**applied**;
demo-felhom `latest_report_offsite=True, secret_row=(2026-07-21 08:29:29, None)`
**applied + stale-staged since 07-21** — the live specimen SURVIVED the train untouched
(`consumed_at` still NULL, created_at unchanged); peti-felhom → applied.
- **demo-hp controller page** (authed endpoint fetch inside the guest, ASCII-safe greps):
banner count 0, `felhom-offsite-card` id count 0 (configured + 1 toggled app → no card at all),
configured markers present. v0.161.0 healthy on both boxes.
- **Method:** endpoint-level + DB-input derivation (no browser on DooPlex). The rendered card is
pinned by render tests; the operator's 10-second residual: demo-hp Edit page shows
`applied`, demo-felhom shows `applied` + the stale-staged note (since 2026-07-21).
- **The self-heal is NOT live-fired** — no broken box exists and none was broken for it (F9
rule). It ships unit-proven + red-proofed, PARTIAL/IMPLEMENTED on the ROADMAP with the
explicit "fires on next natural occurrence or a staged drill" note — never PROVEN-LIVE.
The controller banner leg is likewise unit-proven/live-pending (no box occupies the
enabled+no-offbox window; the next fresh onboarding is its natural live leg).
## Rulings recorded (CONTEXT.md)
State precedence (applied wins; stale-staged is a flag, never a downgrade); durable cooldowns via
the events table (restart-proof by design); both detector events operator-only (no
customerMessages entry, not in allowedEventTypes — the pbsdr_* precedent) until the mechanism has
history; heal disabled without a provisioner.
## Observed, not acted on
- R-29: `docker_run_volume_path_gate` red on `appexport/estimate.go:179` (pre-existing, has its
own row — the 3-line allowlist fix remains undone by design of this train's scope).
- The `szolg` single-hit on the demo-hp page grep is an accent-truncated unrelated word (the
ASCII-only-grep trap documented in felhom-controller/CLAUDE.md — verified benign via the
card-id count of 0).