Close handover race, upgrade readiness and gateway rollback rehearsal gaps

Record real-core delay-gate tests and actual gateway rollback evidence;
require unsubscribe rather than an unsafe ID-only re-key. Keep the
external native installation gate explicit pending read-only inspection.

Card: SAU-384
This commit is contained in:
SAU-384 implementer
2026-10-31 13:31:06 +00:00
parent 37e216a3c8
commit 8bf2a3c661
3 changed files with 52 additions and 9 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
# One-off handover operator runbook — blocked draft
Read [rehearsal/results](SAU-384-rehearsal.md), the [authority](/docs/design/plugin-handover/design.md) and [approval gates](/docs/symphony/artifacts/SAU-356/plan.md). This is **not** authorization to execute. Workers must not perform these live steps. Mediator/orchestrator alone lands and executes.
Read [rehearsal/results](SAU-384-rehearsal.md) and [resume verification](SAU-384-resume-1369.md), the [authority](/docs/design/plugin-handover/design.md) and [approval gates](/docs/symphony/artifacts/SAU-356/plan.md). This is **not** authorization to execute. Workers must not perform these live steps. Mediator/orchestrator alone lands and executes.
## 0. Finish the installation manifest (no live mutation)
@@ -13,7 +13,7 @@ Bundle: `/docs/symphony/artifacts/SAU-384/target-artifacts.tar.gz`.
- Inventory executable caller payloads in cron jobs, boot and other saved callback/action/configuration stores using their predecessor schemas. History text mentioning an old RPC is not an executable payload. The tested converter covers `jobs.data` where `method == session.send`; it does not claim a full live caller-store audit. Unknown executable references, `session.work`, `session.cancel`, ambiguous `interrupt:true`, invalid text or unexplained notify destinations stop preflight for explicit resolution.
- Source references for predecessor formats: session `f9122585`, `src/main.rs` Paths (`pending.jsonl`, `cancel`) and `src/queue.rs`; cron `ba75c102`; target cron README's one-off conversion procedure. Active old component hashes are separately captured; do not equate a source reference with its compiled active binary without checking.
- Confirm the frontend artifact is approved commit `3d76026749a5d21722033bbfe8743ac368946b0f`; keep `publish:hold` until step 5. Do not publish a worktree snapshot or release it early.
- Resolve the rollback rule before execution: an ID-only re-key is **unsafe**. Use explicit unsubscribe, and prevent the new gateway from re-registering `web-chat` against an old session binary. A different proposed “re-key” needs its own defined semantics/rehearsal.
- Rollback uses the card's explicit **unsubscribe** option. ID-only re-key is **unsafe**, proven again with the actual old manager and gateway in run 1369. Prevent the gateway from re-registering `web-chat` against an old session binary; never call `web.start` in that state. A different proposed “re-key” needs its own defined semantics/rehearsal.
## 1. Obtain approvals, then close ingress/ownership
@@ -23,7 +23,7 @@ Run the one-off controller **outside the world and outside the service/process g
Close the actual ingress and stop the **external host/service owner** synchronously using the pinned command. Await its shutdown/process-exit completion, not a loop over `/proc`, endpoint retry, sleep, or a set of stop requests. If an outer launcher would respawn the host, deliberately stop that owner too; do not edit boot config while agents can still run. `core.restart`/exit-75 is a restart request, not stop-all. The real core's `Host.stop` suppresses service restart admission and stops all trees in parallel. Design budgets are grace 5 seconds and separate EOF-stop 5 seconds, not arbitrary new timeouts.
The rehearsal's native external controller awaited `Host.stop`, asserted its process table was empty, then awaited host exit. The live equivalent needs the actual launcher identity from step 0. **That identity is currently missing; do not invent a unit name.**
The rehearsal's native external controller awaited `Host.stop`, asserted its process table was empty, then awaited host exit. The live equivalent needs the actual launcher identity from step 0. **That identity is currently missing; do not invent a unit name.** Source config has `services.sausage.enable = false` and describes a Herdr panel; read-only systemd-web inspection corroborates a user Herdr socket, not a system `sausage.service`. Credential request `055995a51608c57dd25b323bea731fcb` awaits approval for read-only inspection to pin the actual panel/launcher. It is not permission to stop or change it.
## 2. Back up frozen state and plan changes
@@ -82,6 +82,6 @@ Verify the published approved asset hashes and ingress once, mark the migration
| Before offline mutation | Stop with evidence; old frozen world is untouched. |
| During swap, target never started | Resume the saved hash-guarded plan, or restore the full frozen backup and old external owner/configuration coherently. Do not partially start mixed contracts. |
| Any target start attempted | No automatic full restore/reapply. New histories, mail, jobs, grants or external effects may already exist. Preserve new state; diagnose and plan a narrow forward repair/revert. Never blindly rerun an external effect or undo new work. |
| Session revert after target activity | A new approved operation: close gateway/ingress, `session.unsubscribe {id:"web-chat"}` while the new manager is still available, verify removal, prevent gateway re-registration while old session runs, then coordinate the stopped version change. Do not restore a registry backup that reintroduces the registration. ID-only rename is proven unsafe. Full actual gateway revert remains unverified. |
| Session revert after target activity | A new approved operation: close gateway/ingress, `session.unsubscribe {id:"web-chat"}` while the new manager is still available, verify removal, prevent gateway re-registration while old session runs, then coordinate the stopped version change. Do not restore a registry backup that reintroduces the registration. ID-only rename is proven unsafe. Run 1369 verified this with the actual gateway left running and no re-registration: zero historical callbacks after unsubscribe; ID-only re-key replayed history. Physical browser/SSE display is not claimed. |
Independent plugin recovery follow-ups remain independent. Neither uniform grace nor this one-off migration proves their external side effects, usage accounting, crash recovery or provider cancellation are solved.