Skip to content

feat(trusty-console): webhook ingress with a spool that is durable before the ack (#5089 step 3) - #5175

Merged
bobmatnyc merged 5 commits into
mainfrom
feat/5089-3-console-ingress-spool
Aug 8, 2026
Merged

feat(trusty-console): webhook ingress with a spool that is durable before the ack (#5089 step 3)#5175
bobmatnyc merged 5 commits into
mainfrom
feat/5089-3-console-ingress-spool

Conversation

@bobmatnyc

@bobmatnyc bobmatnyc commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Defect

Both existing webhook handlers return 202 and then do the work, so any failure after the ack loses the delivery permanently — GitHub never retries an acknowledged delivery, and every health signal still reports green.

  • crates/trusty-review/src/service/webhook.rstokio::spawn at :240, ack at :322-329, failure written only to an in-memory Mutex<Option<String>> at :305-309.
  • crates/trusty-analyze/src/service/handlers/review.rstokio::spawn at :210, ack at :216, failure is a bare tracing::warn! at :211-213.

Neither handler is modified here. They stay live until step 4 retires them; this builds the console path that replaces them.

Resolution

POST /api/webhooks/{source} multiplexes review and analyze. The order of operations is the fix, per ADR-0034 §2:

  1. unknown {source}404, before any secret handling;
  2. HMAC verified once over the exact received bytes — unset secret and bad signature both 401, unifying the policy to trusty-review's fail-closed answer;
  3. the delivery is written and fsync'd to a spool under resolve_data_dir("trusty-console")/webhook-spool/on failure 500, and no 202 is ever sent, so GitHub keeps the delivery redeliverable;
  4. the relay runs and its outcome is recorded durably;
  5. 202, because step 3 succeeded — not because step 4 did.

Per failure arm:

Arm Behavior
Spool write fails 5xx before any 202. The relay never runs — asserted, not assumed.
Relay fails (expected until step 4) Entry stays pending, attempt count and reason written durably, sweep retries. Never deleted on failure.
Connected but not acknowledged ack is #[serde(default)] false, so a result object without it is Refused. Only RelayOutcome::Acked reaches the one deletion path.
Pending entry ages out GET /api/console/metrics/webhooks goes red. It scans the spool on the request, not from a cache, so the signal does not go quiet if the retry sweep stops. A spool that cannot be read is red, not empty.

Durability is a temp write → sync_all the file → rename → sync_all the directory, so the entry's name survives a crash too, not just its bytes.

Shared entry points, not a fourth copy

  • trusty_common::uds::rpc::send_framed_request — the framed UDS transport ADR-0034 §4 names, dialling through connect_hardened so the 0700 directory and 0600 socket are verified before a byte is written. Caps the response and bounds the exchange with a timeout. The four existing hand-rolled clients migrate onto it in a documented fast-follow, per the PM's scope call.
  • trusty_common::webhook_hmac (feature webhook-hmac) — one GitHub signature verifier, returning a three-state SignatureVerdict so "no secret configured" cannot collapse into permission to proceed, which is the shape of trusty-analyze's live fail-open. The two existing copies are retired in step 4.

Spawn-on-demand (calling step 2's UdsServiceSupervisor) is deferred to step 4 — no target binds a listener yet, so it would be dead code. Until then every relay lands in Unreachable, which is a durable pending state.

Testing — rung 5

Failure-path coverage is the deliverable. 43 new cases in crates/trusty-console/src/webhook/tests.rs, 7 in crates/trusty-common/src/uds/rpc.rs, 7 in webhook_hmac. Each arm above has at least one case that fails against the pre-fix shape (where all four are a 202 plus a log line):

  • ingest_returns_spool_failed_and_never_accepts_when_the_write_fails / route_returns_500_and_no_ack_when_the_spool_write_fails
  • relay_failure_leaves_a_pending_entry_with_an_incremented_attempt_count
  • connected_without_ack_never_deletes_the_entry / relay_treats_a_result_without_ack_as_refused
  • metrics_route_reports_red_for_an_aged_pending_entry / metrics_route_reports_red_when_the_spool_cannot_be_read

The spool-failure injection is a regular file where the directory belongs (ENOTDIR for every uid, root included), so it is deterministic in any CI container rather than depending on a non-root runner. The relay runs against a test-double UnixListener bound through bind_hardened.

--include-ignored integration coverage: integration_from_env_delivery_survives_a_console_restart drives the full loop against the real from_env wiring — verified delivery → durable spool → relay fails → a fresh ingress over the same directory still finds it pending with its body intact → the target comes up and acks → the entry is gone and health returns to Ok. These two are #[ignore]d because they mutate TRUSTY_DATA_DIR_OVERRIDE and GITHUB_WEBHOOK_SECRET, which every concurrent sibling in the binary can observe.

Gates run

cargo fmt --check                                                            — clean
cargo clippy -p trusty-common -p trusty-console --all-targets -- -D warnings  — clean
cargo test -p trusty-common                     — 294 passed, 0 failed, 6 ignored
cargo test -p trusty-common --features uds,webhook-hmac
                                                — 343 passed, 0 failed, 6 ignored
cargo test -p trusty-console -- --include-ignored
                                                — 193 + 2 passed, 0 failed, 0 ignored
bash scripts/check_line_cap.sh                  — 3797 files, 0 violations
bash scripts/check_sld.sh                       — 0 errors, 0 warnings
bash scripts/check_changelog_fragment.sh        — both crates recorded

Rung 4's cargo check --workspace passes for every crate except trusty-code-gui and trusty-mpm-gui, which both fail on tauri::generate_context! panicking over a missing ui/dist — a frontend build artifact absent in a fresh worktree, unrelated to this diff (which touches zero files in either crate). cargo check --workspace --exclude trusty-code-gui --exclude trusty-mpm-gui exits 0.

Refs #5089. ADR: docs/adr/0034-webhook-ingress-console-relays-over-uds-to-a-supervised-on-demand-process.md.

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools


Review round 1 — all three HIGHs plus four others (commit 92c1ed3fc)

HIGH-1 — the sweep and the request path relayed the same delivery twice. retry_pending_once listed every .json with no claim and no age filter, so a tick landing inside the ≤5 s relay window re-sent a delivery ingest was still sending. schedule::ClaimSet now gives one relay per entry path at a time, released on drop so a panicking relay cannot wedge an entry. sweep_does_not_relay_an_entry_the_request_path_is_still_relaying reproduces the critic's case — 600 ms delayed acking stub, sweep 150 ms in — and asserts exactly one frame reaches the target.

HIGH-2 — no backoff, contrary to ADR-0034 §2. Every pending entry was relayed every 60 s and each non-ack rewrote the whole base64 body plus two fsyncs. Until step 4 binds a listener that is every delivery, forever. BackoffPolicy holds a fresh entry for the relay timeout, then spaces attempts 30 s doubling to a 1 h ceiling, and stops at 24 failures. An exhausted entry is never relayed again and never deleted — it holds the health signal red until an operator intervenes, which bounds the write cost absolutely rather than just reducing it. A per-pass SWEEP_BUDGET of 32 keeps one serial pass from outlasting its own tick.

HIGH-3 — an absent spool directory reported green. list_pending answered ErrorKind::NotFound with an empty listing, so a removed console data dir or an unmounted volume made every POST 500 while /api/console/metrics/webhooks reported {"status":"ok","pending":0}. Ingress dead, alarm healthy — the exact contradiction between the PR body's claim and the code. Spool now records whether it was opened; for an opened spool a missing directory is SpoolError::ReadDir, which scan_health renders red. Spool::at on a never-created path is still legitimately empty, covered separately.

Body limit. 25 MiB on the webhook sub-router only. axum's 2 MiB default 413s a real push / pull_request delivery before the handler runs — no spool entry, no metric, no log. Same invisible drop, arriving through the framework instead of the code.

Wire contract moved to trusty-common. RELAY_METHOD, RelayFrame, RelayParams, Provenance and the response types now live in trusty_common::webhook_relay, with an owned RelayRequest for the receiving side and RelayResponse::{ack, refuse, is_ack}. relay.rs's "both halves read this constant" was not true as written — step 4's receivers cannot depend on the console.

persist_new commits with hard_link, not rename, so a colliding path fails atomically with AlreadyExists instead of clobbering a delivery that may already have been acknowledged. persist_update keeps rename semantics for record_attempt's deliberate overwrite. Temp files use create_new with a pid+nanosecond suffix.

Socket-dir comment corrected. It claimed the paths avoid the $TMPDIR convention ADR-0034 §3 rejects; scratch_socket_dir() is $TMPDIR/trusty-<uid> with a /tmp fallback. It now says what is actually true: #5099's 0700 uid-keyed directory plus connect_hardened's owner/mode re-check supersedes §3's path rule by satisfying the property §3 wanted.

The concurrency test class

Rung 5 for criterion (c) specifies failure-path and concurrency tests, and the first round had none — which is where HIGH-1 lived. Added: the sweep-versus-request race, two overlapping sweeps over two entries, two concurrent deliveries, claim exclusion, and claim release under panic. Plus five backoff_* cases and two sweep-schedule cases.

Regression proof

Each fix was reverted in place and the corresponding test re-run:

sweep_does_not_relay_an_entry_the_request_path_is_still_relaying ... FAILED
  assertion `left == right` failed: the sweep must see the entry as claimed, not free to relay
health_reports_error_when_the_spool_directory_is_gone ... FAILED
  assertion `left == right` failed: a spool whose directory vanished is broken, not empty
metrics_route_reports_red_when_the_spool_directory_is_gone ... FAILED
test result: FAILED. 0 passed; 3 failed; 0 ignored; 0 measured; 207 filtered out

route_accepts_a_body_larger_than_the_axum_default_limit ... FAILED
  left: 413
 right: 202

All four pass with the fixes restored.

Gates re-run

cargo fmt --check                                                             — clean
cargo clippy -p trusty-common -p trusty-console --all-targets -- -D warnings  — clean
cargo test -p trusty-common                      — 294 passed; 0 failed; 6 ignored
cargo test -p trusty-common --features uds,webhook-hmac,webhook-relay
                                                 — 348 passed; 0 failed; 6 ignored
cargo test -p trusty-console -- --include-ignored — 210 passed; 0 failed; 0 ignored
                                                 —   2 passed; 0 failed; 0 ignored
bash scripts/check_line_cap.sh    — 3799 tracked .rs files, 4 allowlisted, 0 violations
bash scripts/check_sld.sh         — 56 spec docs + 3143 code files; 0 errors, 0 warnings
bash scripts/check_changelog_fragment.sh — 18 changed paths; both crates recorded
cargo check --workspace --exclude trusty-code-gui --exclude trusty-mpm-gui — exit 0

The two excluded crates fail on tauri::generate_context! over a missing ui/dist build artifact, unrelated to this diff — unchanged from the first round.

Now non-optional for step 4

Target-side dedup on delivery_id. Console keeps a spool entry until an explicit ack, so a receiver that acknowledges after doing the work can still be re-sent the same delivery if the ack is lost. Relay is at-least-once by construction: duplicate delivery is the normal case, not the edge. RelayParams::attempts is a hint, never a guarantee that the first attempt did nothing — the doc comment on that field says so.

Deliberately out of scope this round, per review: the tctl doctor check (owned by in-flight #5018 / #5011), a console UI tab for the webhooks metric, and header denylist → allowlist.


Review round 2 — two HIGHs plus the runtime-blocking MEDIUM (commit aeba7970a)

HIGH-A — exhausted entries accumulated forever and every scan paid full decode for them. The sweep counted exhausted and continued; nothing deleted, quarantined, or aged them out. Since no target binds a listener until step 4, that is every delivery reaching 24 attempts in ~17 h and staying in the live set permanently, with both retry_pending_once and scan_health reading and serde_json-decoding it on every pass.

An exhausted entry now moves to webhook-spool/exhausted/. Kept, because it is still an unacknowledged webhook and still holds its body for a manual redelivery — but off both hot paths. Two new primitives make the scan cheap:

  • Spool::scan_metadata reads received_at_unix_ms and the delivery id from filenames and opens nothing. That is what entry_path's zero-padded timestamp prefix was always for; until now its stated rationale ("does not have to parse every file") was not realised anywhere, which was the MEDIUM at spool.rs:281.
  • Spool::load decodes the single entry the health scan actually needs — the oldest live one, for its attempt count and last error.

A filename that does not parse is reported through unparsable rather than dating to 0, which would read as the oldest entry in the spool and hijack every diagnostic.

HIGH-B — once red, the signal stopped saying anything new. SpoolHealth had no exhausted field, and SweepReport.exhausted reached exactly one consumer: a tracing::info! — the log line health.rs's own module doc names as the trap. Worse, scan_health took listing.pending.first(), and exhausted entries are by construction the oldest, so oldest_pending_delivery_id, oldest_pending_last_error and oldest_pending_age_secs pinned to the first poisoned delivery forever.

pending and exhausted are now counted separately, with their own ids and ages, and oldest_pending_* describes the oldest live entry. Any exhausted entry still forces status: Error — via its own field, not by hijacking the oldest-pending ones. total_failed_attempts is replaced by oldest_pending_attempts: the spool-wide sum cost one decode per entry per metrics request, which is what HIGH-A is about, and the oldest live entry's count is the actionable number.

sweep_stops_relaying_an_exhausted_entry asserted the old behavior as desired. It now asserts the entry leaves the live set, stays readable with its body byte-exact, and appears in the exhausted fields.

MEDIUM — spool I/O off the async runtime. All of it now goes through spawn_blocking. Ingest fsyncs a file and a directory twice per delivery; the metrics route scans two directories per request. A join failure is surfaced as an error, and WebhookIngress::health renders an unrunnable scan red rather than empty — same rule as an unreadable spool.

Regression proof

Each fix reverted in place and the corresponding test re-run:

health_diagnostics_track_the_live_entry_not_the_exhausted_one ... FAILED
  assertion `left == right` failed: the diagnostics must describe the LIVE failure, not the 30-day-old corpse
  left: Some("d-day-one")
 right: Some("d-day-thirty")
sweep_quarantines_an_exhausted_entry_and_stops_paying_for_it ... FAILED
  assertion `left == right` failed: an exhausted entry must stop costing a decode on every pass
  left: 2
 right: 0
test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 217 filtered out

Both pass with the fixes restored. The HIGH-B case is the one you asked for specifically: one exhausted entry from day 1 alongside a newer live entry failing on day 30, asserting the diagnostic fields describe the live one.

Gates re-run

cargo fmt --check                                                             — clean
cargo clippy -p trusty-common -p trusty-console --all-targets -- -D warnings  — clean
cargo test -p trusty-common                      — 294 passed; 0 failed; 6 ignored
cargo test -p trusty-common --features uds,webhook-hmac,webhook-relay
                                                 — 348 passed; 0 failed; 6 ignored
cargo test -p trusty-console -- --include-ignored — 219 passed; 0 failed; 0 ignored
                                                 —   2 passed; 0 failed; 0 ignored
bash scripts/check_line_cap.sh    — 3799 tracked .rs files, 4 allowlisted, 0 violations
bash scripts/check_sld.sh         — 56 spec docs + 3143 code files; 0 errors, 0 warnings
bash scripts/check_changelog_fragment.sh — 18 changed paths; both crates recorded
cargo check --workspace --exclude trusty-code-gui --exclude trusty-mpm-gui — exit 0

Left for step 4, deliberately

The ingest concurrency semaphore (25 MiB buffered before HMAC at ~3× body size), the unreachable None claim arm, and the hard_link filesystem doc note. A >SWEEP_BUDGET test did not fall out of the HIGH-A work for free, so it is not here.

webhook-spool/exhausted/ has no retention policy: it grows until an operator acts, and the red health state with the exhausted count and ids is what tells them to. Deleting an undelivered webhook automatically is the one thing this whole step exists to prevent.

…fore the ack (#5089 step 3)

Both existing webhook handlers return 202 and *then* do the work
(trusty-review/src/service/webhook.rs:305-309,
trusty-analyze/src/service/handlers/review.rs:210-214). GitHub never
retries an acknowledged delivery, so every post-ack failure is permanent
silent loss with health still reporting green. This builds the console
path that replaces them; the two handlers stay live until step 4.

POST /api/webhooks/{source} multiplexes review and analyze. The order of
operations is the fix: unknown source 404s before any secret handling;
the HMAC is verified once over the exact received bytes, with an unset
secret and a bad signature both 401 (ADR-0034 §2 unifies the policy to
trusty-review's fail-closed answer); the delivery is written and fsync'd
to a spool under the console data directory; and only then is a 202 sent.
A spool write that fails returns 5xx and never acks, so GitHub keeps the
delivery redeliverable.

A relay outcome other than an explicit "ack": true leaves the entry
pending with an incremented attempt count and a durable reason. Reaching
the target is deliberately not enough — treating a successful connect as
a successful delivery is the same silent loss one layer down.

GET /api/console/metrics/webhooks reports oldest-pending age, pending
count and failed-attempt total, red once the oldest entry passes the
threshold. The scan runs on the request rather than from a cache, so the
signal stays honest if the background retry sweep stops; a spool that
cannot be read is red rather than empty.

trusty-common gains the two shared entry points this needs rather than a
fourth bespoke copy of each: uds::rpc::send_framed_request (the framed
UDS transport ADR-0034 §4 names, dialling through connect_hardened) and
webhook_hmac (one GitHub signature verifier, returning a three-state
verdict so "no secret configured" cannot collapse into permission to
proceed). The existing UDS clients and the two HMAC copies migrate in a
follow-up.

Spawn-on-demand is step 4. Until then no target binds a listener, every
relay lands in Unreachable, and that is a durable pending state.

Refs #5089

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
@bobmatnyc bobmatnyc added trusty-mpm trusty-mpm platform and related work ws/tm-dogfood labels Aug 7, 2026
@bobmatnyc bobmatnyc self-assigned this Aug 7, 2026
…pool green (#5089 step 3 review)

Seven findings from the code-critic round on #5175. All three HIGHs were in
the machinery the PR adds, not the ordering it fixes.

HIGH-1 — the sweep and the request path relayed the same delivery twice.
`retry_pending_once` listed every `.json` with no claim and no age filter, so
a tick landing inside the <=5s relay window re-sent a delivery `ingest` was
still sending. A `ClaimSet` now gives one relay per entry path at a time,
released on drop so a panicking relay cannot wedge an entry.

HIGH-2 — no backoff, contrary to ADR-0034 §2. Every pending entry was
relayed every 60s and each non-ack rewrote the whole base64 body plus two
fsyncs; until step 4 binds a listener that is every delivery, forever.
`BackoffPolicy` spaces attempts 30s doubling to a 1h ceiling, holds a fresh
entry for the relay timeout, and stops at 24 failures. An exhausted entry is
never relayed again and never deleted — it holds the health signal red. A
per-pass `SWEEP_BUDGET` keeps one serial pass from outlasting its own tick.

HIGH-3 — an absent spool directory reported green. `list_pending` answered
`ErrorKind::NotFound` with an empty listing, so a removed data dir or an
unmounted volume made every POST 500 while the metrics route said
`{"status":"ok","pending":0}` — ingress dead, alarm healthy. `Spool` now
records whether it was opened; for an opened spool a missing directory is
`ReadDir`, which the health scan renders red. A never-opened one is still
legitimately empty.

Also:

- 25 MiB body limit on the webhook sub-router. axum's 2 MiB default 413s a
  real push/pull_request delivery before the handler runs — no spool entry,
  no metric, no log.
- The relay wire contract moves to `trusty_common::webhook_relay`. Step 4's
  receivers are trusty-review and trusty-analyze, which cannot depend on the
  console, so "both halves read this constant" was not true as written.
- `persist_new` commits with `hard_link`, not `rename`, so a colliding path
  fails atomically instead of clobbering an already-acknowledged delivery.
  `persist_update` keeps rename semantics for `record_attempt`.
- The socket-dir comment claimed the paths avoid `$TMPDIR`; they do not.
  Corrected to say #5099's 0700 uid-keyed dir plus `connect_hardened`'s
  owner/mode re-check supersedes ADR §3's path rule.

Adds the concurrency test class rung 5 requires and the first round lacked —
which is where HIGH-1 lived. Verified by reverting each fix in place: the
sweep-race, both vanished-directory cases, and the 3 MiB body case all fail
against the pre-fix behaviour and pass with it.

Refs #5089

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
…lth signal moving (#5089 step 3 review 2)

Two HIGHs from the round-2 critic, both in the exhaustion semantics round 1
introduced, plus the runtime-blocking MEDIUM.

HIGH-A — exhausted entries accumulated forever and every scan paid full
decode for them. The sweep counted `exhausted` and `continue`d; nothing
deleted, moved, or aged them out. Since no target binds a listener until
step 4, that is EVERY delivery reaching 24 attempts in ~17h and staying in
the live set permanently, with both `retry_pending_once` and `scan_health`
reading and `serde_json`-decoding it on every pass. An exhausted entry now
moves to `webhook-spool/exhausted/` — kept, because it is still an
unacknowledged webhook, but off both hot paths. `Spool::scan_metadata` reads
receipt times from filenames and opens nothing, which is what `entry_path`'s
timestamp prefix was always for; `Spool::load` decodes the single entry the
health scan actually needs.

HIGH-B — once red, the signal stopped saying anything new. `SpoolHealth` had
no exhausted field and `SweepReport.exhausted` reached exactly one consumer,
a `tracing::info!` — the log line `health.rs`'s own module doc names as the
trap. Worse, `scan_health` took `listing.pending.first()` and exhausted
entries are by construction the oldest, so the delivery id, last error and
age pinned to the first poisoned entry forever. Day 30's genuinely stuck
delivery moved nothing an operator or alert rule reads. `pending` and
`exhausted` are now counted separately with their own ids and ages, and
`oldest_pending_*` describes the oldest LIVE entry. Any exhausted entry still
holds `status: Error`, via its own field rather than by hijacking the
oldest-pending ones. `total_failed_attempts` is replaced by
`oldest_pending_attempts` — the sum cost one decode per entry per request,
which is what HIGH-A is about.

`sweep_stops_relaying_an_exhausted_entry` asserted the old behaviour as
desired; it now asserts the entry leaves the live set, stays readable with
its body intact, and shows up in the exhausted fields.

MEDIUM — all spool I/O now runs through `spawn_blocking`. Ingest fsyncs a
file and a directory twice per delivery; the metrics route scans two
directories per request.

Verified by reverting each fix in place: the sweep-quarantine case and the
live-versus-exhausted diagnostics case both fail against 92c1ed3.

Refs #5089

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
…p 3)

`check_test_pointers.sh` was red on two citations that named a prefix of the
real test rather than the test:

- `schedule.rs:48` cited `claim_set_releases_on_drop`; the test is
  `claim_set_releases_on_drop_even_when_the_holder_panics`.
- `spool.rs:498` cited `sweep_quarantines_an_exhausted_entry`; the test is
  `sweep_quarantines_an_exhausted_entry_and_stops_paying_for_it`.

The pointers were wrong, not the names — both test names say more about what
they prove, so they stand.

Refs #5089

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
…e the sweep test (#5089 step 3)

CI was red on `sweep_does_not_relay_an_entry_the_request_path_is_still_relaying`
while it passed locally. Diagnosing it found both a racy test AND a real code
defect; they are separate and both are fixed here.

The test was racy. It slept 150 ms and assumed `ingest` had reached its claim
by then. It does not control that window: printing the whole SweepReport at
sleeps of 0/1/5 ms shows every field zero, meaning `list_pending` returned an
EMPTY spool — the spawned task had not persisted yet. That is exactly CI's
signature (`in_flight: 0` with nothing else set). Moving the write onto the
blocking pool in aeba797 lengthened the pre-claim phase enough to lose the
race under CI load. The test now rendezvouses with the target stub: the stub
signals once it has read the frame and waits to be released, so the sweep runs
when the relay is provably in flight. No wall clock, and it drops from 0.64 s
to 0.04 s.

The code was also wrong. The claim was taken AFTER `persist_new` returned,
leaving the entry on disk and unclaimed for the gap between the write landing
and `ingest` being re-polled. At sleep=20 ms the sweep reported `acked: 1` —
two relays for one delivery, the exact defect the claim exists to prevent.
The claim is now taken on `entry_path` before the write; the path is a pure
function of the receipt time and delivery id, both already fixed, so the window
does not exist. Backoff's first-attempt grace also covered it in production,
but two guards that each fully close it is the point.

No regression test pins the ordering. The window is one scheduler poll wide,
and a rendezvous, a select! loop and a 4-worker parallel hammer all passed
against a claim-after-write build as readily as against the correct one. A
test that cannot tell the two apart is a false assurance, so none was kept and
the code carries a comment saying so.

Evidence: the deraced test is 30/30 green under 12-way CPU saturation, and
5/5 red against a build whose sweep ignores claims.

Refs #5089

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
@bobmatnyc
bobmatnyc merged commit 352fe5d into main Aug 8, 2026
29 checks passed
@bobmatnyc
bobmatnyc deleted the feat/5089-3-console-ingress-spool branch August 8, 2026 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trusty-mpm trusty-mpm platform and related work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant