Files
pikasTech-unidesk/scripts/src/agentrun-secret-sync-output.test.ts
T
2026-07-12 18:08:35 +02:00

218 lines
8.9 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { parseSecretSyncOptions } from "./agentrun/control-plane";
import type { SecretSyncOptions } from "./agentrun/options";
import { compactAgentRunSecretSyncPayload, renderAgentRunSecretSyncResult } from "./agentrun/secret-sync-output";
import { confirmedSecretSyncPlan } from "./agentrun/trigger";
const options = (output: SecretSyncOptions["output"], overrides: Partial<SecretSyncOptions> = {}): SecretSyncOptions => ({
confirm: false,
dryRun: true,
node: "NC01",
lane: "nc01-v02",
secretIds: [],
full: false,
raw: false,
output,
...overrides,
});
function blockedFixture(): Record<string, unknown> {
const planItems = Array.from({ length: 13 }, (_, index) => {
const id = index === 11 ? "tool-github-ssh-private-key" : index === 12 ? "tool-github-ssh-known-hosts" : `fixture-secret-${index}`;
return {
id,
namespace: "agentrun-v02",
secret: index >= 11 ? "agentrun-v01-tool-github-ssh" : `fixture-target-${index}`,
key: index === 11 ? "id_ed25519" : index === 12 ? "known_hosts" : `key-${index}`,
sourceMode: "file",
sourcePath: "/root/.unidesk/.state/secrets/<redacted>",
present: true,
sourceFilePresent: true,
fingerprint: `sha256:${String(index).padStart(64, "a")}`,
valueBytes: 120 + index,
degradedReason: null,
valuesPrinted: false,
};
});
return {
ok: false,
command: "agentrun control-plane secret-sync",
mode: "dry-run-blocked-before-mutation",
status: "blocked",
mutation: false,
blockedBeforeMutation: true,
secretSyncStarted: false,
target: { node: "NC01", lane: "nc01-v02", namespace: "agentrun-v02", valuesPrinted: false },
degradedReason: "provider-secret-activation-fence-unavailable",
plan: { secretCount: planItems.length, items: planItems, omittedCount: 0, valuesPrinted: false },
activationPreflight: {
ok: false,
status: "blocked",
reason: "provider-secret-activation-fence-unavailable",
targetSecretCount: 1,
targetSecrets: [{
namespace: "agentrun-v02",
name: "agentrun-v01-provider-codex",
desiredKeys: ["auth.json", "config.toml"],
queryOk: true,
present: true,
mutationCount: 1,
noOp: false,
mutations: [{
id: "provider-codex-config",
key: "config.toml",
desiredFingerprintSuffix: "aaaaaaaaaaaa",
runtimeFingerprintSuffix: "bbbbbbbbbbbb",
changeKind: "change-key",
valuesPrinted: false,
}],
valuesPrinted: false,
}],
activationRiskCount: 1,
activationRisks: [{
pod: "agentrun-runner-rjob_fixture-pod",
jobName: "agentrun-runner-rjob_fixture",
phase: "Pending",
runId: "run_fixture",
commandId: "cmd_fixture",
runnerJobId: "rjob_fixture",
waitingReasons: ["CreateContainerConfigError"],
classification: "nonterminal-runner-required-provider-secret-missing",
dependencies: [{
source: "volume-secret",
name: "agentrun-v01-provider-codex",
affectedDesiredKeys: ["config.toml"],
mutationKinds: ["change-key"],
reason: "nonterminal-runner-provider-secret-mutation",
valuesPrinted: false,
}],
valuesPrinted: false,
}],
requiresManagerFence: true,
targetSecretObservationComplete: true,
runnerObservationComplete: true,
allObservationsComplete: true,
providerSecretMutationCount: 1,
providerSecretDataNoOp: false,
providerSecretMutationAuthorized: false,
managerAuthority: {
owner: "agentrun-manager-provider-activation-fence",
atomicFenceAvailable: false,
mutationAuthorized: false,
noOpOnly: true,
trackingIssue: "https://github.com/pikasTech/agentrun/issues/284",
valuesPrinted: false,
},
capture: {
stdoutTail: "FULL_PROBE_BODY_ONLY_VISIBLE_WITH_EXPLICIT_FULL",
valuesPrinted: false,
},
valuesPrinted: false,
},
execution: {
providerSecretClassification: "exact-target-ref",
providerSecretWriteBlockedCount: 2,
secretSyncStarted: false,
valuesPrinted: false,
},
next: {
observeRunners: "bun scripts/cli.ts agentrun control-plane cleanup-runners --node NC01 --lane nc01-v02 --dry-run",
retryAfterManagerFence: "bun scripts/cli.ts agentrun control-plane secret-sync --node NC01 --lane nc01-v02 --confirm",
},
valuesPrinted: false,
};
}
describe("AgentRun secret-sync bounded output", () => {
test("confirmed sync reports all written secrets without stale provider classification", () => {
const items = [{ id: "provider-gpt-pika-auth-json" }, { id: "provider-gpt-pika-config" }];
expect(confirmedSecretSyncPlan(items, 2)).toEqual({
secretCount: 2,
items,
writableSecretCount: 2,
valuesPrinted: false,
});
});
test("parses compact machine output and explicit disclosure options", () => {
expect(parseSecretSyncOptions(["--node", "NC01", "--lane", "nc01-v02", "--dry-run", "-o", "yaml"])).toEqual({
confirm: false,
dryRun: true,
node: "NC01",
lane: "nc01-v02",
secretIds: [],
full: false,
raw: false,
output: "yaml",
});
expect(parseSecretSyncOptions(["--node", "NC01", "--lane", "nc01-v02", "--secret-id", "tool-github-ssh-private-key", "--full", "--output=json"])).toMatchObject({
secretIds: ["tool-github-ssh-private-key"],
full: true,
raw: false,
output: "json",
});
expect(parseSecretSyncOptions(["--node", "NC01", "--lane", "nc01-v02", "--raw"])).toMatchObject({ full: true, raw: true });
expect(() => parseSecretSyncOptions(["--node", "NC01", "--lane", "nc01-v02", "-o", "wide"])).toThrow("must be one of human,json,yaml");
});
test("uses one bounded Secret-safe projection for human, JSON, and YAML", () => {
const fixture = blockedFixture();
const compact = compactAgentRunSecretSyncPayload(fixture);
const human = renderAgentRunSecretSyncResult(fixture, options("human")).renderedText;
const jsonText = renderAgentRunSecretSyncResult(fixture, options("json")).renderedText;
const yamlText = renderAgentRunSecretSyncResult(fixture, options("yaml")).renderedText;
const json = JSON.parse(jsonText) as Record<string, any>;
const yaml = Bun.YAML.parse(yamlText) as Record<string, any>;
expect(json).toEqual(compact);
expect(yaml).toEqual(json);
expect(json.kind).toBe("AgentRunSecretSyncPlan");
expect(json.status).toMatchObject({ status: "blocked", reason: "provider-secret-activation-fence-unavailable", mutation: false, valuesPrinted: false });
expect(json.plan.secretCount).toBe(13);
expect(json.plan.omittedCount).toBe(0);
expect(json.plan.items.some((item: Record<string, unknown>) => item.id === "tool-github-ssh-private-key")).toBe(true);
expect(json.plan.items.some((item: Record<string, unknown>) => item.id === "tool-github-ssh-known-hosts")).toBe(true);
expect(json.activationFence).toMatchObject({
kind: "ProviderSecretActivationFence",
identity: "providersecretactivationfence/NC01/nc01-v02",
status: "blocked",
reason: "provider-secret-activation-fence-unavailable",
resourceCount: 1,
valuesPrinted: false,
});
expect(json.activationFence.resources[0]).toMatchObject({
identity: "runnerjob/rjob_fixture",
status: "Pending",
runId: "run_fixture",
commandId: "cmd_fixture",
runnerJobId: "rjob_fixture",
});
expect(json.activationFence.resources[0].drillDown.map((item: Record<string, unknown>) => item.identity)).toEqual([
"runnerjob/rjob_fixture",
"command/cmd_fixture",
"run/run_fixture",
]);
expect(json.next.secretById).toContain("--secret-id <secret-id> --dry-run -o json");
expect(human).toContain("ACTIVATION FENCE");
expect(human).toContain("runnerjob/rjob_fixture");
expect(human).toContain("tool-github-ssh-private-key");
expect(human).toContain("VALUES PRINTED false");
for (const output of [human, jsonText, yamlText]) {
expect(Buffer.byteLength(output, "utf8")).toBeLessThan(10_240);
expect(output).not.toContain("FULL_PROBE_BODY_ONLY_VISIBLE_WITH_EXPLICIT_FULL");
expect(output).not.toContain("/root/.unidesk/.state/secrets/<redacted>");
}
});
test("keeps exhaustive probe details behind explicit full or raw", () => {
const fixture = blockedFixture();
const full = renderAgentRunSecretSyncResult(fixture, options("json", { full: true })).renderedText;
const raw = renderAgentRunSecretSyncResult(fixture, options("human", { full: true, raw: true })).renderedText;
expect(JSON.parse(full)).toEqual(fixture);
expect(JSON.parse(raw)).toEqual(fixture);
expect(full).toContain("FULL_PROBE_BODY_ONLY_VISIBLE_WITH_EXPLICIT_FULL");
expect(raw).toContain("FULL_PROBE_BODY_ONLY_VISIBLE_WITH_EXPLICIT_FULL");
});
});