docs(R-116): CLOSED — proven live; capability row F to PROVEN-LIVE; R-120 filed

The events leg the previous commit reported as not-reached is now done. The operator
relayed the claim code (the only route: bcrypt-hashed hub-side, emailed only), the
two storage paths were registered through the real POST /api/storage/register, and
the cycle ran on the fresh box:

  07:20:04  backup_target_absent   (error)  Cel meghajto   <- TARGET, specific
  07:22:34  backup_target_restored (info)   Cel meghajto   <- its matching pair
  07:24:04  storage_disconnected   (error)  Adat meghajto  <- NON-target, generic
  07:25:34  storage_reconnected    (info)   Adat meghajto

All four at the hub; gate fired in 3 s. Two matched pairs, correctly discriminated
-- and discrimination is proven NON-trivially for the first time, since both prior
runs had the target itself emit the generic event. Over-correction passes on a
positive observable, with two RETURNED lines proving the gate was ticking.

00-capability-map row F: PARTIAL -> PROVEN-LIVE with the evidence and the caveat.

R-120 filed: the golden bakes controller 0.185.1, which PREDATES R-114 + R-112, so
a freshly installed box shows the customer the WRONG absent-target message --
observed live on the drill box: the generic "the backup is on the same disk as the
system" copy (false; the target is a drive that vanished) plus an offer of the other
drive as the remedy. That is E2D 5.3's exact payload, still reachable on any new
install. R-115's class one layer up -- R-111 closed by re-baking the golden, 0.186.0
then shipped, the golden did not move, and the gap reopened silently; this time the
stale artifact carries a customer-facing falsehood in exactly the state R-116 now
alarms about correctly.

Teardown recorded for all three layers, hub layer gate-blocked with the command.
This commit is contained in:
2026-07-30 09:34:08 +02:00
parent 315c469fc8
commit 772956d214
3 changed files with 77 additions and 23 deletions
@@ -121,7 +121,7 @@
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| An ABSENT backup-target drive raises its OWN alarm, paired with a matching recovery | agent v0.114.0, controller v0.184.1+, hub v0.81.0 | **PARTIAL** | `SESSION-C-2026-07-29` C5: the drive-absent gate fires (4 s) and an alarm reaches the hub — but it is the **generic** `storage_disconnected`, while the return fires the **specific** `backup_target_restored`, so the pair cannot be matched. `backup_target_absent` never fired (count 0) | RE-TESTED 2026-07-30 on the fully shipped stack (`R116-PART5-2026-07-30`) — **still generic**; the v0.115.0 fix was ineffective and the mechanism is not isolated. The specific alarm, its severity, Hungarian copy and hub routing remain unexercised end-to-end**R-116** |
| An ABSENT backup-target drive raises its OWN alarm, paired with a matching recovery | agent **v0.116.0**, controller v0.184.1+, hub v0.81.0 | **PROVEN-LIVE** (2026-07-30) | `audits/R116-v0116-2026-07-30.md`. On a fresh box built through the **real day-0** on demo-hp, running the agent it installed **unaided from the vouched Day-0 manifest** (0.116.0), both drives enrolled through the real endpoints and device loss a real hot-detach — **the full four-event sequence, two matched pairs, correctly discriminated:** `07:20:04 backup_target_absent (error)` / `07:22:34 backup_target_restored (info)` for the TARGET, and `07:24:04 storage_disconnected (error)` / `07:25:34 storage_reconnected (info)` for a NON-target drive on the same box minutes apart. Gate fired in **3 s**. All four reached the hub — specific alarm, severity, Hungarian copy and hub routing now exercised end-to-end. **Discrimination is proven NON-trivially for the first time**: both prior runs had the target itself emit the generic event, so the mirror proved nothing. **Over-correction guard PASSES** with a positive observable — 0 ABSENT lines and 0 drive events over a 2m14s window with both drives present, target `degraded:false`, while 2 `RETURNED` lines prove the gate was ticking. | **The mechanism was isolated from the captured payload first** (`DIAG-r116-disks-payload-2026-07-30.md`), after two fixes aimed at shapes that do not occur. v0.116.0 joins the two records of one drive on the only identity that survives the device — the CONFIGURED path — so one row carries both the flag and the guest path the gate keys on. **Both smaller-looking fixes were rejected because they regress R-114** (`backup_target_offer.go:79` reads flag+mount_path as *healthy*). **Caveat worth reading: the drill box ran controller 0.185.1 from the golden, which PREDATES R-114** — so its absent-state banner showed the old false "backup is on the system disk" copy. That is the golden being a release behind, not a regression**R-120** |
| Health-degradation email (edge-triggered, cooldowns, Hungarian) via hub → Resend | controller, hub | **IMPLEMENTED** | delivery pipeline live-proven for the **enlarge-block** trigger (`CAMPAIGN-6D` P3-DELIVERY, op+customer "Kedves Ügyfél!"); `NotifyHealthChange` ok→warn/fail edge-trigger implemented | The **health-degradation** trigger specifically has never fired an email live in any doc. Demoted (pipeline proven for a different event). Deliverability to HU freemail → R-4 |
| Event catalog: app_start_failed, dead-app, offbox_enlarge_blocked, claim/reset codes, critical severity | controller, hub v0.31/48/50/55 | **PROVEN-LIVE** | live-delivered: `CAMPAIGN-6D` P3-DELIVERY (enlarge-block, op+customer); `DRILL-day0-vm` F-4 (claim code); `DRILL-day0-take2` F-15 (reset code) | `app_start_failed`/`dead-app` delivery is unit-only (6C inconclusive) — the pipeline + 3 event families are live, those two are not |
| Prefs safety: empty-email wipe guard | controller v0.137 + hub v0.71.0 | **IMPLEMENTED** | controller leg red-proofed 07-15; hub-side no-clobber belt (`handleSavePreferences` preserves a stored non-empty address on an empty-email push) red-proofed 07-22 | Born from a live incident; controller 0.160.0 guards both its push legs, so the hub belt covers older/rogue boxes |