Bound interview token startup and no-show cleanup

Merged
XU
21h ago
+937-106

Summary

  • Add a server-side deadline while reading the /api/token request body.
  • Release recorded-interview consent when a dispatched room reaches the candidate no-show deadline.
  • Add a browser-side deadline for /api/token and use the existing offline-practice fallback when it expires.
  • Keep successful startup and existing non-timeout failure behavior unchanged.

The no-show cleanup is guarded by the room name, matching the existing refused-dispatch cleanup. A lost response may still leave an agent waiting until CANDIDATE_JOIN_LIMIT, but the agent then exits and the consent is no longer left bound to an unused room.

Tests

  • cargo test token_body_read_has_a_deadline -- --nocapture
  • cargo test --test web token_stalls_before_and_after_dispatch_have_different_side_effects -- --nocapture
  • node --test tests/browser/dom-contract.test.js tests/browser/recording-consent.test.js

The integration coverage verifies:

  • a stall before dispatch leaves no dispatched room or consent claim;
  • a stall after dispatch has a dispatched room and claimed consent;
  • the consent is released after the dispatched room reports a candidate no-show.

The full local test script reached 1,455 browser tests. One unrelated lobby layout test failed because the VM maps system-ui to Noto Sans and measured 814 px against an 800 px viewport. The branch does not modify the lobby test or its layout files.

Closes #380


Summary by cubic

Bounds interview startup so a stalled /api/token request can't hold it open forever, and releases recorded-interview consent when a dispatched room never gets a candidate or fails before one joins. Closes #380.

  • Adds a 10-second server deadline while reading the token request body; a timeout returns 408 before any room is reserved or consent claimed. A matching 20-second browser deadline falls back to offline practice.
  • Claims consent and dispatches in one spawned task, so a dropped request can't cancel the claim after it commits but before the dispatch sees it.
  • Releases a claimed consent when a dispatched room sees no candidate or fails before a candidate joins; the release is guarded by the room name, refuses once recording has started, and is skipped while a newer pending interview holds the same consent version's pending slot.
  • Keeps successful startup and failures after a candidate join unchanged, including the different side effects of a stall before versus after dispatch. Regression tests cover both paths.