Repository navigation
CONTRACT: feat(ui-server): prepare durable turn egress records - #2399
Merged
Merged
Conversation
This was referenced Oct 19, 2026
schlessera
added this pull request to stack #2646
October 22, 2026 12:19
schlessera
marked this pull request as ready for review
October 22, 2026 13:12
schlessera
marked this pull request as draft
October 22, 2026 13:12
schlessera
marked this pull request as ready for review
October 22, 2026 17:21
schlessera
marked this pull request as draft
October 22, 2026 17:21
schlessera
marked this pull request as ready for review
October 22, 2026 21:22
This was referenced Oct 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #1665
Bottom layer of the #1665 stack: this PR, then #2644 (first-party path measurement), then #2645 (default-on for governed and strict Claude turns).
What changed
Adds the typed
egress_connectiongovernance event and an internal per-turn proxy recorder (prepareTurnEgress). Real completed and refused HTTP/CONNECT connections persist host, port, method, visible path, bytes, duration and outcome in SQLite, and anegress_denialis written for allowlist, deny and byte-cap refusals. A recorder failure cancels the owning turn. Outward destinations wait for the existing approval bridge; voice has no approval surface. A zero-bytemax_bytes_per_turnis a valid policy that refuses before any upstream contact or credential release. No server path consumes the recorder in this layer; #2645 composes it.Why this shape
This is the independent recording prerequisite from #1665. The payload is additive (
CONTRACT:; server minor) and documented indocs/http-api.mdanddocs/integration-contract/http.md. It adds no public extension seam or credential authority.Proof
Head
8406e0062mergesorigin/main4ba50d824(#2671) intoeded2a0da, which mergedorigin/main46380183binto round 2's head5861e4e5b. Both merges were clean (round 3 refresh for #2657, #2660, #2558, #2653, #2397, #2665, #2671), and they touch none of this layer's files.Stack squash simulation (round 3). In a scratch worktree at
origin/main4ba50d824, each layer's own diff (parent head → layer head) was squashed on in order (#2399, #2644, #2645) withgit merge-tree --merge-base. All three applied without conflict, and the final tree equals #2645's head tree. Each layer head also merges cleanly withorigin/mainon its own.Result on
8406e0062: passed (exit 0). Lint, metadata and the fast phase pass (446 tests / 17 files), and import-graph feedback passes 3169 tests across 262 files.The previous round 3 head
eded2a0dafailed one test that main already fails:turn-scope.test.ts›periodic capture resumes a productive worker and snapshot failure terminates its held worker(Scope fixture timed out). It failed the same way in isolation on bareorigin/main46380183band onaeaaf7794, and is tracked as #2666. It passed in this run.Round 2's result on
5861e4e5b: passed (exit 0), 3123 import-graph tests across 257 files.Two earlier runs on this head each failed one test,
Maintenance temporary storage is busy, while another preflight held the shared per-UID maintenance ledger. Both pass in isolation (mask-scratch.test.ts14/14,brain-client.test.ts35/35), and the third, uncontended run is the one above.The receipts below were taken on round 1's head
757c0d957. The merge changes none of the files they guard (turn-egress.ts,egress-proxy.ts,governance/events.tsand their tests).turn-egress,governance-events,egress-proxy,inference-egressand decision citations pass 87 tests / 444 assertions on this head. Strict types and lint are clean.< 0→<= 0):TURN_EGRESS_ZERO_CAP_ADMISSION_VALIDfails.controller.abortis dropped:TURN_EGRESS_FAILED_RECORD_ABORTSfails (expected true, received false) for both kinds.a real turn refusal durably retains not_allowlistedfails (expected 403, received 200). This is ui-sdk: give governed and strict workers a private network with a recorded, limitable egress proxy #1665's required "bypass the allowlist" receipt.Checklist
docs/reflect the change, or nothing documented moved.docs/decisions/provider-history.md): the provider-history guard passes, or nothing on a turn's path changed.Anything left open
The remaining #1665 work is listed on #2645. This layer is partial and stays
Refs.🤖 Generated with Claude Code