From f93a609fce77936d073ff9131abd500a3f9b817a Mon Sep 17 00:00:00 2001 From: Epinephrine Date: Sun, 11 Oct 2026 18:52:31 -0700 Subject: [PATCH 1/3] fix(test): isolate diagnostic servers from live Codex restart Install a non-operating restart service on all native-owner fixture servers. Synthetic reads and explicit restart refusal cannot invoke host process I/O. Preserve the model-list and native-profile diagnostic paths. Based on current dev with verified unchanged fixture/test/doc preimages. Keep unrelated picker metadata changes out of this focused four-file fix. Local component compatibility: 11 tests pass under archived Bun 1.4.0 setup; full current-tree and native Windows validation remain required. --- .../windows-version-control/README.md | 12 +++++++-- .../codex-restart-route.test.ts | 27 +++++++++++++++++++ tests/helpers/native-main-owner-child.ts | 5 +++- tests/helpers/native-owner-restart-service.ts | 17 ++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 tests/helpers/native-owner-restart-service.ts diff --git a/scripts/diagnostics/windows-version-control/README.md b/scripts/diagnostics/windows-version-control/README.md index 6f6402553a1..d931da4098f 100644 --- a/scripts/diagnostics/windows-version-control/README.md +++ b/scripts/diagnostics/windows-version-control/README.md @@ -1,7 +1,7 @@ # Windows synchronous runtime-selection control This optional Rust control exercises `GET /v1/models` in a separate Bun process -using the repository's unchanged `tests/helpers/native-main-owner-child.ts`. +using the repository's `tests/helpers/native-main-owner-child.ts`. It does not connect to a running proxy, install accounts, or replay turns. It is a reproducer, not a runtime fix or proof of a historical production cause. @@ -10,6 +10,14 @@ authentication values, and an ephemeral loopback listener. It is configured with no real credentials and one unavailable loopback provider. Other network egress is not blocked or audited. +Every native-owner fixture server injects `nativeOwnerRestartService` from +`tests/helpers/native-owner-restart-service.ts`. Codex desktop/app-server state +queries return a synthetic unknown result and restart requests fail without +catalog synchronization, host process enumeration or process signalling. This +boundary applies even when a client presents the fixture authentication values; +redirected homes and descendant Jobs alone are not process-control isolation. +The diagnostic's model-list and native-profile operations are unchanged. + ```powershell cargo test --locked --manifest-path scripts/diagnostics/windows-version-control/Cargo.toml --test async_contracts -- --test-threads=4 cargo clippy --locked --manifest-path scripts/diagnostics/windows-version-control/Cargo.toml --all-targets -- -D warnings @@ -54,7 +62,7 @@ call chain. Keep profiles and fixture artifacts private; publish bounded scalar results and repository-relative function names instead. To compare installed source with the repository fixture, use a separately owned -scratch mirror containing a byte-identical copy of the helper and package +scratch mirror containing byte-identical copies of both helper files and package metadata, with `src` and `node_modules` links to the desired installation. The fixture must perform no writes to that installation. Links alone do not enforce read-only access. Verify the profile's source module paths and source diff --git a/tests/codex-integration/codex-restart-route.test.ts b/tests/codex-integration/codex-restart-route.test.ts index 949597c3c50..18d24103f28 100644 --- a/tests/codex-integration/codex-restart-route.test.ts +++ b/tests/codex-integration/codex-restart-route.test.ts @@ -8,6 +8,9 @@ * Plan: devlog/_fin/260815_gui_codex_restart/010_phase1_backend_endpoint.md */ import { describe, expect, test } from "bun:test"; +import { readFileSync } from "node:fs"; +import { helperPath } from "../helpers/repo-root"; +import { nativeOwnerRestartService, NATIVE_OWNER_RESTART_REFUSAL } from "../helpers/native-owner-restart-service"; import { handleSystemRoutes } from "../../src/server/management/system-routes"; import type { ManagementContext } from "../../src/server/management/context"; import { @@ -162,3 +165,27 @@ describe("POST /api/system/codex-restart", () => { }); }); + +describe("native-owner fixture process-control boundary", () => { + test("the fixture installs its non-operating service on the common server startup path", () => { + // This source-wiring guard complements the real route dispatch checks below. Do not import + // the helper here: its top level starts a server and reads the stdin control protocol. + const source = readFileSync(helperPath("native-main-owner-child.ts"), "utf8"); + const start = source.slice(source.indexOf("function start("), source.indexOf("const primary = start();")); + expect(start).toContain("codexRestartService: nativeOwnerRestartService"); + }); + + test("state queries use a synthetic unknown result without host process enumeration", async () => { + const response = await handleSystemRoutes(contextFor(CODEX_APP_SERVER_STATE_PATH, "GET", nativeOwnerRestartService)); + expect(response?.status).toBe(200); + expect(await response!.json()).toEqual({ state: "unknown", runningCount: 0 }); + }); + + test("restart is refused instead of invoking the live service or claiming a successful restart", async () => { + await expect(handleSystemRoutes(contextFor(CODEX_RESTART_PATH, "POST", nativeOwnerRestartService))) + .rejects.toThrow(NATIVE_OWNER_RESTART_REFUSAL); + // A refused call does not poison a later read or make the next restart succeed. + expect(await nativeOwnerRestartService.readState()).toEqual({ state: "unknown", runningCount: 0 }); + await expect(nativeOwnerRestartService.performRestart()).rejects.toThrow(NATIVE_OWNER_RESTART_REFUSAL); + }); +}); diff --git a/tests/helpers/native-main-owner-child.ts b/tests/helpers/native-main-owner-child.ts index b70db3dde04..250a4529d75 100644 --- a/tests/helpers/native-main-owner-child.ts +++ b/tests/helpers/native-main-owner-child.ts @@ -12,6 +12,7 @@ import { import type { NativeProfileKey, NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; import { drainAndShutdown } from "../../src/server"; import { startServer } from "../../src/server"; +import { nativeOwnerRestartService } from "./native-owner-restart-service"; const required = (name: string): string => { const value = process.env[name]; @@ -137,7 +138,9 @@ function start(home = codexHome): ReturnType { } : undefined, }, - managementApi: { nativeProfileApi: { manager } }, + // Synthetic homes do not isolate OS process-control APIs. Every server, including extra + // fixture instances, must inject the entire restart service rather than using live defaults. + managementApi: { nativeProfileApi: { manager }, codexRestartService: nativeOwnerRestartService }, }); servers.push(server); return server; diff --git a/tests/helpers/native-owner-restart-service.ts b/tests/helpers/native-owner-restart-service.ts new file mode 100644 index 00000000000..518237a0fc9 --- /dev/null +++ b/tests/helpers/native-owner-restart-service.ts @@ -0,0 +1,17 @@ +/** The native-owner fixture must not enumerate or restart the operator's desktop. */ +import type { + CodexAppServerStateResponse, + CodexRestartResponse, +} from "../../src/lib/codex-restart-contract"; + +export const NATIVE_OWNER_RESTART_REFUSAL = "Codex desktop restart is disabled in the native-owner fixture"; + +/** Complete service injection: neither state reads nor restart requests reach production I/O. */ +export const nativeOwnerRestartService = Object.freeze({ + async readState(): Promise { + return { state: "unknown", runningCount: 0 }; + }, + async performRestart(): Promise { + throw new Error(NATIVE_OWNER_RESTART_REFUSAL); + }, +}); From ae6ea87562286a38217861b6e3a9092ab3f91d00 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 02:01:31 +0000 Subject: [PATCH 2/3] test(codex): cover the restart injection boundary through live HTTP servers Devin Review on #717: the source-wiring guard passes on the fixture's text alone, so a break in startServer's managementApi -> ctx.deps forwarding would silently restore the live restart service in diagnostic servers. Drive two real listeners on the same startup path the child uses and assert the injected service answers authenticated GET/POST requests end to end. Co-Authored-By: Epinephrine --- .../codex-restart-route.test.ts | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/tests/codex-integration/codex-restart-route.test.ts b/tests/codex-integration/codex-restart-route.test.ts index 18d24103f28..ec2fe392016 100644 --- a/tests/codex-integration/codex-restart-route.test.ts +++ b/tests/codex-integration/codex-restart-route.test.ts @@ -8,7 +8,10 @@ * Plan: devlog/_fin/260815_gui_codex_restart/010_phase1_backend_endpoint.md */ import { describe, expect, test } from "bun:test"; -import { readFileSync } from "node:fs"; +import { mkdtempSync, readFileSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { startServer } from "../../src/server"; import { helperPath } from "../helpers/repo-root"; import { nativeOwnerRestartService, NATIVE_OWNER_RESTART_REFUSAL } from "../helpers/native-owner-restart-service"; import { handleSystemRoutes } from "../../src/server/management/system-routes"; @@ -188,4 +191,70 @@ describe("native-owner fixture process-control boundary", () => { expect(await nativeOwnerRestartService.readState()).toEqual({ state: "unknown", runningCount: 0 }); await expect(nativeOwnerRestartService.performRestart()).rejects.toThrow(NATIVE_OWNER_RESTART_REFUSAL); }); + + test("servers on the common startup path serve the injected service over authenticated HTTP", async () => { + // The child's start() is a thin wrapper over this same startServer call: driving real + // listeners proves the managementApi -> ctx.deps forwarding cannot silently drop the + // boundary while the source guard above still passes. Primary and extra fixture + // servers share one injection path, so both are exercised here. The sentinel restart + // body is one the live implementation could never emit: it does not fabricate a pid. + const root = mkdtempSync(join(tmpdir(), "ocx-restart-boundary-")); + const previousHome = process.env.OPENCODEX_HOME; + const previousCodexHome = process.env.CODEX_HOME; + const previousAdminToken = process.env.OPENCODEX_ADMIN_AUTH_TOKEN; + process.env.OPENCODEX_HOME = root; + process.env.CODEX_HOME = root; + process.env.OPENCODEX_ADMIN_AUTH_TOKEN = "restart-boundary-admin"; + const sentinel: CodexRestartResponse = { + success: true, + stateBefore: "unknown", + synced: false, + requested: [424242], + stopped: [424242], + surviving: [], + failed: [], + code: "stopped", + }; + const calls: string[] = []; + const observed = { + readState: async () => { + calls.push("readState"); + return nativeOwnerRestartService.readState(); + }, + performRestart: async () => { + calls.push("performRestart"); + return sentinel; + }, + }; + const deps = { managementApi: { codexRestartService: observed } }; + const primary = startServer(0, deps); + const extra = startServer(0, deps); + try { + const headers = { "x-opencodex-api-key": "restart-boundary-admin" }; + for (const server of [primary, extra]) { + const state = await fetch(new URL(CODEX_APP_SERVER_STATE_PATH, server.url), { headers }); + expect(state.status).toBe(200); + expect(await state.json()).toEqual({ state: "unknown", runningCount: 0 }); + const restart = await fetch(new URL(CODEX_RESTART_PATH, server.url), { method: "POST", headers }); + expect(restart.status).toBe(200); + expect(await restart.json()).toEqual(sentinel); + } + expect(calls).toEqual([ + "readState", "performRestart", + "readState", "performRestart", + ]); + } finally { + await primary.stop(true); + await extra.stop(true); + for (const [name, value] of [ + ["OPENCODEX_HOME", previousHome], + ["CODEX_HOME", previousCodexHome], + ["OPENCODEX_ADMIN_AUTH_TOKEN", previousAdminToken], + ] as const) { + if (value === undefined) delete process.env[name]; + else process.env[name] = value; + } + rmSync(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 50 }); + } + }); }); From 1dcb4bd2469d93f213f237aa2f4db9ca3bd1ad6e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 02:43:26 +0000 Subject: [PATCH 3/3] test(codex): harden restart-route fixture boundary guards - Assert the source-wiring guard's slice markers exist and are ordered before slicing, so a renamed marker fails loudly instead of passing on an unrelated range. - Inject inspectNativeCodexOwnership into the e2e servers' shared deps so startServer never inspects the developer machine's installed service state. The verdict is "foreign": it fences native-main admission with no lifecycle machinery, which this restart-route test does not exercise ("owned" would start a real owner drive on the fixture home). Co-Authored-By: Epinephrine --- .../codex-restart-route.test.ts | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/codex-integration/codex-restart-route.test.ts b/tests/codex-integration/codex-restart-route.test.ts index ec2fe392016..643ca19cff3 100644 --- a/tests/codex-integration/codex-restart-route.test.ts +++ b/tests/codex-integration/codex-restart-route.test.ts @@ -174,8 +174,11 @@ describe("native-owner fixture process-control boundary", () => { // This source-wiring guard complements the real route dispatch checks below. Do not import // the helper here: its top level starts a server and reads the stdin control protocol. const source = readFileSync(helperPath("native-main-owner-child.ts"), "utf8"); - const start = source.slice(source.indexOf("function start("), source.indexOf("const primary = start();")); - expect(start).toContain("codexRestartService: nativeOwnerRestartService"); + const from = source.indexOf("function start("); + const to = source.indexOf("const primary = start();"); + expect(from).toBeGreaterThanOrEqual(0); + expect(to).toBeGreaterThan(from); + expect(source.slice(from, to)).toContain("codexRestartService: nativeOwnerRestartService"); }); test("state queries use a synthetic unknown result without host process enumeration", async () => { @@ -226,7 +229,18 @@ describe("native-owner fixture process-control boundary", () => { return sentinel; }, }; - const deps = { managementApi: { codexRestartService: observed } }; + // startServer probes service ownership on every boot; without this seam it inspects the + // developer machine's installed service state — the host coupling this fixture exists to + // remove (the same seam native-main-owner-child.ts injects). "foreign" is deliberate: it + // fences native-main admission with no lifecycle machinery, which this restart-route test + // does not exercise; "owned" would start a real owner drive on the fixture home. + const deps = { + inspectNativeCodexOwnership: () => ({ + ownership: "foreign", + reason: "restart route test fixture", + }), + managementApi: { codexRestartService: observed }, + }; const primary = startServer(0, deps); const extra = startServer(0, deps); try {