Skip to content

v1.7.4

Choose a tag to compare

@marmutapp marmutapp released this 28 May 13:00
· 16 commits to main since this release

Headline: observer-side mitigation for V5-1 — codex-cli's global
\\.\pipe\codex-ipc named pipe (Windows) / app-server-control.sock
(POSIX) lets the first long-running codex.exe app-server process
intercept every subsequent codex exec call on the host. When that
holder was spawned without observer's -c openai_base_url=… override
(typically by the VS Code Codex extension or Codex Desktop), the
call's HTTP traffic bypasses observer's proxy entirely — no api_turn
row, no compression telemetry. The v4 codex compression A/B benchmark
blocked at Phase 1 pre-fix because per-cell capture was
non-deterministic. Observer can't fix the IPC bypass — true fix has
to come upstream in codex (4 options proposed in
docs/observer-platform-issues-v5.md §V5-1) — but this release
detects the bypass, warns loudly, and offers --exclusive as a
one-flag operator workaround. Operator transparency contract: at
most one additive stderr line per observer codex invocation when
shared app-servers are present, zero new output on a clean host,
codex exit code never changed by the new checks. (#21)

feat(codexipc): cross-platform codex app-server detection + termination

New internal/codexipc/ package provides Detect / Terminate
primitives the wrapper uses. Windows path runs a PowerShell CIM query
against Win32_Process for codex.exe / Codex.exe entries via
ConvertTo-Csv, filters CommandLine matching app-server, excludes
--type= Electron child processes (per the v5 doc's reproducer
heuristic). POSIX path stats ${CODEX_HOME:-~/.codex}/app-server- control.sock as a microsecond fast path; if absent, returns empty
without spawning ps. Only when the sock is present does it run
ps -A -o pid,comm,args and hand bytes to the platform-agnostic
parser. classifySource labels detected processes as
vscode-extension (.vscode/extensions/openai.chatgpt-…),
codex-desktop (Codex.app, AppData\Local\Programs\Codex,
/opt/Codex/), or unknown. Termination uses
taskkill /F /PID <pid> on Windows and syscall.Kill(pid, SIGKILL)
on POSIX; OS errors surface verbatim so the per-PID operator line can
name access-denied / EPERM clearly. Pure parsers and classifySource
live in the platform-agnostic file so unit tests run on any host;
table-driven tests pin the v5 doc's PID 10072 / PID 35388 reproducer
plus the negative cases (codex exec, --type=renderer children,
non-codex processes).

feat(codex): V5-1 wrapper-side mitigation — pre/post-flight + --exclusive + --detect-only

Three new flags on observer codex:

  • --exclusive — opt-in. Terminates detected shared app-servers
    before exec. Operator-hostile but bounded; prints intent + per-PID
    outcome + a "re-launch your VS Code Codex extension / Codex Desktop
    manually after this run" recovery hint before acting. Never
    silent kills.
  • --detect-only — inspection-only. Runs pre-flight, prints summary,
    exits 1 if any detected, 0 otherwise. CI-gate friendly. Mutually
    exclusive with --exclusive (errors out with a clear message).
  • --no-app-server-check — universal escape hatch that skips both
    pre- and post-flight checks silently. For scripts that have
    verified the host is clean or that want zero detection latency.

Pre-flight (default ON, warn-only when shared app-servers detected):
one concise self-contained stderr line names PIDs + sources, suggests
--exclusive, mentions --no-app-server-check, links
docs/codex-shared-app-server-gotcha.md. Single line so it's
greppable in CI logs and not noisy. Detection runs once per
invocation and the result is cached for --exclusive termination +
post-flight cross-reference; no double scan.

Post-flight (default ON, swallows errors): records cmdStart before
child.Run; on exit (success OR failure) walks CODEX_HOME for
rollout-*.jsonl files with ModTime() >= cmdStart, extracts
session_id from session_configured envelopes, counts inner
event_msg/token_count events. Uses bufio.Reader.ReadString per
feedback_jsonl_parser_cursor (Scanner is wrong for live-written
JSONL with CRLF + empty lines). Compares per-session JSONL counts
against api_turns rows the proxy recorded. Emits one stderr line
per branch:

  • 0 of N captured + preflight non-empty → "confirms V5-1 bypass
    from the shared app-server(s) above"
  • 0 of N captured + preflight empty → "no shared app-server was
    detected at pre-flight; please report as a V5 follow-up"
  • X of N captured (0 < X < N) → "partial V5-1 bypass"
  • all captured → silent (happy path stays quiet).

Cross-mount CODEX_HOME is walked via crossmount.AllHomes() so a
wrapper running in WSL2 finds /mnt/c/Users/<u>/.codex. Mirrors the
codex adapter's WatchPaths logic at
internal/adapter/codex/adapter.go:59. New tests cover the flag
defaults, mutex error, --no-app-server-check + --detect-only
contradiction (kind skip note + exit 0), the single-line pre-flight
warning format, and all 4 capture-rate branches including the
preflight-cross-reference variants and the CRLF + partial-last-line
parser tolerance. End-to-end WSL smoke confirmed: clean host → silent

  • exit 0; fake rollout JSONL + missing api_turns → "0 of 3 codex
    turn(s) reached observer's proxy" line fires.

docs(codex): document V5-1 shared app-server gotcha + Resolution + carve-out sync

docs/codex-shared-app-server-gotcha.md (NEW, tracked + public
carve-out from v1.7.4+) is the operator guide referenced from
observer codex --help. TL;DR block up top (the --detect-only +
--exclusive recipes), then the mechanism, --exclusive trade-offs,
--detect-only CI-gate pattern, --no-app-server-check escape
hatch, manual termination recipes for hosts where --exclusive
can't run (elevated processes), limitations (cross-mount WSL→Windows
wrapping isn't covered; pre-flight is a snapshot; auto-restart isn't
done), and cross-links to V5-1 §"Suggested upstream fixes" and the
adapter-audit-playbook red-flag pattern.

docs/observer-platform-issues-v5.md (NEW, promoted from untracked
persistent doc to tracked) gains a Resolution block under V5-1
explaining the wrapper-side mitigation, the additive-stderr default,
and the note that true fix still requires upstream codex changes.
The "Status of the v4 batch" table flips V5-1 from "NEW BLOCKER" to
"Mitigated in v1.7.4 (observer codex --exclusive / --detect-only

  • pre/post-flight detection); true fix still upstream".

docs/adapter-audit-playbook.md §5 gains a fixed-name IPC discovery
red-flag pattern — generalized guidance for future adapter audits:
when adding a wrapper for a new external tool, search the tool's
source for pipe, socket, IPC, app-server, daemon; if the
IPC name isn't parameterized by a per-invocation key
(CONFIG_HOME, account, model), the wrapper needs detection +
termination support like internal/codexipc/.

docs/release-runbook.md gains a "v1.7.4 follow-up — V5-1
observer-side mitigation" subsection mirroring the v1.7.3 format,
with a grep -n verification command for the 3-site carve-out sync.
scripts/release.sh adds docs/codex-shared-app-server-gotcha.md
to all three carve-out sites (git add --force block, .gitignore
negation heredoc, docs_leaks grep alternation), mirroring the v1.7.3
add of docs/proxy-live-test-recipe.md.


Downloads

Pre-built binaries for each supported platform are attached below. Linux variants bundle antigravity-bridge.exe next to the observer binary for WSL2 users of the Antigravity adapter.

Platform Asset
Linux x86_64 observer-v1.7.4-linux-x64.tar.gz
Linux arm64 observer-v1.7.4-linux-arm64.tar.gz
macOS x86_64 (Intel) observer-v1.7.4-darwin-x64.tar.gz
macOS arm64 (Apple Silicon) observer-v1.7.4-darwin-arm64.tar.gz
Windows x86_64 observer-v1.7.4-win32-x64.zip

Verify with sha256sum -c SHA256SUMS (or shasum -a 256 -c SHA256SUMS on macOS) from the directory containing the downloads.

Also available via npm: npm install -g @superbased/observer@1.7.4

Org server (Docker)

The self-hosted org server ships as a Docker image and as per-platform observer-org-v1.7.4-* archives (attached below).

docker pull ghcr.io/marmutapp/observer-org:v1.7.4

The image is keyless-signed with cosign. Verify it:

cosign verify ghcr.io/marmutapp/observer-org:v1.7.4 \
  --certificate-identity-regexp 'https://github.com/marmutapp/superbased-observer-private/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Supply chain

CycloneDX SBOMs are attached: observer.cdx.json and observer-org.cdx.json.

SLSA Level 3 build provenance for the binaries is attached below as a *.intoto.jsonl attestation. The build runs on the private origin repo, so pass that as the source when verifying an extracted binary with slsa-verifier v2.7.0 or newer (older versions fail with unexpected tlog entry type: expected intoto:0.0.2, got dsse:0.0.1):

slsa-verifier verify-artifact ./observer \
  --provenance-path *.intoto.jsonl \
  --source-uri github.com/marmutapp/superbased-observer-private