gh shim: a valid bot write is no longer refused when its shell is sealed or backgrounded mid-write
A valid bot write (MC's comment at 23:10Z) was refused once with task_gh_authority_unavailable … (snapshot_invalid); the same command went through a minute later. Nothing was posted wrongly, but a valid write shouldn't be refused.
Cause: a foreground bot write records its authority record's generation at preflight. Between preflight and final admission, a normal lifecycle step bumps that generation: the command's shell being sealed (first seal of a candidate), or the command moving to the background (activation). The final gate then saw a different generation and refused.
Fix: revalidate_authority (crates/aft/src/db/gh_speech.rs) reloads the same incarnation, which checks revocation and scope end. It then requires the record to be identical to the preflight record apart from the seal, and allows exactly these steps:
- a first seal with valid PID, start time and birth identity, only from
candidate; candidate→active, only with this request's own ticket digest;- generation equal to the previous one plus exactly those steps, using checked arithmetic.
Anything else refuses with snapshot_invalid as before, with nothing sent. That covers a changed agent, owner, scope ref or epoch, route, flow, repository set, binding identity or binding generation, any unrelated generation bump, a revoke, and a scope end. Seal and activation now share the admission mutex with the final refresh. Each refusal logs which check failed, without record contents, tickets, nonces or bodies.
Tests: gh_shim_speech/lifecycle_dispatch_tests.rs runs through the production relay with substituted partners. Promotion or sealing between preflight and admission posts exactly once, and each identity change, a revoke and a scope end refuse with zero sends. db/gh_speech/tests.rs covers the exact step arithmetic and the warnings.
Security audit (report-only, top tier): ship. No reachable bypass was found, so no proof test was added. Low-severity coverage notes, not defects: the first seal's association with its command relies on the trusted synchronous spawn-ticket callback, and the local fake provider doesn't exercise PR-own-author enforcement. Optional hardening would add a wrong-command first-seal regression. The audit's 86 filtered tests passed on Linux 12-core on this branch.
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Valid bot writes are no longer refused when the command's shell is sealed or backgrounded between preflight and final admission.
- The root cause was a generation bump from a lifecycle step (first seal, activation) between preflight and the final gate, which the gate treated as an invalid snapshot.
revalidate_authoritynow reloads the same incarnation and accepts only those exact lifecycle steps, rejecting any other change to the authority record (agent, owner, scope, route, bindings, revoke, scope end) withsnapshot_invalidbefore anything is sent.- Seal and activation now run under the admission mutex shared with the final refresh.
- Snapshot refusals now log a single warning with the failed check and safe identifiers only, never tickets, nonces, payloads, or raw errors; standalone gh shim warnings go to the process log before logger initialization.
- Added lifecycle dispatch tests that post exactly once when promotion or sealing happens between preflight and admission, and refuse with zero sends for every identity change, a revoke, and a scope end.