Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion src/server/local-management-read-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export interface LocalManagementReadDeps {
readRuntime?: (pid: number) => RuntimePortState | null;
createNonce?: () => string;
now?: () => number;
}

export interface LocalManagementReadRequestDeps extends LocalManagementReadDeps {
timeoutMs?: number;
}

Expand All @@ -34,7 +37,7 @@ export interface LocalManagementReadDeps {
export async function fetchBoundLocalManagementRead(
target: LiveProxy,
path: LocalManagementReadPath,
deps: LocalManagementReadDeps = {},
deps: LocalManagementReadRequestDeps = {},
): Promise<LocalManagementReadResult> {
if (
target.source !== "runtime"
Expand Down
23 changes: 11 additions & 12 deletions structure/05_gui-and-management-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
13 changes: 13 additions & 0 deletions tests/doctor-service-memory-contract.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { describe, expect, test } from "bun:test";
import { fetchServiceMemory } from "../src/cli/doctor";

type ServiceMemoryDeps = NonNullable<Parameters<typeof fetchServiceMemory>[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);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});
});
10 changes: 10 additions & 0 deletions tests/tsconfig.doctor-service-memory-contract.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"rootDir": ".."
},
"include": [
"../src",
"./doctor-service-memory-contract.test.ts"
]
}
Loading