hub v0.105.0: the third name, a machine told to be quiet, and a guard for the hub's own words
gates / gates (push) Successful in 17s

Hub only. No controller change, no agent change, no wire change — nothing to bake.
demo-hp untouched: the operator is re-deploying it this evening.

R-323 — the five-word phrase is „Tulajdonosi jelmondat". It was „Visszaállító
jelszó": one word from the name retired last week, and false besides — it restores
nothing, it proves the account owns the box being bound. Five sites, all in the hub;
felhom-controller and felhom-agent carry the name nowhere, so no halt and no bake.
Both suggested names were rejected with reasons: „Fiókjelszó" would collide with the
dashboard login (a DIFFERENT real secret), and „Összekötési jelszó" would leave the
two factors on this page separated only by kód-versus-jelszó — the exact shape being
removed, since the other factor is the „Párosító kód". The chosen name differs on
both axes, stem and noun. Naming only; the acceptance pin drives the real handler.

R-324 — the hub's customer copy is under a guard for the first time. Retired names
banned across all 95 hub files; retrieval stems registered in four declared customer
surfaces. The selftest found a defect in its own instrument on the first run. One
shared vocabulary in scripts/, drift-checked into the controller gate rather than
copied (R-325 removes the scaffold).

R-321 — a machine we told to be quiet is no longer reported as dead, and it was two
doors, not one: because the state is RECORDED rather than deleted, the morning
deadline check can skip it too. A deleted state returns "", which is not "down" —
R-195's shape returning through a second door. The clock runs from the report the hub
can see, so re-enabling starts it there and emits no recovery for an outage that never
happened. Three red-proofs; the one that matters showed a genuinely dead machine
sitting at "disabled" when the suppression was made unconditional.

R-326 — "which claims are unproven" is answerable by a command now. The nine I have
been repeating was the count of claims the 9 August pass DOWNGRADED, not the count of
unproven ones. The real figures: 55 claims, 23 walked, 32 not — and only 6 of those 32
cite evidence. Its first run found a stale claim (R-327).
This commit is contained in:
2026-08-13 15:50:32 +02:00
parent 955a4f07b7
commit b03a105375
14 changed files with 995 additions and 16 deletions
+90
View File
@@ -1,3 +1,93 @@
## v0.105.0 — the third name, a machine told to be quiet, and a guard for the hub's own words (2026-08-13)
Hub only. **No controller change, no agent change, no wire change — nothing to bake.** R-323, R-324,
R-321, R-326.
### R-323 — the third near-homograph: „Tulajdonosi jelmondat"
Three secrets a customer can hold, and they must be tellable apart by a hurried reader:
| | what it is | name |
|---|---|---|
| three words | takes control of the dashboard | „Beállító kód" |
| ten words | opens the sealed off-site backups | „Helyreállítási kód" |
| **five words** | **proves the account owns the box being bound** | **„Tulajdonosi jelmondat"** |
The five-word phrase was „Visszaállító jelszó" — **one word from the name retired last week for
colliding with „Helyreállítási kód"**, and false besides: the phrase restores nothing.
**Five customer-facing sites, all here**: `web/selfbind.go:255,256,261,263` and
`notify/templates.go:331`. Nothing in `felhom-controller` or `felhom-agent` — the only hits there are
comments and a test asserting the already-retired „Visszaállító **kód**" is absent.
**Both obvious names were rejected, with reasons.** „Fiókjelszó" is worse than the trap it fixes:
there IS an account password (the dashboard login), so it would collide with a *different* real
secret. „Összekötési jelszó" recreates the trap structurally — the other factor on the same page and
in the same mail is the **„Párosító kód"**, so naming this one after the same act would leave the two
factors a customer types in one sitting separated only by kód-versus-jelszó, which is exactly the
shape being removed. „Tulajdonosi jelmondat" is distinct on **both** axes — stem and noun.
**Naming only.** The form field is still `name="passphrase"`;
`TestSelfBindPassphrase_StillAcceptedAfterTheRename` drives the real handler with the same messy human
spacing and asserts the appliance still binds.
### R-324 — the hub's customer copy comes under a guard, for the first time
`retrieval_promise_gate.py` lives in `felhom-controller` and scans that repo only. It was extended to
Go strings on 2026-08-12 because the recovery screen's copy *"had never been scanned"* — and the same
sentence was true one repo over, for the surface a customer reads **first**.
`scripts/hub_copy_gate.py`, registered in `repo_gates.py`:
- **retired names — banned outright, across all 95 hub files**, no allowlist. Comments stripped.
- **retrieval stems — registered, not banned**, in four declared customer surfaces. A missing declared
surface is a FAILURE, never a skip. The allowlist is empty, and that is a measurement.
**The selftest found a defect in its own instrument on the first run**: the synthetic source was named
`<selftest>`, comment-stripping keys off the `.go` extension, and the step-3 control convicted a
comment. The bug was in the guard; the control is what found it.
Vocabulary is **not duplicated**`scripts/customer_copy_vocab.py` is the one list, in the same
shared-gate home both repos already consume without copying. The controller gate has not yet adopted
it (that would be a felhom-controller change, out of scope tonight), so this gate **reads its `STEMS`
and fails on divergence** — watched failing, and green again when restored. R-325 removes the scaffold.
### R-321 — a machine we told to be quiet is not a machine that died
Switching a box's reporting off is supported: the controller sends one final report carrying
`health.status = "disabled"` and goes quiet by design. The hub stored that, rendered it in the
roll-up, and **alarmed on it anyway** — stale at 30 minutes, down at 60, two e-mails about an outage
we caused on purpose.
**It was two doors, not one.** `StalenessChecker.Check` now skips the age transition; and because the
state is **recorded** (`StateDisabled`) rather than deleted, `CheckBackupDeadlines` can skip it too —
a deleted state returns `""`, which is not `"down"`, so that check would have gone on sending
`expected_backup_missed` every morning. R-195's shape returning through a second door.
The discriminator is the box's own last word, not an inference. `downtimeStart` is cleared on entry.
**The re-enablement clock runs from the report the hub can see**, so a box that reports on re-enabling
starts its clock there; leaving `disabled` re-enters the new-customer branch, so no `node_recovered`
fires for an outage that never happened. **Limit, stated:** a box re-enabled that then fails to report
keeps being suppressed — the hub's view changes only when a report arrives, which is exactly why the
state is made visible.
**Three red-proofs, mutations asserted applied.** The one that matters: an unconditional suppression
was seen leaving a genuinely dead machine at `"disabled"` instead of `"down"`. A test weakness was
found by a red-proof and fixed — scenario A seeded the customer already-disabled, so the new-customer
branch swallowed the first observation and it passed on the state assertion alone even with the
suppression deleted.
### R-326 — "what is unproven" becomes a question a machine can answer
A session asked for *"the nine grey claims"* could not determine which nine and declined to guess.
**Nine is real and answers a different question: it is the count of claims the 2026-08-09 pass
DOWNGRADED.** The real figures, from `where-felhom-stands.yaml`: **55 claims — walked 23, partial 14,
built 14, missing 4; NOT WALKED 32 of 55**, of which only 6 cite evidence and 26 are prose only.
`scripts/unproven.py` prints them; `--summary` prints the counts. Wired into the end-of-session
checklist. Its first run found a stale claim — `claim.code-naming` still describes a defect now fixed
twice over (R-327). The capability map is deliberately **not** restructured.
## v0.104.0 — the hub can see whether a guest's networking works, and one name per secret (2026-08-13, R-319 + R-295 hub half)
Two things, both hub-only. **No wire change, no agent change, no controller change, nothing to bake.**