Commit Graph

130 Commits

Author SHA1 Message Date
admin 84751cb0ce hub v0.167.0 source (not built, not deployed): D31 — the F-14 PBS auto re-issue reads the newest deletion of a host that held a key, a keyless install between no longer blocks it (R-1205); D30 — the new key's handshake clears wg_tunnel_stale (pinned), wording; wire gate entry; Part 1 stray-copy 9202 evidence
gates / gates (push) Successful in 15m46s
2026-10-22 21:04:42 +02:00
admin e267c5e2cd hub 0.166.0 source: the clock-ahead tunnel alarm wg_tunnel_stale/ok (R-1204, operator-only, edge-triggered); D21 + D4 proof evidence 2026-10-22 17:02:37 +02:00
admin 5ae5984cf9 hub 0.165.0 source: a household's mail list is never overwritten by a box default, a box reads it back (R-1199 reopened); host_swap_short only when swap is really short (R-1216, D28 = A); host-swap-rule gate with 4 decoys; 03/05/08 updated
gates / gates (push) Successful in 15m54s
2026-10-22 12:23:07 +02:00
admin 3c620f8d2e hub 0.164.0 (unreleased): host_swap_short / host_swap_ok operator alarm from the agent's host and guest swap numbers (R-1192 follow-up); wire gate allowlists guests.spec.swap_bytes
gates / gates (push) Failing after 14m53s
2026-10-21 21:55:15 +02:00
admin 9688e76efd hub v0.163.0: a rebuilt box gets the household's sealed package back (R-1176); one run per daily job on clock-change days (R-1183); a scoped abandonment purge (R-1182); the new-link page says the old box is still linked (R-1203)
gates / gates (push) Successful in 13m23s
2026-10-21 13:36:45 +02:00
admin 5f31da04bc hub v0.162.0 (built, not deployed): no repeat mail after a restart for a known-down host or an already-reported stale restore test (R-1001); the Day-0 agent list leaves out packages without the felhom-agent file, a vouch of one is refused (R-1011); an absent tunnel reads 'none set up' (R-1070)
gates / gates (push) Successful in 7m20s
2026-10-19 20:27:01 +02:00
admin b6a911c3f9 hub v0.161.0: passphrase keys only until the box uses its own (box-config route; R-1159, D19); ep0 namespaces without a prune job alarmed, tenantsync v1.3.0 creates the job (R-1165)
gates / gates (push) Successful in 7m47s
2026-10-19 15:55:45 +02:00
admin 503c93fada hub v0.160.0: a live re-enroll mails the operator (R-1156); further refused backups counted, alarm once a day (R-1157); the reinstall's off-site re-issue says what it still does (R-1158) 2026-10-19 10:34:41 +02:00
admin d5e3c8b0d9 hub: gofmt -w on 22 files, formatting only, no behaviour change (R-1160) 2026-10-19 10:26:36 +02:00
admin b505ce4ba0 hub v0.159.0 (R-1154, after security review): the enroll reuse path re-issues nothing, it warns the operator
The first draft (5121536f, unpushed) re-issued the claim code and the off-site login on a
reuse whose old box was stale or switched off. A security review flagged it: the caller
holds only the household's retrieval passphrase, and both re-issues are operator
session-only actions (05 section 17.5, 09 decision 252, R-1055/R-1059). Now the reuse
path classifies the old box and re-issues nothing: gone -> host_reinstall_over_old_host
(warning, mailed to the operator: delete the old host and re-run, or re-issue by hand);
live -> host_reenroll_while_live (info). The mint path after the operator's delete is
unchanged and still re-issues. The once-per-silence record and the claim engine comment
edit are reverted. 05 section 8, README and CHANGELOG updated; tests red-proved.
2026-10-19 03:29:44 +02:00
admin 5121536f10 hub v0.159.0: a refused whole-guest backup has its own alarm (R-1150); a reinstall re-issues the claim code and the off-site login when the old host is stale or off (R-1154)
R-1150: the agent's localapi:backup-cadence-cap is a separate per-host state in
HostCapabilityChecker: alone it raises whole_guest_backup_refused (warning, plain text,
agent reason in details) and whole_guest_backup_refusal_cleared (info); other critical
caps keep agent_capability_degraded/_recovered unchanged. New types operator-only and
hub-origin only (not in allowedEventTypes: the suspected controller must not post them).
agent_capability_degraded/_recovered join operatorOnlyEvents (the checker's "never the
customer" claim was configuration only).

R-1154: handleHostEnroll's reuse path re-issues (claim code + off-site login) when no
controller wait is open and either deliberate_off_at is held or both the host report and
the controller report are older than alerting.stale_threshold (wired from main); once per
silence (host_reenroll_reissued record, also written at mint); a live box gets nothing
re-issued and the skip is recorded (host_reenroll_not_reissued). 05 section 8 [DESIGN].

Tests red-proved; go build/vet/test green.
2026-10-19 03:18:34 +02:00
admin 7d64038f02 Hub v0.158.0 code (built, NOT deployed): agent-only vouch, R-895 snapshot alarms, the hub's own 90-day access log (R-1140 A); installer --rotate-recovery-only (R-1141); 02/03/05/09 + break-glass
gates / gates (push) Successful in 6m45s
Hub: the R-120 golden guard judges only a CHANGED golden selection; offsite_snapshots_vanished /
_unexplained (operator-only, hub-origin) on the 07:10 listing; internal/accesslog writes path-only
lines to /data/access-log, 90 days. Installer: --rotate-recovery-only runs step 4b alone (rides
the next installer tag). 03: the orphan check runs after a failed backup (agent 6545ccc). 02: the
allow-list is empty, appdata_folders (controller v0.329.0). All red-proofed.
2026-10-17 23:31:34 +02:00
admin 8f97b8009b hub v0.157.0: app_definition_refused (R-971), the vault time moves on a re-vault (R-954), the hub's own snapshot count (R-895 slice); uninstall knows felhom-thin-check
gates / gates (push) Successful in 6m58s
- hub: `app_definition_refused` in allowedEventTypes + operatorOnlyEvents (controller v0.328.0's catalog
  allow-list refusal); SaveHostRecoveryCredential moves set_at on a re-vault (found live: both rotated hosts
  kept their first vault's time); the daily key audit also lists the box's restic snapshots/ read-only over the
  login the hub already holds and logs count/newest/oldest (no alarm yet).
- installer (main only, rides the next tag): --uninstall removes /usr/local/sbin/felhom-thin-check (agent
  v0.159.0's bundle file); test_hostinstall.py knows it.
- runbook whole-guest-backup-orphan-thin.md: the human repair the agent's new orphan finding points to.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-17 16:27:51 +02:00
admin b17e9e993c hub v0.155.0: the floor can never deliver a withdrawn controller build (R-1085); RomM/Ghost evidence
gates / gates (push) Successful in 6m44s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-16 12:24:39 +02:00
admin 4c9bb5f198 hub v0.154.0: the host page shows each storage place's physical disk(s) and whether the agent proved them (16 §3)
gates / gates (push) Successful in 6m43s
Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-15 21:28:05 +02:00
admin d62cc08b2e hub v0.152.0: operator access tokens with scopes (09 §3 decision 251, operator 2026-10-15 11:38)
gates / gates (push) Successful in 6m44s
- Configuration → Access tokens: named, scoped (group read/write), expiring (≤365 d), shown once,
  stored SHA-256 only, every use logged by name. Bearer fhp_… on the web surface only; /api/v1 refuses it.
- Route table = the code's single source (web/routes.go), pinned to ServeHTTP's switch; session-only:
  secrets shown/minted, deletes/resets, password, tokens.
- R-952 closed: /api/v1 route table names each caller, pinned to the switch; no-credential refusal test.
- Fail-open fixed: an empty operator password served the UI open (main skipped RequireAuth). Live hub never open.
- 05 §17, 04 §6.2, 13, 09 §3 251; register 155→157 (+R-1054, R-1055, R-1056, −R-952); STATUS.
- website: prowlarr-logo.svg (byte copy from felhom.eu-media) — the site gate refused every push.
Not deployed — waits for the operator's yes.

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-15 12:20:35 +02:00
admin 822d039344 hub v0.150.0: app_repaired_after_crash — allow-listed + operator-only, counts line in the operator mail (R-1007); decision 236 recorded
gates / gates (push) Successful in 6m40s
The operator's half of the repair after an unclean boot (controller 0.311.0): counts only, never a
file name; warning mails, info is recorded. Registered in allowedEventTypes and operatorOnlyEvents in
the same commit, plus the per-app cooldown list; tests pin the pair, a household that enabled the type
gets nothing, and the counts line (red-proofed). Decision 236 (operator, 2026-10-14): the box asks
Immich through Immich's own job queue. R-1007 updated; the scripts' run on 9202 added as evidence.

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-14 16:58:35 +02:00
admin a6acb0f762 Hub v0.149.0: clamp a future deliberate-off time; hold a customer only when all its hosts are off (R-998)
gates / gates (push) Successful in 6m27s
Security review of 50e47e29: requested_at is the box's clock — a future value is cut to the hub's
now; CustomerDeliberatelyOff now needs every host of the customer held (one machine of two no
longer silences the other), and fails closed on a read error or no host. Both red-proofed.
2026-10-13 19:52:12 +02:00
admin 50e47e29af Hub v0.149.0: a box the household switched off is not an outage for 14 days (R-998)
gates / gates (push) Successful in 6m40s
hosts.deliberate_off_at follows the agent's deliberate_off field (set, then cleared by the first
report of a new boot; one info event each way). While held, every silence alarm is held: host and
node staleness, the 05:00 backup deadlines, off-site and restore-test freshness, the OS alarms and
the kernel notice. After 14 days the usual alarms fire once, naming the power-off. Pages show
KIKAPCSOLVA and the time. Consequence tests with controls; each guard red-proofed.
2026-10-13 19:47:02 +02:00
admin 013ee81369 hub (tests only): five cross-box refusal tests (security review part 3); R-955 filed (100 -> 101 rows)
gates / gates (push) Successful in 6m25s
2026-10-12 17:06:51 +02:00
admin b67b8cea8f hub v0.148.0 (code): SECURITY — the customer list and box reports need the operator key (R-951); R-950 rotated; R-952, R-953 filed (97 -> 99 rows)
gates / gates (push) Successful in 6m8s
2026-10-12 16:51:42 +02:00
admin e5b9151e05 hub (unreleased, SECURITY): /preferences and /notify refuse a per-customer key acting for another household (403); red-proved
gates / gates (push) Successful in 5m49s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-09 12:48:54 +02:00
admin d55c590c5a hub (unreleased): R-922 option A — a household's clear deletes its notification address (email_cleared); MAIL-HOLD — a restored hub sends no mail until released; two log lines drop the address; runbooks: mail hold is restore step 1; 07 §6.4 R-921 pre-check; R-921/R-922 narrowed
gates / gates (push) Successful in 5m25s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-09 12:37:29 +02:00
admin 87af859fc3 hub: operator actions for a box (D1, R-314/R-279/R-177, decision 185)
Host page "Operator Actions" card: run off-site backup now, run a check now
(fixed job list), stop / extend (1-30 days) a deletion countdown. POST
/hosts/{id}/operator-action validates against the CLOSED list before
storing (unknown -> 400, no row), stores operator_actions(id, customer_id,
action, arg, requested_at, requested_by, done_at, outcome, message), logs
who pressed (channel + address) and bumps the box's intent. The report ACK
lists pending rows as operator_actions until the box's
operator_action_results closes them (matched on id AND reporting
customer); each closed row becomes a hub-minted operator_action event
(stored, never dispatched). Unanswered after 24 h: expired. A customer
RESET cancels pending rows. Wire gate: new root + field-by-field mirror
(controller report.OperatorAction) — needs the controller commit first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 15:17:06 +02:00
admin d604e624a3 hub: box presence from the wait channel + delete a switched-off box at once (R-30, D2)
Slice 1: intent.Hub records one start/end per GET /api/v1/wait request and answers
Presence(customer, now): connected (hold open, or one started < 333 s = 243 s cadence + 90 s
grace ago), not connected since T, or unknown (hub up < 333 s; in memory only). The host page
shows "Box connection". One DEBUG line per presence change.

Slice 2 (operator ruling D2, 2026-10-08, 09 §3 decision 186): a host that is online by its report
clock but whose box has had no wait-channel connection for >= 360 s may be deleted at once after
the tick "I checked: the box is off". Presence is re-read at POST time; the tick alone, unknown
presence, a connected box or a shorter gap keep today's 409. The delete logs the operator channel
and saves one host_deleted_box_off event. RESET and the customer-delete cascade are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 15:17:05 +02:00
admin 5beedcce1a R-304 option C (hub half): recovery_older_package allowlisted and operator-only; design + row updated
gates / gates (push) Successful in 4m13s
Unreleased; ships with tomorrow's hub release.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 10:09:20 +02:00
admin b119301c6f R-243: offsite_escrow_pending — an operator alarm when off-site is on and the escrow never done (7 days); 09 decisions 177-179; 07 R-899 note
gates / gates (push) Successful in 2m48s
Hub code unreleased; ships with tomorrow's hub release.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 08:00:08 +02:00
admin 9c94a9c6c0 R-366 slice 2 (decision 168): one operator line when the box's whole-guest archives include another key's (edge-triggered)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 10:21:25 +02:00
admin aeca52ea54 R-105 (decision 169): retire the never-built slim DR record fields (no writer, no reader); 05 §9/§11, 06 §3.5 corrected
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 10:21:25 +02:00
admin b3c835625d R-330: the hub models SMART 187/188/199 in the host-report (G-1; nothing alarms on them yet)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 22:03:49 +02:00
admin 74009014aa R-366: the hub retains the escrow when the whole-guest backup key changes
A reinstall mints a new PBS key K while R-241 keeps the restic password, so
the supersession rule (restic sha only) overwrote the only copy of the old K
and every pre-reinstall whole-guest archive became unopenable for good. The
current row is now also retained when the key fingerprint changes (case and
space ignored; an empty fingerprint is unknown, not a change).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 20:45:00 +02:00
admin 5f060e3d1e R-879: seal box API keys, owner passphrases, controller keys and PBS-DR tokens at rest
hosts.api_key, customer_configs.api_key / retrieval_password and host_pbs_secrets.value now hold the
R-821/R-133 seal (enc:v1:, OFFSITE_SECRET_KEY). The two API keys get an api_key_hash lookup twin
(SHA-256, backfilled keyless in migrate()), so box authentication never needs the sealing key; a row
with no hash is matched on its plaintext only while it is plaintext. SealLegacyBoxSecrets seals legacy
rows at start-up (idempotent, non-fatal). A sealed value that does not open sets SecretsUnreadable:
serve/compare paths answer 500, saves refuse the record, the PBS token is not burned.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:45:04 +02:00
admin b26d292a64 burn-down Part B: 14 small rows fixed and closed across four repos (306 -> 292); no :latest in the hub build; gate list pinned; closed-id duplicates refused; R-262 subset pinned
gates / gates (push) Failing after 1m40s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 17:10:38 +02:00
admin 6da3a7d866 hub v0.134.0: a down box is judged on longer missed-backup lines (R-872); household outage mail at most weekly (R-873); backup_catchup_done allowed (R-871)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 09:24:14 +02:00
admin ff1db11db4 hub v0.133.0 (R-859 test approvals end with the test; R-840 bundle on the System page, manifest, alarm); installer 1.31.0 (root files from the config bundle); bundle bootstrap script; golden 0.293.0 evidence; rulings 96–99; drill-r50 removed (evidence)
gates / gates (push) Successful in 29s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-04 20:18:37 +02:00
admin 175ecfcdd2 hub v0.132.0: the System page (versions + OS updates with the ring/switch/approve buttons, R-852), the Hosts Proxmox/kernel column, the operator-approved Docker engine release (2 healthy ring-0 nights), the crash-guard events (R-851); evidence audits/os-docker-crash-2026-10-04
gates / gates (push) Successful in 30s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-04 16:16:02 +02:00
admin 88b0a2e761 hub v0.131.0: the tunnel status is true (R-841: three states, tunnel_down after two not_running reports, unknown never alarms); OS updates per layer (guest/host separate approved sets, host candidate leaves out kernel/boot/firmware, host_release in the box block), the fleet view and four hourly operator alarms (11 §8 steps 3+4); red-proofs in audits/os-host-lane-2026-10-04
gates / gates (push) Successful in 30s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-04 13:05:00 +02:00
admin c5f91174f6 hub v0.130.0: OS updates, guest fast lane — rings, per-box switch, OS releases approved from ring 0, os-report, os_update desired block
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-04 10:56:39 +02:00
admin 55f7621c90 hub v0.129.0: operator raises ONE clean-up window's cap (R-833); restore-beside script + runbooks (R-834)
gates / gates (push) Successful in 30s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-04 08:56:56 +02:00
admin d3c50b50f6 hub v0.128.0: set-aside deletion through the hub after a 7-day wait (decision 74, R-823), key-file clean-up route (R-826), read-only key check (R-827), window cap = half
gates / gates (push) Successful in 29s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-04 07:05:21 +02:00
admin f417cdede1 hub v0.127.0: off-site key registrar (box never gets the storage password), password sealed at rest, daily key check, clean-up window (shipped off) — decisions 68-69, R-820/R-821/R-822
gates / gates (push) Successful in 29s
Part A evidence (migration spike, sftp-written repo through the pinned rclone key) and the hub
red-proofs under documentation/audits/offsite-lock-build-2026-10-03/. Manifest bump follows after
the image is built and Secret/offsite-secret-key exists.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-03 16:57:04 +02:00
admin 99c0709cbe hub v0.123.0: app_stopped_unhealthy (decision 28); 09 decisions 26-28 recorded
gates / gates (push) Successful in 31s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-24 11:38:13 +02:00
admin e4d45a8f72 hub v0.122.0: app_hold_no_whole_copy — allow-listed, operator-only, per-app cooldown (R-659)
gates / gates (push) Successful in 28s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-24 07:33:04 +02:00
admin 511969928d hub v0.121.0: app_oom_storm allow-listed, operator-only, per-app cooldown (R-636)
gates / gates (push) Successful in 24s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-23 17:17:12 +02:00
admin d3b284863e hub v0.120.0: app_update_undone/held reach the household, per app, in its language
gates / gates (push) Successful in 26s
Allowlisted, not operator-only, seeded for new households and added
once (add-only) to every existing enabled_events row. mail.event entries
in hu and en name the app from details.stack_name. Per-app cooldown on
both the operator and the household leg.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-23 13:47:13 +02:00
admin 9167cf53af hub v0.118.0: the household's e-mails follow the household's language (R-558 Part A)
gates / gates (push) Successful in 23s
The hub has written every customer e-mail in Hungarian whatever the box was set
to. The box has published its language since controller v0.247.0; nothing read
it. Now it does.

Nothing an operator reads changes. The Hungarian mails are byte-identical, and
that is a diff rather than a reading: 56 goldens per language captured from
v0.117.0 BEFORE any string moved, and all 56 Hungarian ones pass unchanged after
every sentence was routed through the new bundle.

- internal/i18n: flat bundle, 79 keys, hu authoritative + hu fallback, ceiling 0.
- customerMessages/severityLabels are DERIVED from the bundle, so a sentence is
  written in one place and all 40+ tests that read those maps still work.
- Language order: last reported -> created-with -> hu. reports.language defaults
  to EMPTY, never hu: "never told us" is not "chose Hungarian".
- message_customer on POST /api/v1/event, additive and optional forever, for the
  sentences the box composes and the hub cannot translate.
- The bind page is per-language, and its `expired` state stays Hungarian: it is
  the state an unknown token lands in, so rendering a real English customer's
  token in English would make the LANGUAGE answer what the TEXT refuses to.

Two defects found inside the release:
- R-581: the newest report was picked by received_at, which has SECOND
  granularity, so same-second reports tied and the winner was arbitrary. Ordered
  by the autoincrement id now. GetCustomers() still has the shape - row open.
- R-582: the English copy-guard stems, ported word for word from Hungarian,
  convicted 141 honest sentences. The English claim is a phrase with a modal.

R-555 closed: the language allowlist entry is out of wire_contract_gate.py.
hub_copy_gate.py follows the sentences into the bundle - without that it would
have scanned four files that no longer hold any customer text and reported
success. Three new decoys incl. an innocent control.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-18 16:20:11 +02:00
admin 37ae31fd44 hub v0.117.0: the status follows the configured threshold; slow crash loop and interrupted restore events
gates / gates (push) Successful in 21s
R-549 (operator ruling A): controllerStatus hardcoded 30m/1h while both
staleness checkers and hostStatus read alerting.stale_threshold. Moving the
threshold to 45m would have painted a customer amber 15 minutes before the
alarm could fire - the second definition rollup.go's header forbids. It now
reads the same value, down at 2x. Both 'checker initialized' log lines print
the threshold, which no line did before.

R-539 (ruling 3 of 2026-09-16): controller_slow_crashloop (warning,
operator-only), minted when the agent's slow_crashloop_since moves, with the
fast sibling's first-sight rule.

R-550: restore_interrupted (warning, for the household) allowlisted with a
Hungarian customer message.

Red-proofs, each seen failing then passing: the status test with the old
hardcoded numbers; the checker test with the movement branch removed; the
operator-only test with the registration removed; the household-message test
with the Hungarian entry removed (asserted on the SUBJECT - the body
legitimately repeats the raw message, which my first version of the test
mistook for a fallback).

go build/vet/test ./... green, 18 packages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-17 10:20:32 +02:00
admin 3738dfc548 hub v0.116.0: every new customer starts WITH the off-site copy (operator ruling)
gates / gates (push) Successful in 19s
Off-site is ON by default for a new customer — shared, 100 GB soft quota prefilled,
the checkbox kept so an operator can opt a customer out. The reason is this repo's
own [FACT]: the whole-guest tiers do not carry the data drive and a Tier-1 unit has
no file leg, so with this unticked a one-drive box keeps NO copy of the household's
own files. Measured on a fresh box the same day.

The quota is prefilled because the fill warning only fires when quota_gb > 0.

Also registers controller v0.244.0's app_deploy_started / app_deploy_failed in both
allowedEventTypes and customerMessages, per the rule that the two move together.

Red-proofed: dropping the default fails the new render test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-16 16:56:01 +02:00
admin 07959e61b5 hub v0.114.0: self-bind auto-send while a customer waits for a box (R-509); node_* bypass the quiet hour (ruling 2026-09-15); PBS re-issue adopts an endpoint token (R-511); controller supervisor events (R-523); event registers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-15 10:05:41 +02:00
admin f181efd6a7 hub v0.112.0: a floor carries a declared MinAgent past the golden (R-472)
gates / gates (push) Successful in 18s
Operator ruling 2026-09-13. Above the vouched golden, a floor saved with a
declared MinAgent is served under the same agent comparison; an undeclared
one is still held beyond the golden. The declaration is stored beside each
floor as FLOOR=MINAGENT so it never carries to a later floor. Both floor
forms require min_agent above the golden (flash floor_needs_min_agent,
nothing stored). The Hosts page and the API log name the source.

Vouch path and R-120 gate untouched. Scenarios A-E tested; red-proofs A
and C in documentation/audits/rulings-r472-r475-2026-09-13/.
2026-09-13 16:47:11 +02:00