The "observer revocation and monotonic TTL expiry deny the next
mutator" acceptance test reused a 1-second-TTL lease both to prove
authorization works immediately after promotion and, later, to
demonstrate real monotonic-clock expiry. Under a contended push-CI
host (concurrent build-gateway/appservice/web matrix), scheduling
delay alone between promote() and the immediate "still valid"
authorize() check could consume the entire 1-second margin, flipping
that setup assertion to a spurious deny (Woodpecker push CI#1945:
`expected { ok: false } to match { ok: true, decision: 'allow' }`).
Reproduced deterministically by inserting a 995ms delay between
promote() and the check, which reliably reproduced the exact CI#1945
failure signature.
Fix is test-determinism only: the initial "lease authorizes" check
now uses a normal-TTL lease with no real-time race, and a dedicated,
isolated short-TTL lease drives only the deliberate wait-then-expire
assertion. No production lease-broker/mutator-gate code changed, and
the deny-the-next-mutator security assertions (LEASE_EXPIRED after
TTL wait, MUTATOR_UNVERIFIED after revoke) are unchanged and
unweakened.
Closes#860
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMpAGx3YQZT64dov5xCNJL