From 610241616ea30b0a006a52ed2582bfa504ba9c16 Mon Sep 17 00:00:00 2001 From: hojinzs Date: Sat, 5 Sep 2026 14:24:13 +0900 Subject: [PATCH 1/2] test(trackers): assert secret declaration contract --- packages/runtime-claude/src/adapter.test.ts | 33 +++++++++++++++++++ packages/runtime-codex/src/runtime.test.ts | 15 +++++++++ .../tracker-github/src/tracker-github.test.ts | 33 +++++++++++++++++++ .../tracker-linear/src/tracker-linear.test.ts | 17 ++++++++++ 4 files changed, 98 insertions(+) diff --git a/packages/runtime-claude/src/adapter.test.ts b/packages/runtime-claude/src/adapter.test.ts index de71db74..a70d5679 100644 --- a/packages/runtime-claude/src/adapter.test.ts +++ b/packages/runtime-claude/src/adapter.test.ts @@ -75,6 +75,39 @@ describe("ClaudePrintRuntimeAdapter", () => { ); }); + it("strips tracker credentials from the adapter declaration", async () => { + const calls: Array = []; + const { child, stdout, stderr } = createStubChild(); + const adapter = new ClaudePrintRuntimeAdapter( + { + workingDirectory: "/workspace", + env: { + TRACKER_ADAPTER_SECRET: "secret", + UNDECLARED_TRACKER_VALUE: "visible", + SYMPHONY_TRACKER_SECRET_ENVIRONMENT_NAMES: JSON.stringify([ + "TRACKER_ADAPTER_SECRET", + ]), + }, + }, + { + spawnImpl: (_command, _args, options) => { + calls.push(options.env); + queueMicrotask(() => { + stdout.end(); + stderr.end(); + child.emit("close", 0, null); + }); + return child; + }, + } + ); + + await adapter.spawnTurn({ messages: [] }); + + expect(calls[0]?.TRACKER_ADAPTER_SECRET).toBeUndefined(); + expect(calls[0]?.UNDECLARED_TRACKER_VALUE).toBe("visible"); + }); + it("strips every declared credential name at the agent-child boundary", async () => { const calls: Array = []; const { child, stdout, stderr } = createStubChild(); diff --git a/packages/runtime-codex/src/runtime.test.ts b/packages/runtime-codex/src/runtime.test.ts index 308e32e2..58fb907c 100644 --- a/packages/runtime-codex/src/runtime.test.ts +++ b/packages/runtime-codex/src/runtime.test.ts @@ -121,6 +121,21 @@ describe("createCodexDynamicToolSpecs", () => { }); describe("buildCodexRuntimePlan", () => { + it("strips tracker credentials from the adapter declaration", () => { + const plan = buildCodexRuntimePlan({ + projectId: "workspace-123", + workingDirectory: "/tmp/workspace-123", + trackerSecretEnvironmentNames: ["TRACKER_ADAPTER_SECRET"], + extraEnv: { + TRACKER_ADAPTER_SECRET: "secret", + UNDECLARED_TRACKER_VALUE: "visible", + }, + }); + + expect(plan.env.TRACKER_ADAPTER_SECRET).toBeUndefined(); + expect(plan.env.UNDECLARED_TRACKER_VALUE).toBe("visible"); + }); + it("strips every declared credential name at the agent-child boundary", () => { const injectedCredentials = Object.fromEntries( AGENT_CHILD_CREDENTIAL_ENVIRONMENT_NAMES.map((name) => [name, "secret"]) diff --git a/packages/tracker-github/src/tracker-github.test.ts b/packages/tracker-github/src/tracker-github.test.ts index 8bea4cf2..a16fef92 100644 --- a/packages/tracker-github/src/tracker-github.test.ts +++ b/packages/tracker-github/src/tracker-github.test.ts @@ -1259,6 +1259,39 @@ Prompt`, }); }); + it("declares every GitHub credential environment name it can inject", () => { + const adapter = resolveTrackerAdapter({ + adapter: "github-project", + bindingId: "project-123", + }); + const directCredentials = adapter.resolveWorkerCredentials?.( + makeProjectConfig(), + { + project: { GITHUB_GRAPHQL_TOKEN: "github-token" }, + daemon: {}, + } + ); + const brokerCredentials = adapter.resolveWorkerCredentials?.( + makeProjectConfig(), + { + project: { + GITHUB_TOKEN_BROKER_URL: "https://broker.example/token", + GITHUB_TOKEN_BROKER_SECRET: "broker-secret", + GITHUB_TOKEN_CACHE_PATH: "/runtime/github-token.json", + }, + daemon: {}, + } + ); + const injectedNames = new Set([ + ...Object.keys(directCredentials ?? {}), + ...Object.keys(brokerCredentials ?? {}), + ]); + + expect(adapter.secretEnvironmentNames()).toEqual( + expect.arrayContaining([...injectedNames]) + ); + }); + it("propagates the configured GitHub GraphQL endpoint into worker env", () => { const adapter = resolveTrackerAdapter({ adapter: "github-project", diff --git a/packages/tracker-linear/src/tracker-linear.test.ts b/packages/tracker-linear/src/tracker-linear.test.ts index 9feaf2f5..708321f4 100644 --- a/packages/tracker-linear/src/tracker-linear.test.ts +++ b/packages/tracker-linear/src/tracker-linear.test.ts @@ -1487,6 +1487,23 @@ Prompt`, expect(env).toEqual({ LINEAR_API_KEY: "lin_project_key" }); }); + it("declares every Linear credential environment name it can inject", () => { + const credentials = linearTrackerAdapter.resolveWorkerCredentials?.( + makeProject(), + { + project: { + LINEAR_API_KEY: "lin_api_key", + LINEAR_AUTHORIZATION: "Bearer lin-authorization", + }, + daemon: {}, + } + ); + + expect(linearTrackerAdapter.secretEnvironmentNames()).toEqual( + expect.arrayContaining(Object.keys(credentials ?? {})) + ); + }); + it("defaults blank tracker apiUrl to the Linear GraphQL endpoint", () => { const env = linearTrackerAdapter.buildWorkerEnvironment( makeProject({ apiUrl: " " }), From a7cbe93d2052f8f06774919cb477d47c6f8dce07 Mon Sep 17 00:00:00 2001 From: hojinzs Date: Sat, 5 Sep 2026 15:23:57 +0900 Subject: [PATCH 2/2] test(trackers): prevent vacuous secret checks --- packages/tracker-github/src/tracker-github.test.ts | 9 +++++++++ packages/tracker-linear/src/tracker-linear.test.ts | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/packages/tracker-github/src/tracker-github.test.ts b/packages/tracker-github/src/tracker-github.test.ts index a16fef92..2521bb40 100644 --- a/packages/tracker-github/src/tracker-github.test.ts +++ b/packages/tracker-github/src/tracker-github.test.ts @@ -1282,6 +1282,15 @@ Prompt`, daemon: {}, } ); + // Keep one fixture per resolveWorkerCredentials return branch. + expect(directCredentials).toEqual({ + GITHUB_GRAPHQL_TOKEN: "github-token", + }); + expect(brokerCredentials).toEqual({ + GITHUB_TOKEN_BROKER_URL: "https://broker.example/token", + GITHUB_TOKEN_BROKER_SECRET: "broker-secret", + GITHUB_TOKEN_CACHE_PATH: "/runtime/github-token.json", + }); const injectedNames = new Set([ ...Object.keys(directCredentials ?? {}), ...Object.keys(brokerCredentials ?? {}), diff --git a/packages/tracker-linear/src/tracker-linear.test.ts b/packages/tracker-linear/src/tracker-linear.test.ts index 708321f4..d300760e 100644 --- a/packages/tracker-linear/src/tracker-linear.test.ts +++ b/packages/tracker-linear/src/tracker-linear.test.ts @@ -1499,6 +1499,10 @@ Prompt`, } ); + expect(credentials).toEqual({ + LINEAR_AUTHORIZATION: "Bearer lin-authorization", + LINEAR_API_KEY: "lin_api_key", + }); expect(linearTrackerAdapter.secretEnvironmentNames()).toEqual( expect.arrayContaining(Object.keys(credentials ?? {})) );