Repository navigation
fix(harness): retry the boot-time secret prefetch - #212
Conversation
Codex flagged this auditing the CI change, and the mechanism checks out: a failed prefetch was permanent for the life of the VM. `prefetch_declared` warms the secret cache moments after boot, so the mTLS vend path runs on every boot rather than only when a workload asks. It ran each declared secret exactly once and logged a warning on failure. That looks recoverable — `refresh_loop` runs every 15s — but it is not: the refresh loop iterates entries ALREADY in the cache and re-vends the ones near expiry, so a prefetch that never landed leaves nothing to iterate. One lost race at boot and the vend never happens again. The window is real. This runs immediately after the guest's network comes up, against a manager that may not be accepting yet. The workload can still vend on demand, so production impact is a cold cache rather than a broken one. The sharper edge is the integration test: it asserts on that boot vend (EXPECT_VENDSECRET=1, now always on in CI), so a lost race would report a failed security contract instead of a slow start — a flaky gate on the one assertion that proves the mTLS boot contract works. Now retried up to 5 times with doubling backoff (250ms, 500ms, 1s, 2s — ~3.75s total, capped so a wedged manager cannot stretch it out). Only failures are retried. Still best-effort: spawned off the boot path, bounded, and giving up never blocks the VM — it just logs that the workload will vend on demand. Not using a shared retry helper because the repo's canonical `lantern-retry` crate does not exist yet (same gap as `@lantern/retry` in TS, already noted in bridge-core). Small local loop, to be replaced when it lands. The backoff schedule is a pure function so it is testable without a live manager. The test asserts it both backs off AND stays bounded; removing the cap makes it fail (verified by mutation, then reverted). Verified on real KVM — and the binary was checked to actually contain the change first, after an earlier build silently reused a two-day-old root-owned artifact: 5/5 assertions, including "harness live + secret vended over mTLS" 156 harness tests pass (1 new), clippy and rustfmt clean on 1.94.
🔎 Codex cross-audit (agent:audit)Blocking: none found. I audited Verification: |
🧪 QA — ❌ tests failing |
🔎 Codex cross-audit (agent:audit)Blocking: none found. Findings: no correctness or security regressions attributable to this PR. The retry loop in services/harness/src/secrets.rs preserves best-effort boot behavior, retries only pending names, removes successful vends from subsequent attempts, and keeps the sleep schedule bounded. Verification: |
🔷 Gemini cross-audit (agent:audit-gemini)An independent audit of the unified diff in The implementation of the boot-time retry mechanism in 1. Metadata Leak (Secret URIs) in Warning Logs
2. Sequential & Unbounded Connection Timeouts (The "Bounded Wait" Illusion)
|
🔷 Gemini cross-audit (agent:audit-gemini)Audit Report: Boot-Time Secret Prefetch Retry SupportAfter a thorough, independent static analysis of the unified diff in The implementation is highly robust, correct, and idiomatic. Below is the detailed audit summary: 1. Security Analysis (No Issues)
2. Correctness & Edge-Case Verification (No Issues)
3. Test Coverage & Quality
Verdict: Approved. The PR is fully safe, correct, and ready for integration. |
Follow-up to the finding Codex raised while auditing #211. The mechanism checks out: a failed prefetch was permanent for the life of the VM.
Why it couldn't recover
prefetch_declaredwarms the secret cache moments after boot, so the mTLS vend path runs on every boot rather than only when a workload asks. It tried each declared secret once and logged a warning on failure.That looks recoverable —
refresh_loopruns every 15s — but it isn't. That loop iterates entries already in the cache and re-vends the ones near expiry. A prefetch that never landed leaves nothing to iterate. One lost race at boot and the vend never happens again.The window is real: this runs immediately after the guest's network comes up, against a manager that may not be accepting yet.
Impact
EXPECT_VENDSECRET=1, now always on), so a lost race reads as a failed security contract, not a slow startThe second is the sharper edge: a flaky gate on the one assertion that proves the mTLS boot contract works.
Change
Retry up to 5 times with doubling backoff — 250ms, 500ms, 1s, 2s (~3.75s total, capped so a wedged manager can't stretch it out). Only failures are retried. Still best-effort: spawned off the boot path, bounded, and giving up never blocks the VM — it logs that the workload will vend on demand.
Not using a shared helper because the repo's canonical
lantern-retrycrate doesn't exist yet (same gap as@lantern/retryin TS, already noted in bridge-core). Small local loop, to be replaced when it lands.Verification
harness live + secret vended over mTLS.