docs: v0.93.0 publish train executed — built, published, vouched, deployed fleet-wide
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
## v0.93.0 — a recovery code can no longer contain a hyphenated word (2026-07-21)
|
||||
|
||||
> **SHIPPED 2026-07-22:** built + published (sha256 `a68b2ff73200622e…`), Day-0-manifest-vouched,
|
||||
> deployed to both fleet boxes (felhom-pve + demo-hp), clean-restart verified. Record:
|
||||
> `felhom.eu/documentation/pilot/RUNBOOK-publish-agent-0.93-2026-07-22.md`.
|
||||
|
||||
**Generation-only change. Every recovery code already issued remains valid** — R is consumed as a
|
||||
whole passphrase by the PBS scrypt KDF (`Wrap`/`Unwrap`) and is never re-split, so nothing about
|
||||
verification moves. Nothing in the KDF/consume path, the word count, or the joiner changed.
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
|
||||
## Current
|
||||
|
||||
- **2026-07-22 — v0.93.0 is the FLEET AGENT.** Built, published (sha `a68b2ff73200622e…`),
|
||||
Day-0-manifest-vouched (MinAgent also 0.93.0, operator-ruled) and deployed to BOTH boxes
|
||||
(`demo-felhom-8363b5` + `demo-hp-bb76ea`, the latter over G1 break-glass — still no key baked);
|
||||
clean-restart 5/5 on both, `.bak-0.92.1` retained. Discharges the onboarding runbook §A5
|
||||
ceremony gate. Record: `felhom.eu/documentation/pilot/RUNBOOK-publish-agent-0.93-2026-07-22.md`.
|
||||
**The bullet below ("agent is DOWN … deployed 0.90.0") is SUPERSEDED history** — vmbr0 was made
|
||||
static .162 on 2026-07-20 (F1 mitigation) and the agent has been up since; kept for the record.
|
||||
|
||||
- **2026-07-20 — REMOTE SITE until ~2026-08-02; the agent is DOWN there and cannot self-recover.**
|
||||
felhom-pve moved off the home LAN; `ssh felhom-pve` = tailnet `100.70.170.35` (direct, ~37 ms). The
|
||||
host is on DHCP and holds `192.168.0.147`, so `localapi`'s literal `192.168.0.162` bind fails with
|
||||
|
||||
@@ -1,79 +1,76 @@
|
||||
# REPORT — escrow recovery-code wordlist fix (TASK-E Part 1), 2026-07-21
|
||||
# REPORT — v0.93.0 publish train executed: built, published, vouched, deployed fleet-wide (2026-07-22)
|
||||
|
||||
**Version: v0.93.0. Baseline `935904f` (v0.92.1), clean tree. NOT built or deployed** — no operator
|
||||
action needed today; this rides the next agent publish train.
|
||||
**The previous report's "NOT built or deployed" line dies here.** v0.93.0 (hyphen-free escrow
|
||||
wordlist, `a452dc33`, red-proofed 2026-07-21) is now the fleet agent. No code changed this train —
|
||||
this was the build/publish/deploy leg. Full operational record:
|
||||
`felhom.eu/documentation/pilot/RUNBOOK-publish-agent-0.93-2026-07-22.md`.
|
||||
|
||||
## What was wrong
|
||||
## Confirmed baselines (re-verified at live source before acting)
|
||||
|
||||
The EFF large wordlist contains exactly four entries that themselves contain the hyphen the words are
|
||||
joined with: `drop-down` (L2009), `felt-tip` (L2528), `t-shirt` (L6640), `yo-yo` (L7748). Drawing one
|
||||
produced a recovery code that reads as **11 words instead of 10** — ambiguous to transcribe in the one
|
||||
situation R exists for, a customer reading a code back during a disaster.
|
||||
- `main` = `eba040d0` = origin/main, clean tree; v0.93.0 delta vs 0.92.1 = escrow code + tests +
|
||||
docs only, **no `configs/` change** → binary-only deploy (sudoers/wrapper untouched).
|
||||
- Both boxes 0.92.1 + active (hub `hosts` table AND direct `--version`); Day-0 manifest agent
|
||||
0.92.1/`7424bc1c…`; floor 0.156.0; hub 0.70.0; package `felhom-agent/0.93.0` = 404 pre-publish.
|
||||
|
||||
**The "known flake" was this defect, not a flaky test.** Per code the hit rate is
|
||||
`1 − (7772/7776)^10 ≈ 0.51%`; over the test's 50 draws that is ≈ **23%**, which is exactly the "fails
|
||||
~1/5" that had been documented in the `felhom-testing` skill and re-run past for weeks.
|
||||
`felhom.eu/REPORT.md` §6 had it at 3/8 in one session.
|
||||
## Artifact
|
||||
|
||||
## The fix
|
||||
```
|
||||
AGENT_VERSION=0.93.0
|
||||
AGENT_SHA256=a68b2ff73200622ea9e23aed71a0a8ff885808626cab9e9d554a5a5df5ced28f (13 817 690 bytes)
|
||||
```
|
||||
|
||||
`joinSafe` filters those four out of the effective wordlist at init. Generation-only.
|
||||
|
||||
| | before | after |
|
||||
|---|---|---|
|
||||
| draw space | 7776 | **7772** |
|
||||
| 10-word code entropy | 129.248 bits | **129.241 bits** |
|
||||
| margin over the 128-bit floor | 1.248 | **1.241** |
|
||||
|
||||
The cost is **0.007 bits**. Both numbers are asserted in `TestEntropyFloorSurvivesFiltering`, so a
|
||||
future wordlist swap cannot quietly move the floor.
|
||||
|
||||
**Every recovery code already issued remains valid**, and this was verified rather than assumed: R is
|
||||
consumed as a whole passphrase by the PBS scrypt KDF (`Wrap`/`Unwrap`), and `grep` confirms nothing in
|
||||
the consume path ever splits it. The joiner, the word count and the KDF path are untouched.
|
||||
Built on DooPlex from `eba040d0` (`CGO_ENABLED=0`, ldflags version); published via
|
||||
`scripts/publish-agent.sh` (pre-delete 404 → PUT 201 → round-trip sha match); **sha-chain identical
|
||||
at three independent points** incl. an anonymous GET of the package URL.
|
||||
|
||||
## Tests
|
||||
|
||||
`TestGenerateRecoveryCode_EntropyAndFormat` now counts words by **generation count**, not by splitting
|
||||
the joined string — conflating those two is what made it flake. It asserts the segmentation property
|
||||
separately, because that is the property `joinSafe` actually buys.
|
||||
Green gate on the exact built HEAD: `go build ./... && go vet ./... && go test ./...` — green.
|
||||
**The formerly-flaky escrow package: `-count=10` fresh → 10/10 pass (135.2 s).** The ~1/5 flake WAS
|
||||
the hyphenated-word defect (see the 2026-07-21 report), so a clean 10× run is direct evidence the
|
||||
fix is in the built artifact.
|
||||
|
||||
New in `wordlist_test.go`: the four filtered words are pinned by name (a wordlist swap that changes the
|
||||
set fails loudly); the entropy numbers above; and a production-wiring test that drives the exported
|
||||
`GenerateRecoveryCode` 500×, so the fix is proven at the entry point and not only in the helper.
|
||||
## Manifest vouch (rule 1 — before any box moved)
|
||||
|
||||
### Red-proof — RUN, both deterministic and probabilistic halves
|
||||
Viktor saved Day-0 artifacts (password-gated UI, the train's one STOP); CC verified in the live hub
|
||||
DB before deploying: agent **0.93.0 / a68b2ff7…**. Golden, floor and wrapper sha **byte-identical
|
||||
before/after** (0.153.0 / 0.156.0 / `104db0a4…`). **Deviation, ruled:** MinAgent moved
|
||||
0.92.1→0.93.0 at the save (spec said do-not-touch); flagged before deploy, ruled leave-as-is —
|
||||
transient held-floor window only, both boxes already ran controller ≥ floor.
|
||||
|
||||
Pre-fix shape restored (`var wordlist = parseWordlist(wordlistRaw)`), suite re-run:
|
||||
## Deploys — felhom-pve first, then demo-hp
|
||||
|
||||
```
|
||||
--- FAIL: TestWordlistLoaded
|
||||
effective wordlist should be 7772 words (7776 EFF - 4 hyphenated), got 7776
|
||||
--- FAIL: TestGenerateRecoveryCode_EntropyAndFormat
|
||||
joined code must segment into 10 words, got 11 (a drawn word contained "-")
|
||||
--- FAIL: TestEntropyFloorSurvivesFiltering
|
||||
filtered entropy moved: 129.248, expected 129.241
|
||||
--- FAIL: TestGenerateRecoveryCode_NeverContainsAmbiguousWord
|
||||
code 193 segmented into 11 parts, want 10
|
||||
```
|
||||
Channel per the 0.90 train: scp one hop → on-box sha256 verify (= `a68b2ff7…` both) →
|
||||
`.bak-0.92.1` → `install -m0755` → restart. demo-hp reached over the hub-vaulted G1 break-glass
|
||||
(no key baked; secret handled file→file via `SSH_ASKPASS`, shredded after, never printed).
|
||||
|
||||
Fix restored → green; `git diff` clean.
|
||||
Per-box clean-restart verification — **5/5 green on both** (journal times host-local CEST):
|
||||
|
||||
`TestGeneratedCodeSegments_FilteredVsUnfiltered` is the **deterministic** companion: it drives the
|
||||
generator against a fixture list where every word is hyphenated, so the pre-fix defect reproduces with
|
||||
probability 1 rather than ~1/5, and shows the same list through `joinSafe` refuses to generate at all.
|
||||
| Check | felhom-pve (restart 06:56:49Z) | demo-hp (restart 06:57:48Z) |
|
||||
|---|---|---|
|
||||
| active / no restart loop | ✅ active, NRestarts=0, clean startup `version=0.93.0` | ✅ same |
|
||||
| capabilities | ✅ 68/68 ok, degraded=0, inactive=0 | ✅ 68/68 ok, degraded=0, inactive=0 |
|
||||
| ReassertGuestBinds | ✅ only enrolled `uuid:47a3361a…` (`/mnt/hdd_1`→9201) | ✅ only enrolled `uuid:91d2dc2d…` (`/mnt/nvme-1tb`→9201) |
|
||||
| guestnet sweep | ✅ watchdog up; sweeps quiet, 0 ERROR/WARN since restart | ✅ same |
|
||||
| hub `agent_version` | ✅ 0.93.0 (report at startup, 06:56:52Z) | ✅ 0.93.0 (06:57:52Z) |
|
||||
|
||||
## Gates
|
||||
Escape hatch not needed; `.bak-0.92.1` retained on both boxes. `peti-felhom` deliberately not
|
||||
deployed to (down; gets 0.93.0 via Friday's reinstall + the vouched manifest — by design).
|
||||
|
||||
`go build ./... && go vet ./... && go test ./...` — **green**. The ex-flaky package was additionally
|
||||
run 10× consecutively: 10/10 pass (it previously failed ~1 in 5).
|
||||
## Explicit statements (per the train spec)
|
||||
|
||||
## Observations
|
||||
- Controller floor and MinAgent handling: floor **byte-identical** before/after (0.156.0); golden
|
||||
entry byte-identical; MinAgent's 0.93.0 value is the one ruled deviation above.
|
||||
- No escrow ceremony was run as "verification" — the proof is the generation-path tests + version
|
||||
reporting, per the spec.
|
||||
- This train discharges `RUNBOOK-onboarding-draft-v4.md` §A item 5 (agent ≥ 0.93.0 box-side before
|
||||
the first real tester's escrow ceremony) — annotated there.
|
||||
|
||||
- The `felhom-testing` skill's "Known flake … re-run before diagnosing; it is not a regression" line
|
||||
is now removed. It had been actively harmful: it told every future session to dismiss a true
|
||||
positive. Replaced with the generalised lesson — "known flake, just re-run it" is a diagnosis and
|
||||
needs evidence like any other.
|
||||
- `WordlistSize()` now reports the **effective** (filtered) draw space, 7772. `WordlistFilteredOut()`
|
||||
is new, for audit. Any external consumer expecting a literal 7776 would need updating; there is none
|
||||
outside the tests.
|
||||
## Observations (recorded, not acted on)
|
||||
|
||||
- The spec's "ROADMAP wordlist row" does not exist in `felhom.eu/documentation/backlog/ROADMAP.md`;
|
||||
the gate discharge was annotated at its real home (onboarding runbook §A5) instead.
|
||||
- demo-hp's 1TB NVMe is now **enrolled** (reasserted into 9201) — TASK-H's "unenrolled/NTFS, do not
|
||||
touch" note is outdated.
|
||||
- demo-hp remains key-less; break-glass deploy worked cleanly. Tailnet key-expiry toggle still open.
|
||||
- CONTEXT.md's stale "agent DOWN at remote site / deployed 0.90.0" bullet superseded this train.
|
||||
|
||||
Reference in New Issue
Block a user