Repository navigation
Conversation
… each Sandbox's share Requests refused by the installation or route checks no longer take a replay key, and one Sandbox can hold at most a quarter of the replay table, so it cannot refuse protected requests for every other Agent.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
…dline before reserving Internal review: the installation await now sits between the deadline check and the reservation, so recheck the clock there. Document the multi-Sandbox residual and the identity's accepted-exchange bound; assert both duplicates pass the early check.
|
Codex review: needs maintainer review before merge. What this changesThis PR delays replay reservation until installation and route validation, adds a 2048-ID per-Sandbox share, and enlarges the shared table to 8192 IDs. Example: Sandbox A submits 4096 unsupported requests within 30 seconds, then Sandbox B submits a valid protected request.
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness✅ Ready for maintainer review All three prior findings are resolved, and no new actionable defect was found; this PR still addresses replay-table exhaustion present on current main. Priority: P2 Before mergeNone. FindingsNone. Tests
Agent review detailsHow this fits togetherThe OCC Credential Proxy receives authenticated Sandbox requests, validates their installed route, reserves replay capacity, checks current authority, and selects credential material before separate send authorization. flowchart TB
A[Authenticated Sandbox request] --> B[Installation and route checks]
B --> C[Replay reservation and Sandbox quota]
C --> D[Exchange custody and policy check]
D --> E[Credential material selection]
E --> F[Separate send authorization]
Technical reviewBest possible solution: Land the focused replay-accounting repair while retaining separate ownership of the acknowledged shared-operation and multi-Sandbox exhaustion limits. Do we have a high-confidence way to reproduce the issue? Current-main source deterministically retains IDs for unsupported requests until the shared 4096-entry table fills; tests were inspected but not executed during this read-only review. Is this the best way to solve the issue? The repair uses the existing replay owner, reserves atomically before effectful work, preserves duplicate rejection, and releases expired accounting before enforcing either limit. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against eea5257b9957. Provenance checked
TestingProof path: in-process harness. SecurityNone. EvidenceWhat I checked:
Review metrics
LabelsLabel changes:
Label justifications:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment HistoryReview history (1 earlier review cycle)
Reviewed October 23, 2026, 3:43 AM ET / 07:43 UTC (Revision 2). |
…t a bound Review: entries can expire while the installation lookup is pending, so a full share or table is pruned again before refusing. Correct the capacity table's release rule and the no-reservation boundary (installation and route checks, not policy).
|
@clawsweeper re-review Head a30f855 addresses the three items: expired replay entries are pruned before refusing at either bound (new test covers a window that ends during the installation lookup), the capacity table's release rule for in-progress operations is corrected, and the reference now says only installation and route refusals reserve no ID. |
|
🦞👀 Re-review progress:
|
Problem
The Credential Proxy keeps every request ID it has seen for 30 seconds, so a replayed request is refused. That table is one in-memory pool of 4096 entries for all Sandboxes.
resolvereserved the ID before the installation lookup and route classification, and entries leave only by age. Requests refused at those checks (for example an unsupported operation) therefore still held an entry for the full window. When the table was full, every Sandbox's protected requests were refused withunavailable/resolver, so one Sandbox's traffic could stop protected egress for every other Agent. The bound also capped the whole API process at about 136 protected requests per second, which was not documented.Change
resolvenow reserves the request ID after the installation and route checks, which have no side effects (a state read and pure classification), and before exchange capture, the policy check and any Secret read. A request refused before that point uses no entry, and its ID was never used. A known replay is still refused before any lookup. The reservation checks the table again in the same turn, so two concurrent requests with the same ID cannot both proceed. A request whose lookup outlasts its deadline is refused before reserving. From exchange capture on, the ID stays reserved for the whole 30-second window, as before, even if the request is then refused.resolvedrops entries whose window ended while the installation lookup was pending. Past either bound, it refuses with the existingunavailable/resolver, with no further detail.These are provisional decisions, made by precedent; a maintainer may overrule them. The choices are the share identity (sender and Sandbox), the quarter share and the 8192 table size.
Not changed here, and filed as follow-ups:
Verification
tests/integration/static-egress.test.mjs, using a newsandboxes()helper on the sharedsyntheticDispatchFixture:requests refused before capture leave the replay table to every Sandbox: a full table's worth of refused requests from one Sandbox, after which another Sandbox's first request and the same Sandbox's next request are both accepted. An ID refused before capture can still be used. With the table size set to 4096, this test fails on main ("another Sandbox's first request").one Sandbox's replay share bounds it without refusing other Sandboxes: a Sandbox at its share is refused while another Sandbox is accepted. Four full shares still hit the shared bound. Both bounds clear after the 30-second window, including when the window ends while the request's installation lookup is pending.a request ID stays reserved once policy or Secret work can start: after a policy refusal and after a ready resolution, the same ID is refused. A known replay does no lookup. Concurrent duplicates both pass the early check, then yield exactly one ready resolution and one Secret read. A lookup that outlasts the deadline is refused withdeadline_exceededand starts no policy check.static-egress.test.mjsandcredential-proxy-peer-pin.test.tspass locally, including the existing replay, horizon, capacity and sustained-traffic tests.tsc --buildpasses, and prettier and eslint pass on the touched files.Risks