feat(system): expose shared terminals locally - #71
Conversation
Initial high-risk review wavePinned head: Risk: high because this changes shared PTY I/O, policy enforcement, session lifetime, and multi-client concurrency. Reviewers:
The replacement preserves independent contexts and a different named model family; the runtime cannot independently prove provider-level model-family diversity beyond those identities. No code changed during the wave. Consolidated findings and dispositions
No other findings were consolidated. All accepted items will be fixed in one remediation change, then the changed head will rerun full gates and return to both recoverable reviewer contexts for verification. Verdict: |
Remediation verification wavePinned head:
Prior findings
New evidence and dispositions
These are based on new remediation-code evidence. They do not reopen resolved initial findings. The fixes will be batched before the next exact-head verification. Verdict: |
Final-verification wave on
|
Verification wave on
|
Verification wave on
|
Verification wave on
|
Final verification wave on
|
|
Merge-gate decision: the repository owner explicitly confirmed that the published approval status from the two independent external reviewer contexts is sufficient. GitHub cannot create a formal review because the sole collaborator is the PR author. Proceeding with the exact-head dual |
Closes nicodes/ormos-be#504
Risk: high. This changes shared PTY input/output, connection limits, local directory-policy enforcement, and multi-client concurrency.
Corrections
The worker rechecksCorrection:POLLOUTunder the shared input lock and writes at most 512 bytes, the portable Linux/DarwinPIPE_BUFfloor, so the write cannot block.PIPE_BUFapplies only to pipes/FIFOs, not PTY masters, and POSIX does not make a subsequent blocking write safe afterpoll. The current head instead normalizes the PTY master to permanentO_NONBLOCKand routes all browser/local input through one session scheduler whose sole kernel write is raw nonblockingunix.Write.The shared session scheduler is bounded at exactly 256 calls and 1 MiB.Correction: that bound let a legal maximal local paste disconnect the next browser keystroke. Local aggregate admission remains exactly 256 calls/1 MiB; the scheduler now adds a bounded 64-call/256 KiB browser reserve, for exact combined bounds of 320 calls/1.25 MiB. Browser readers wait on capacity release rather than disconnecting.The 256-call/1 MiB session-local bound was reserved before input copying.Correction: on38b55d6, only each attachment reserved before copying; competing attachments could allocate beyond the session aggregate before rejection. The current head reserves per-attachment, session-local, and total scheduler accounting in one ordered transaction before any copy, then rolls all ledgers back exactly once if publication fails.Summary
File.FdcallsPOLLOUTwaits and a 4096-byte round-robin fairness quantumVerification
-count=20-count=5mise exec -- go test ./...mise exec -- go test -race ./...mise exec -- go vet ./...mise exec -- govulncheck ./...(0 reachable vulnerabilities; one required-module vulnerability is not called)GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 mise exec -- go test -exec /bin/true ./... -run "^$"GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 mise exec -- go test -exec /bin/true ./... -run "^$"git diff --checkDarwin was cross-compiled, not runtime-tested locally. The Linux real-PTY gates run on a raw/no-echo slave and a master filled to actual
EAGAIN.Deliberate gate failures
All mutations below were run one at a time and reverted before the current head.
Initial gates:
TerminalSessionInfo.ProjectIDfromproject_idtoprojectId; the literal DTO test failed on the missing snake_case key and decode mismatchlocal reattach created a duplicate shellstalled local client was not detached at the write deadlinelocal decoded output queue capacity = 2, want one bounded handoffAdmission and lifecycle gates:
local input worker did not release queued input after detachinput beyond byte budget error = <nil>, want ErrTerminalInputBackpressurereattached PTY size = 80x24, want 100x40>=to>; the test failed withlocal session limit error = <nil>>= 256to> 256; the test failed withaccepted local input calls = 257, want exact bound 256implementation copies = 769, accepted calls = 256; rejected calls allocateddetach passed a Write already holding admissionoversized local input error = terminal input backpressure, want ErrTerminalInputTooLargeNonblocking scheduler and real-PTY gates:
TestPTYMasterRemainsNonblockingAcrossTerminalIOCTLSfailed withregister pty with runtime poller: file type does not support deadlineWriteand removed the raw helper;TestTerminalInputHasOneRawPTYWriterAndOneSchedulerfailed withdirect terminal_sessions.go Write callandunix.Write PTY helpers = 0, want exactly oneTestTerminalInputStartsExactlyOneWorkerAndCloseDrainsAccountingfailed withpanic: close of closed channelTestRealPTYDetachReleasesMaximalLocalInputAndBrowserProgressesfailed withinput accounting session=1/1048576 local=1/1048576, want 0/0TestRealPTYInputFairnessAt4096ByteQuantumfailed withbrowser marker followed 8192 local bytes, exceeds exact 4096-byte quantumBrowser-pressure gates:
256 KiB - 1;TestTerminalInputExactSchedulerBoundsfailed withscheduler bounds = 320 calls/1310719 bytes, want 320 calls/1.25 MiBTestBrowserInputFullCapacityWaitsThenResumesfailed withbrowser submission did not enter capacity waitTestTerminalInputExactSchedulerBoundsfailed withinitialized scheduler channel capacity = 256, want 320\n- moved session-local reservation after the copy;TestLocalTerminalWriteReservesAggregateBeforeCopyAcrossClientsfailed withaggregate reservation before copy total=0/0 local=0/0\n- changed the combined call threshold from 320 to 321;TestTerminalInputExactSchedulerBoundsfailed withscheduler bounds = 321 calls/1310720 bytes, want 320 calls/1.25 MiB\n- removed connection cancellation from the between-chunk capacity wait;TestBrowserLargeFrameChunkWaitCancellationDrainsAccounting/connectionfailed withbetween-chunk cancellation did not unblock submission\n- skipped rollback when a reserved local request found publication closed;TestReservedLocalPublicationRollsBackWhenSessionClosesfailed withsession ledgers after close = [1 1048576 1 1048576 0 0], want all zero\n- shrank the production scheduler channel to 319;TestReservedLocalInputOwnsFutureSchedulerChannelSlotfailed withproduction scheduler channel capacity = 319, want 320 future-slot invariant