From 03de1fee8f11e15f91b019be41ad16250b4db45c Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:01:50 +0200 Subject: [PATCH 1/6] test: pin doctor memory timeout contract --- tests/doctor-service-memory-contract.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/doctor-service-memory-contract.test.ts diff --git a/tests/doctor-service-memory-contract.test.ts b/tests/doctor-service-memory-contract.test.ts new file mode 100644 index 0000000000..21b854764e --- /dev/null +++ b/tests/doctor-service-memory-contract.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from "bun:test"; +import { fetchServiceMemory } from "../src/cli/doctor"; + +type ServiceMemoryDeps = NonNullable[1]>; +type TimeoutOptionIsHidden = "timeoutMs" extends keyof ServiceMemoryDeps ? false : true; + +const timeoutOptionIsHidden: TimeoutOptionIsHidden = true; + +describe("doctor service memory contract", () => { + test("owns its timeout instead of accepting a caller override", () => { + expect(timeoutOptionIsHidden).toBe(true); + }); +}); From 07133ab179359372143d79a97b357181dd269a29 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:02:36 +0200 Subject: [PATCH 2/6] fix(cli): narrow doctor local read dependencies --- src/server/local-management-read-client.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/local-management-read-client.ts b/src/server/local-management-read-client.ts index abcaa7acf2..50629090db 100644 --- a/src/server/local-management-read-client.ts +++ b/src/server/local-management-read-client.ts @@ -21,6 +21,9 @@ export interface LocalManagementReadDeps { readRuntime?: (pid: number) => RuntimePortState | null; createNonce?: () => string; now?: () => number; +} + +export interface LocalManagementReadRequestDeps extends LocalManagementReadDeps { timeoutMs?: number; } @@ -34,7 +37,7 @@ export interface LocalManagementReadDeps { export async function fetchBoundLocalManagementRead( target: LiveProxy, path: LocalManagementReadPath, - deps: LocalManagementReadDeps = {}, + deps: LocalManagementReadRequestDeps = {}, ): Promise { if ( target.source !== "runtime" From 8d7b8d4026dc7dab299a0bd8806c4c49ea14d77a Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:04:23 +0200 Subject: [PATCH 3/6] docs: correct local read capability consumers --- structure/05_gui-and-management-api.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/structure/05_gui-and-management-api.md b/structure/05_gui-and-management-api.md index 098d77898a..a9a9239705 100644 --- a/structure/05_gui-and-management-api.md +++ b/structure/05_gui-and-management-api.md @@ -25,18 +25,17 @@ a fourth credential class. A management credential that equals any configured da does not enable management access. The data plane may continue to start, but `/api/*` remains closed. CLI health collection follows the same boundary without transporting the reusable management credential. Its local-read HMAC capability is an additional single-use, route-scoped admission -mechanism, not a reusable credential class. `ocx status` and `ocx doctor` derive these capabilities -from the protected -`runtime-port.json` secret for exactly two read-only GETs: `/api/codex-auth/accounts` and -`/api/system/memory`. Each capability is bound to its method, path, nonce, proxy PID, and port. A -short expiry is part of the HMAC, and the server consumes each capability once. A capability cannot -authorize another management route or survive process replacement. These probes connect directly -to the selected listener instead of delegating local identity to an environment HTTP proxy. Their -output distinguishes -a missing proxy, rejected local capability, and an unexpected management response so a reachable -`401` cannot be reported as "proxy not running." Legacy or configured-port-only listeners still -satisfy ordinary liveness, but their detailed CLI health remains unavailable until restarted with -an attested runtime record and capability-aware server. +mechanism, not a reusable credential class. `ocx doctor` and OAuth health derive these capabilities +from the protected `runtime-port.json` secret for exactly two read-only GETs: +`/api/codex-auth/accounts` and `/api/system/memory`. Each capability is bound to its method, path, +nonce, proxy PID, and port. A short expiry is part of the HMAC, and the server consumes each +capability once. A capability cannot authorize another management route or survive process +replacement. These probes connect directly to the selected listener instead of delegating local +identity to an environment HTTP proxy. Their output distinguishes a missing proxy, rejected local +capability, and an unexpected management response so a reachable `401` cannot be reported as +"proxy not running." Legacy or configured-port-only listeners still satisfy ordinary liveness, but +their detailed CLI health remains unavailable until restarted with an attested runtime record and +capability-aware server. [Decision Log] - 목적과 의도: Keep a lower-privileged local process from collecting the management bearer by impersonating `/healthz` on an unused port. From 1c5de4af081e9bcf11206d0436ea77eb1b391ff1 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:16:42 +0200 Subject: [PATCH 4/6] test(ci): typecheck doctor service-memory contract --- tests/tsconfig.doctor-service-memory-contract.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/tsconfig.doctor-service-memory-contract.json diff --git a/tests/tsconfig.doctor-service-memory-contract.json b/tests/tsconfig.doctor-service-memory-contract.json new file mode 100644 index 0000000000..647db8a9f4 --- /dev/null +++ b/tests/tsconfig.doctor-service-memory-contract.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": ".." + }, + "include": [ + "../src", + "./doctor-service-memory-contract.test.ts" + ] +} From 7b0fc59f573580e5573a6fddad44b238138bae48 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:18:23 +0200 Subject: [PATCH 5/6] test(ci): typecheck doctor service-memory contract --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1dcd92bde2..bb7db9a8c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -405,7 +405,7 @@ jobs: bun install --frozen-lockfile - name: Typecheck - run: bun x tsc --noEmit + run: bun x tsc --noEmit -p tests/tsconfig.doctor-service-memory-contract.json - name: GUI tests run: cd gui && bun test tests @@ -717,7 +717,6 @@ jobs: run: ocx help # The one check name that means "CI passed". - # # Shard names move whenever the shard count changes, and the platform legs come # and go by trigger. Neither is a stable thing to require in branch protection. # This job is: it depends on every other job and asserts each result. `dev` has @@ -768,4 +767,4 @@ jobs: # leg is a gate violation: on push events it is always skipped, and on # dispatch a failed Windows leg already fails the allowlist above. The # old "windows must have run on main/preview" assertion left with the - # condition it policed. + # condition it policed. \ No newline at end of file From cd574638ccaa3b599b97c9f85572b3f4d34c5803 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:20:05 +0200 Subject: [PATCH 6/6] test(ci): preserve workflow formatting --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb7db9a8c4..86691d202c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -717,6 +717,7 @@ jobs: run: ocx help # The one check name that means "CI passed". + # # Shard names move whenever the shard count changes, and the platform legs come # and go by trigger. Neither is a stable thing to require in branch protection. # This job is: it depends on every other job and asserts each result. `dev` has @@ -767,4 +768,4 @@ jobs: # leg is a gate violation: on push events it is always skipped, and on # dispatch a failed Windows leg already fails the allowlist above. The # old "windows must have run on main/preview" assertion left with the - # condition it policed. \ No newline at end of file + # condition it policed.