feat: add authenticated recorder control channel - #79
Merged
Conversation
Add an authenticated cross-process status and stop contract for an active Capture recorder, so a launcher can stop a recording and prove that the recording finished. - bind every request and response to the exact session, PID, process start identity, and request ID, with HMAC-SHA256 over an unguessable per-session capability - store the capability only in a current-user-only runtime descriptor, using POSIX owner modes, macOS extended-ACL clearing, and a protected current-user Windows DACL, each verified after it is applied - refuse to start the control channel, and therefore the recording, when that boundary cannot be established or verified - make stop idempotent and report success only after database and event integrity verification; a timeout or a failed check never returns a success-shaped status - retain atomic incomplete terminal metadata after timeout, failure, or a discovered crash, and remove exact runtime descriptors after normal exit, abort, direct stop, and authenticated stale-process discovery - shut the event writers down with a separate terminate_writers event, so producers stop before writers and the committed rows can be reconciled - expose status_recording, stop_recording, discover_recorders, and RecorderStatus, plus capture status and capture stop commands - add a focused macOS and Windows pull-request workflow for the real subprocess contract The endpoint binds to IPv4 loopback on an ephemeral port. The capability does not enter process arguments, logs, responses, or capture artifacts. Stale discovery verifies the owner-protected descriptor and the exact process identity, checks the Windows kernel process signal before fallible metadata calls, rejects PID reuse, and keeps an ambiguous or access-denied process conservatively live. Closes #77 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
abrichr
force-pushed
the
codex/capture-control-ipc
branch
from
August 20, 2026 01:29
5fcb2ce to
9b4c325
Compare
abrichr
marked this pull request as ready for review
August 20, 2026 01:30
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.
Summary
capture status/capture stopcommands for the launcherSecurity model
The endpoint binds to IPv4 loopback on an ephemeral port. Every message uses
HMAC-SHA256 with an unguessable per-session capability. The capability does not
enter process arguments, logs, responses, or capture artifacts. The runtime
directory and descriptor must be current-user-only. Capture refuses to start the
control channel when it cannot establish and verify that boundary, and
Recorder.__enter__re-raises that refusal, so the recording does not starteither.
Requests carry a UUID request ID with a bounded replay cache. Cache saturation
raises
request_limitrather than clearing still-valid IDs, so replay cannot bereopened by flooding.
Stale discovery verifies the authenticated owner-protected descriptor and exact
process identity. On Windows it checks the kernel process signal directly before
fallible process metadata calls. It rejects PID reuse and keeps an ambiguous or
access-denied process conservatively live.
stop_recordingreturns only whencomplete,integrity_verified, andphase == "complete"all hold. Any other outcome raisesCaptureControlError,and
capture stopturns that into exit code 1. A stop can never report successwithout proof.
Rebase
This branch is rebased onto
mainafter Capture #76(
07990886b1e206bcc807ba95f822ef859e9b7325) and Capture #78(
b04e8292aad9b2df36bcd9c63fe9ea0c04d5b760).Two conflict classes were resolved in
openadapt_capture/recorder.py:terminate_writersevent instead ofterminate_processing, keepingmain'sutils.WrapStdout(write_events)target. Producers stop before writers, so committed rows can be reconciled.
browser_event_writerprocess stays removed. feat: qualify resilient native capture #78 removed the browserrecording path, and
record()refusesRECORD_BROWSER_EVENTSbefore anyworker starts.
The pre-rebase head
5fcb2ceee57cabf6cdc1d72dd3fd8060e17bac3ais preserved onbranch
codex/capture-control-ipc-original.This branch carries no lifecycle label change. The package stays Experimental
in
README.mdand staysDevelopment Status :: 2 - Pre-Alphainpyproject.toml.Verification on the rebased head
openadapt_capture/: passedpython scripts/check_changelog.py: passedscripts/verify_distribution.py: passedpython scripts/check_source_boundary.py --require-dist: passedCloses #77
🤖 Generated with Claude Code