D53 built + live-proven (08 §10 [DESIGN — built]); R-1297 decoys: register-shape decoys assert the script's exit
gates / gates (push) Successful in 3m25s

- 08 §10: built (controller 5bd03ad, hub 7e57e824, commit only); putback_pending as on the wire; as-built notes
- audits/d53-held-apps-2026-10-26: live proof on 9202 against a test hub (3-min grace), red-proofs, teardown
- R-1291 BUILT (not released); R-1298 filed (9202's orphan holds + PrivateBin leftover)
- test_gate_decoys.py: the register-shape cases also run the script and assert its exit code — R-1297's decoy 2
  showed an inert main() passed every case (9 cases red with it now)
- audits/r1297-ci-trim-2026-10-26: runners, times, decoys
This commit is contained in:
admin committed 2026-10-26 19:03:07 +01:00
1 parent 7e57e824a2
commit e33ec8210a
23 files changed
+2464 -7

No files matched your search

+16 -5
View File
@@ -610,7 +610,7 @@ normal use; work it does not explain is the sign of a hacked app. Numbers and me
(Samba) has no counter; the push floor is a lower bound, the weekly test is close to the line.
7. **Release:** released 2026-10-24 on the operator's yes (controller v0.342.0, hub v0.169.0; R-1244) — corrected 2026-10-24.
## 10. A held app the operator can see [DESIGN — proposed, R-1291, 2026-10-26; no code]
## 10. A held app the operator can see [DESIGN — built 2026-10-26 (commit only): controller `5bd03ad`, hub `7e57e824`; D53 = operator-only, `09` §3 decision 265; R-1291]
**Why.** A held app is stopped on purpose and stays stopped until a person acts — and today nobody is told after the
first minute. demo-hp's Kimai sat held for 11 days (2026-10-14 → 10-26) and was found by accident (R-1286). The
@@ -625,7 +625,7 @@ anything, and the hub has no held-app state at all. On a household box the same
| `restore_mixed` | an off-site restore whose database replay failed | a person (the same) |
| `update_failed` | a failed update | the household, by restoring the app from its backup |
| `unhealthy_stop` | the crash-loop guard | the household's Start (one more try, `09` §3 decision 28) |
| `put_back_pending` | a restore waiting for its pre-restore copy | nobody — it clears itself when the drive comes back |
| `putback_pending` | a restore waiting for its pre-restore copy | nobody — it clears itself when the drive comes back |
**What the controller reports.** The legacy report is frozen (hub rule), so the event channel carries it:
`app_held` when a hold is written (stack, reason, since — the hold's own `At`) and `app_hold_cleared` when it goes.
@@ -636,7 +636,7 @@ treats it as idempotent. Both types enter `allowedEventTypes` AND `customerMessa
**Where the hub shows it.** The host page (and the customer page) get a „Held apps" list: app, reason in one line
(the `holdWhy` sentence), since, and who may clear it. Built from the open `app_held` events per customer and stack.
**When it mails.** One operator mail per hold after a grace that follows the reason: `put_back_pending` 6 hours (it
**When it mails.** One operator mail per hold after a grace that follows the reason: `putback_pending` 6 hours (it
should have cleared itself — if not, something is stuck); `restore_failed` / `restore_mixed` 1 day (only a person can
act); `update_failed` and `unhealthy_stop` 3 days (the household can act first). Then one reminder a week while it
lasts, through the dispatcher's existing per-type cooldown (§6.2). A cleared hold sends nothing.
@@ -647,5 +647,16 @@ never clears a hold** — it only shows and reminds.
**Cost.** One controller release (the two events + the daily re-send, ~½ day with tests) and one hub release (allow-list,
the i18n keys, the list on two pages, a reminder checker; ~1 day). No agent change.
**Open pick (STATUS D53):** v1 operator-only (CC's pick), or also mail the household for the two holds it can clear
itself („press Start" / „restore from the backup")?
**Ruled (D53, operator 2026-10-26, `09` §3 decision 265):** v1 is operator-only. Household mails for the two holds it can
clear itself may follow once the operator list has run.
**As built (2026-10-26, commit only — releases ride an attended run).** The wire reason is the controller's own constant:
`putback_pending` (one word), and the empty legacy reason is sent as `restore_failed`. The controller's reporter is ONE
observer of the hold store, ticked every minute (`internal/holdreport`), never a send inside a hold writer; the set it
last reported is kept in settings, so a hold cleared while the controller was down is still reported cleared. The hub
mirrors the events in `held_apps`, sends `app_held_reminder` (warning, operator-only, per-app cooldown, the subject
names the app) once after the grace and then weekly, records the reminder before it sends it, and does not remind about
a row the box stopped repeating for 50 h (the list still shows it, marked). `alerting.held_app_grace_override` replaces
every grace — a test configuration only. Live proof: `audits/d53-held-apps-2026-10-26/` (a crash-looped throwaway app on
9202 against a test hub with a 3-minute grace: listed on both pages, one operator mail, Start cleared it, the row went,
every household leg `skipped operator_only`).