perf(secrets): narrow dry-run auth store preflight

This commit is contained in:
Vincent Koc
2026-04-07 10:39:45 +01:00
parent 2b5f663c9c
commit b4d0d6fcc9
2 changed files with 73 additions and 0 deletions

View File

@@ -304,6 +304,75 @@ describe("secrets apply", () => {
expect(callLog.split("\n").filter((line) => line.trim().length > 0).length).toBeGreaterThan(0);
});
it("ignores unrelated auth-profile store refs during allowExec dry-run preflight", async () => {
if (process.platform === "win32") {
return;
}
const execScriptPath = path.join(fixture.rootDir, "resolver.sh");
await fs.writeFile(
execScriptPath,
[
"#!/bin/sh",
"cat >/dev/null",
'printf \'{"protocolVersion":1,"values":{"providers/openai/apiKey":"sk-openai-exec"}}\'', // pragma: allowlist secret
].join("\n"),
{ encoding: "utf8", mode: 0o700 },
);
await writeJsonFile(fixture.configPath, {
secrets: {
providers: {
execmain: {
source: "exec",
command: execScriptPath,
jsonOnly: true,
timeoutMs: 20_000,
noOutputTimeoutMs: 10_000,
},
},
},
models: {
providers: {
openai: createOpenAiProviderConfig(),
},
},
});
await writeJsonFile(fixture.authStorePath, {
version: 1,
profiles: {
"openai:default": {
type: "api_key",
provider: "openai",
keyRef: { source: "env", provider: "default", id: "MISSING_AUTH_STORE_KEY" },
},
},
});
const plan = createPlan({
targets: [
{
type: "models.providers.apiKey",
path: "models.providers.openai.apiKey",
providerId: "openai",
ref: { source: "exec", provider: "execmain", id: "providers/openai/apiKey" },
},
],
options: {
scrubEnv: false,
scrubAuthProfilesForProviderTargets: false,
scrubLegacyAuthJson: false,
},
});
await expect(
runSecretsApply({ plan, env: fixture.env, write: false, allowExec: true }),
).resolves.toMatchObject({
mode: "dry-run",
skippedExecRefs: 0,
checks: { resolvabilityComplete: true },
});
});
it("rejects write mode for exec plans unless allowExec is set", async () => {
const plan = createPlan({
targets: [

View File

@@ -695,6 +695,10 @@ async function validateProjectedSecretsState(params: {
await prepareSecretsRuntimeSnapshot({
config: params.nextConfig,
env: params.env,
// Dry-run preflight only needs auth-store materialization when this plan
// actually touches auth-profile state. Write mode keeps the stricter
// whole-runtime check.
includeAuthStoreRefs: params.write || params.authStoreByPath.size > 0,
loadAuthStore: (agentDir?: string) => {
const storePath = resolveUserPath(resolveAuthStorePath(agentDir));
const override = authStoreLookup.get(storePath);