Files
pikasTech-unidesk/scripts/platform-infra-sub2api-codex-sentinel-contract-test.ts
T
2026-06-11 05:02:27 +00:00

108 lines
6.1 KiB
TypeScript

import { readFileSync } from "node:fs";
import { rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { rootPath } from "./src/config";
import {
defaultCodexPoolSentinelConfig,
readCodexPoolSentinelConfig,
renderCodexPoolSentinelManifest,
sentinelRunnerPython,
} from "./src/platform-infra-sub2api-codex-sentinel";
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
}
const configPath = rootPath("config", "platform-infra", "sub2api-codex-pool.yaml");
const parsed = Bun.YAML.parse(readFileSync(configPath, "utf8")) as { sentinel?: unknown };
const sentinel = readCodexPoolSentinelConfig(parsed.sentinel, defaultCodexPoolSentinelConfig(), configPath);
assertCondition(sentinel.monitor.enabled === true, "sentinel monitor must be enabled for observation-first rollout", sentinel);
assertCondition(sentinel.actions.enabled === false, "sentinel actions must default off until monitoring quality is reviewed", sentinel);
assertCondition(sentinel.actions.freezeOnMarkerMismatch === true, "marker mismatch must be configured as freeze-worthy when actions are enabled", sentinel.actions);
assertCondition(sentinel.actions.freezeOnTransportError === false, "transport errors must not freeze by default", sentinel.actions);
assertCondition(sentinel.endpoint === "responses", "v1 sentinel must target OpenAI Responses only", sentinel);
assertCondition(sentinel.model === "gpt-5.5", "v1 sentinel must use GPT-5.5", sentinel);
assertCondition(sentinel.probe.maxOutputTokens > 0 && sentinel.probe.maxOutputTokens <= 16, "sentinel maxOutputTokens must be tightly capped", sentinel.probe);
assertCondition(!("concurrency" in sentinel.probe), "sentinel must not cap probe concurrency; all due accounts are probed concurrently", sentinel.probe);
assertCondition(!("maxAccountsPerRun" in sentinel.probe), "sentinel must not cap accounts per run; all due accounts are eligible", sentinel.probe);
assertCondition(sentinel.cadence.successInitialIntervalMinutes === 1, "success trust backoff must start at 1 minute", sentinel.cadence);
assertCondition(sentinel.cadence.successMaxIntervalMinutes === 20, "success trust backoff must cap at 20 minutes", sentinel.cadence);
assertCondition(sentinel.freeze.initialTtlMinutes === 10, "freeze backoff must start at 10 minutes", sentinel.freeze);
assertCondition(sentinel.freeze.maxTtlMinutes === 120, "freeze backoff must cap at 2 hours", sentinel.freeze);
assertCondition(!("budget" in sentinel), "sentinel must not use token budgets as a probe gate; usage is recorded only", sentinel);
const manifest = renderCodexPoolSentinelManifest(sentinel, [
{
accountName: "unidesk-codex-example",
profile: "example",
baseUrl: "https://example.invalid/v1",
apiKey: "sk-test-secret",
upstreamUserAgent: null,
},
], {
namespace: "platform-infra",
serviceName: "sub2api",
serviceDns: "sub2api.platform-infra.svc.cluster.local:8080",
appSecretName: "sub2api-secrets",
});
assertCondition(manifest.includes("kind: CronJob"), "sentinel manifest must render a CronJob", manifest.slice(0, 1000));
assertCondition(manifest.includes("concurrencyPolicy: Forbid"), "sentinel CronJob must forbid overlapping runs", manifest);
assertCondition(manifest.includes("suspend: false"), "monitor.enabled=true must unsuspend the CronJob", manifest);
assertCondition(manifest.includes("kind: ServiceAccount") && manifest.includes("kind: Role") && manifest.includes("kind: RoleBinding"), "sentinel manifest must include minimal RBAC", manifest);
assertCondition(manifest.includes("sub2api-account-sentinel-state"), "sentinel manifest must reference the state ConfigMap", manifest);
assertCondition(manifest.includes("\"enabled\": false"), "sentinel manifest must preserve actions.enabled=false in config.json", manifest);
assertCondition(!manifest.includes("sk-test-secret"), "sentinel manifest must not expose upstream credentials as plaintext", manifest);
assertCondition(manifest.includes("profiles.json:"), "sentinel credentials Secret must include the profiles payload as Secret data", manifest);
assertCondition(manifest.includes("\"budgetMode\": \"record-only\""), "sentinel runner must expose record-only budget/accounting mode", manifest);
assertCondition(manifest.includes("max_workers=max(1, len(due))"), "sentinel runner must probe all due accounts concurrently", manifest);
const disabledMonitor = {
...sentinel,
monitor: { enabled: false },
actions: { ...sentinel.actions, enabled: false },
};
const suspendedManifest = renderCodexPoolSentinelManifest(disabledMonitor, [], {
namespace: "platform-infra",
serviceName: "sub2api",
serviceDns: "sub2api.platform-infra.svc.cluster.local:8080",
appSecretName: "sub2api-secrets",
});
assertCondition(suspendedManifest.includes("suspend: true"), "monitor.enabled=false must suspend the CronJob", suspendedManifest);
const pythonPath = join(tmpdir(), `sub2api-account-sentinel-${process.pid}.py`);
writeFileSync(pythonPath, sentinelRunnerPython(), "utf8");
try {
const pyCompile = Bun.spawnSync(["python3", "-m", "py_compile", pythonPath], {
stdout: "pipe",
stderr: "pipe",
});
assertCondition(pyCompile.exitCode === 0, "sentinel runner python must compile", {
exitCode: pyCompile.exitCode,
stdout: pyCompile.stdout.toString(),
stderr: pyCompile.stderr.toString(),
});
} finally {
rmSync(pythonPath, { force: true });
}
console.log(JSON.stringify({
ok: true,
checks: [
"sentinel has independent monitor/actions YAML switches",
"observation-first rollout keeps actions disabled",
"v1 scope is OpenAI Responses + GPT-5.5",
"probe max_output_tokens is tightly capped",
"probe concurrency is not artificially capped",
"budget is record-only and does not gate probes",
"success trust backoff is 1m to 20m",
"freeze backoff is 10m to 120m",
"CronJob is k8s-native with Forbid concurrency and minimal RBAC",
"monitor switch controls CronJob suspend state",
"rendered Secret avoids plaintext upstream credentials",
"embedded Python runner compiles",
],
}));