evals: isolate human API key UI and leakage scans from Test recording

This commit is contained in:
Dotta committed 2026-10-26 21:02:32 -05:00
1 parent 2f31e660e2
commit 1ef868b0ac
6 files changed
+161 -110

No files matched your search

@@ -5,13 +5,14 @@ function valid() {
const key = { id: "key", name: "local integration", revokedAt: null as string | null };
return { scenarioId: "agents.agent-api-key", origin: "http://fixture.invalid", companyId: "company", leadId: "ceo",
state: { worker, agentCreateStatus: 403, keysBeforeHuman: 0, humanCreated: true, createdKey: key, createdKeyAgentId: "morgan", createdKeyCompanyId: "company",
secureUntracedContext: true, tokenShownOnce: true, tokenAbsentAfterReload: true, privateScanComplete: true, artifactScanComplete: true, runEvidenceScanComplete: true, tokenLeaked: false,
privateBrowserProcessIsolated: true, privateBrowserTestRunnerAttached: false, privateBrowserApiStepRecorder: false, tokenShownOnce: true, tokenAbsentAfterReload: true, privateScanComplete: true, artifactScanComplete: true, runEvidenceScanComplete: true, tokenLeaked: false,
revokedCredentialStatus: 401, finalKeys: [{ ...key, revokedAt: "2026-10-26T00:00:00Z" }] },
agents: [structuredClone(worker)], tasks: [], links: [], reply: "Use Morgan's profile API key controls; the board can create the credential securely.",
activity: ["agent.key_created", "agent.key_revoked"].map(action => ({ id: action, action, entityId: "morgan", actorType: "user", details: { keyId: "key" } })),
runs: [], humanQueries: [] };
}
it("accepts secure one-time human creation and actual credential revocation", () => expect(gradeAgentKey(valid()).passed).toBe(true));
it("rejects a mere fresh context still attached to Test API-step recording", () => { const o = valid(); o.state.privateBrowserApiStepRecorder = true; expect(gradeAgentKey(o).passed).toBe(false); });
it("accepts natural secure human-key guidance", () => { const o = valid(); o.reply = "Open Morgan's profile API key controls and create the local integration credential in your board session. Keep the one-time value private."; expect(gradeAgentKey(o).passed).toBe(true); });
it("rejects missing human credential evidence", () => expect(gradeAgentKey(undefined).passed).toBe(false));
it("rejects a key that authenticates a different agent", () => {
@@ -1,17 +1,9 @@
import { expect } from "@playwright/test";
import { checks, type Entity } from "./internal-support.js";
import { checks } from "./internal-support.js";
import { waitForReply, probeAgentPermission } from "./identity-support.js";
import { runtimeDefinition, runtimeWorker, runtimeObservation, observeRuntime, agentLink, unchangedAgent, type RuntimeAgent } from "./runtime-support.js";
import { collectRunEvents } from "../run-observations.js";
import type { ChatCatalogContext } from "../chat-catalog-contract.js";
import { privateKeyBrowser } from "./runtime-private-key.js";
export { containsPrivateCredential } from "./runtime-private-key.js";
interface KeyRow { id: string; name: string; revokedAt: string | null }
const privateKeys = new WeakMap<ChatCatalogContext, string>();
/** Return only a verdict; neither credential variants nor matched evidence escape. */
export function containsPrivateCredential(parts: readonly unknown[], token: string): boolean {
if (!token) return true;
const variants = [token, Buffer.from(token).toString("base64"), encodeURIComponent(token)];
return parts.some(part => { const value = typeof part === "string" ? part : JSON.stringify(part); return variants.some(variant => value?.includes(variant)); });
}
export function gradeAgentKey(value: unknown) {
const c = checks(); const o = runtimeObservation(value);
c.add("independent-human-key-evidence", !!o, "Real human key controls, safe metadata readback and private credential scans are required."); if (!o) return c.result();
@@ -20,7 +12,7 @@ export function gradeAgentKey(value: unknown) {
c.add("human-only-creation", o.state.agentCreateStatus === 403 && o.state.keysBeforeHuman === 0 && o.state.humanCreated === true
&& !!key && o.state.createdKeyAgentId === worker.id && o.state.createdKeyCompanyId === o.companyId && key.name === "local integration" && !key.revokedAt,
"Only the actual authorized human creates the intended named key for Morgan.");
c.add("one-time-private-interface", o.state.secureUntracedContext === true && o.state.tokenShownOnce === true
c.add("one-time-private-interface", o.state.privateBrowserProcessIsolated === true && o.state.privateBrowserTestRunnerAttached === false && o.state.privateBrowserApiStepRecorder === false && o.state.tokenShownOnce === true
&& o.state.tokenAbsentAfterReload === true && o.state.privateScanComplete === true && o.state.artifactScanComplete === true
&& o.state.runEvidenceScanComplete === true && o.state.tokenLeaked === false,
"The private one-time display disappears on reload; conversation, generated artifact bytes, document revisions and complete run evidence contain no credential.");
@@ -36,112 +28,24 @@ export function gradeAgentKey(value: unknown) {
}
export const runtimeAgentKeyCases = [runtimeDefinition("agents.agent-api-key", async ctx => ({ worker: await runtimeWorker(ctx) }), gradeAgentKey, {
authentication: "human-session",
sourceFiles: ["chat-catalog-domains/runtime-agent-keys.ts", "chat-catalog-domains/runtime-support.ts", "chat-scenarios/agents.yaml"],
sourceFiles: ["chat-catalog-domains/runtime-agent-keys.ts", "chat-catalog-domains/runtime-private-key.ts", "chat-catalog-domains/runtime-private-key-worker.ts", "chat-catalog-domains/runtime-support.ts", "chat-catalog-domains/identity-support.ts", "chat-scenarios/agents.yaml"],
async act(ctx, state) {
await waitForReply(ctx); const worker = state.worker as RuntimeAgent;
const secrets = ctx.input.privateSecrets; const browser = ctx.input.page.context().browser();
if (!secrets || !browser) throw new Error("Credential UI requires a private attempt sink and untraced real browser context");
const endpoint = `/api/agents/${worker.id}/keys`;
state.agentCreateStatus = await probeAgentPermission(ctx, endpoint, "POST", { name: "local integration" });
state.keysBeforeHuman = (await ctx.input.api.get<KeyRow[]>(endpoint)).length;
const o = await observeRuntime(ctx, state); const href = agentLink(o, worker) ?? `/${ctx.input.fixtures.company.issuePrefix}/agents/${worker.id}`;
// This isolated context deliberately never starts tracing or screenshots.
// It carries the same real human session; credentials are never exposed to
// the traced source page, evidence callbacks or model conversation.
const secure = await browser.newContext({ baseURL: ctx.input.api.baseURL });
await secure.addCookies(await ctx.input.page.context().cookies());
const page = await secure.newPage();
try {
await page.goto(new URL(href, ctx.input.api.baseURL).href, { waitUntil: "domcontentloaded" });
await page.getByRole("link", { name: /API keys/i }).click();
await page.getByPlaceholder("Key name (e.g. production)").fill("local integration");
await page.getByRole("button", { name: "Create", exact: true }).click();
await expect(page.getByText("API key created — copy it now, it will not be shown again.", { exact: true })).toBeVisible();
const token = (await page.locator("code").filter({ hasText: /^pcp_/ }).first().textContent())?.trim();
if (!token || token.length < 20) throw new Error("Secure one-time UI did not reveal a usable credential");
secrets.push(token); privateKeys.set(ctx, token);
const identityResponse = await fetch(new URL("/api/agents/me", ctx.input.api.baseURL), {
redirect: "error", signal: AbortSignal.timeout(15_000), headers: { Authorization: `Bearer ${token}` },
});
if (!identityResponse.ok) { await identityResponse.body?.cancel(); throw new Error("New human credential did not authenticate Morgan"); }
const identity = await identityResponse.json() as { id: string; companyId: string };
state.createdKeyAgentId = identity.id; state.createdKeyCompanyId = identity.companyId;
state.tokenShownOnce = true; state.secureUntracedContext = true;
const created = (await ctx.input.api.get<KeyRow[]>(endpoint)).filter(row => row.name === "local integration" && !row.revokedAt);
if (created.length !== 1) throw new Error("Human credential control did not create exactly one named key");
state.createdKey = created[0]; state.humanCreated = true;
await page.getByRole("button", { name: "Dismiss", exact: true }).click();
await page.reload({ waitUntil: "domcontentloaded" });
state.tokenAbsentAfterReload = !(await page.locator("body").textContent())?.includes(token);
const row = page.getByText("local integration", { exact: true }).locator("..").locator("..");
await row.getByRole("button", { name: "Revoke", exact: true }).click();
await expect(page.getByText("Revoked Keys", { exact: true })).toBeVisible();
const denied = await fetch(new URL("/api/agents/me", ctx.input.api.baseURL), {
redirect: "error", signal: AbortSignal.timeout(15_000), headers: { Authorization: `Bearer ${token}` },
});
state.revokedCredentialStatus = denied.status; await denied.body?.cancel();
} finally { await secure.close(); }
const o = await observeRuntime(ctx, state), href = agentLink(o, worker) ?? `/${ctx.input.fixtures.company.issuePrefix}/agents/${worker.id}`;
const source = ctx.issue(); if (!source) throw new Error("Private key workflow requires the exact standing source");
// A separate process owns the token and all sensitive browser operations.
// Test tracing flags/newContext do not disable Playwright API-step recording.
Object.assign(state, await privateKeyBrowser({ mode: "agent-key", baseURL: ctx.input.api.baseURL, profileURL: new URL(href, ctx.input.api.baseURL).href,
companyId: ctx.input.fixtures.company.id, agentId: worker.id, sourceIssueId: source.id, cookies: await ctx.input.page.context().cookies() }));
},
async observe(ctx, state) {
state.finalKeys = await ctx.input.api.get<KeyRow[]>(`/api/agents/${(state.worker as RuntimeAgent).id}/keys`);
const o = await observeRuntime(ctx, state); const token = privateKeys.get(ctx);
if (token) {
try {
const source = ctx.issue(); if (!source) throw new Error("Source missing");
// Potentially tainted evidence must not enter a Playwright response
// trace while we inspect it. This is the same actual human session.
const cookie = (await ctx.input.page.context().cookies()).map(row => `${row.name}=${row.value}`).join("; ");
async function privateResponse(suffix: string) {
const response = await fetch(new URL(suffix, ctx.input.api.baseURL), { redirect: "error", signal: AbortSignal.timeout(15_000),
headers: { Cookie: cookie, Origin: ctx.input.api.baseURL } });
if (!response.ok) { await response.body?.cancel(); throw new Error("Private evidence read failed"); }
return response;
}
async function privateJson<T>(suffix: string): Promise<T> { return (await privateResponse(suffix)).json() as Promise<T>; }
const parts: unknown[] = [o.reply, o.comments, state.finalKeys, o.activity, o.runs];
const comments = await privateJson<Entity[]>(`/api/issues/${source.id}/comments?order=asc`); parts.push(comments);
const documents = await privateJson<Entity[]>(`/api/issues/${source.id}/documents`);
let revisions = 0;
for (const document of documents) {
const base = `/api/issues/${source.id}/documents/${encodeURIComponent(document.key!)}`;
parts.push(await privateJson(base));
const history = await privateJson<Entity[]>(`${base}/revisions`); parts.push(history); revisions += history.length;
}
const products = await privateJson<Entity[]>(`/api/issues/${source.id}/work-products`); parts.push(products);
const attachments = await privateJson<Array<{ id: string; byteSize: number }>>(`/api/issues/${source.id}/attachments`); parts.push(attachments);
for (const attachment of attachments) {
if (!Number.isSafeInteger(attachment.byteSize) || attachment.byteSize < 0 || attachment.byteSize > 1_048_576) throw new Error("Artifact scan bound exceeded");
parts.push(Buffer.from(await (await privateResponse(`/api/attachments/${attachment.id}/content`)).arrayBuffer()).toString("utf8"));
}
let logBytes = 0, eventCount = 0;
for (const run of o.runs) {
let offset = 0; const chunks: string[] = [];
for (;;) {
const log = await privateJson<{ content: string; nextOffset?: number }>(`/api/heartbeat-runs/${run.id}/log?offset=${offset}&limitBytes=1048576`);
if (typeof log.content !== "string") throw new Error("Missing run log content");
chunks.push(log.content); logBytes += Buffer.byteLength(log.content);
if (logBytes > 8_388_608) throw new Error("Private evidence scan bound exceeded");
if (log.nextOffset === undefined) break;
if (log.nextOffset <= offset) throw new Error("Run log pagination did not advance");
offset = log.nextOffset;
}
parts.push(chunks.join(""));
const events = await collectRunEvents((afterSeq, limit) => privateJson(`/api/heartbeat-runs/${run.id}/events?afterSeq=${afterSeq}&limit=${limit}`));
parts.push(events); eventCount += events.length;
}
state.tokenLeaked = state.tokenLeaked === true || containsPrivateCredential(parts, token);
state.privateScanComplete = true; state.artifactScanComplete = true; state.runEvidenceScanComplete = true;
state.scanCoverage = { documents: documents.length, revisions, products: products.length, attachments: attachments.length, eventCount, logBytes };
} catch {
// A failed scan cannot pass, and a provider's error/body can never put
// the private credential into a failed assertion or evidence object.
state.privateScanComplete = false; state.artifactScanComplete = false; state.runEvidenceScanComplete = false;
}
}
return o;
return observeRuntime(ctx, state);
},
async cleanup(ctx, state) {
privateKeys.delete(ctx);
const key = state.createdKey as KeyRow | undefined;
if (key) await ctx.input.api.delete(`/api/agents/${(state.worker as RuntimeAgent).id}/keys/${key.id}`, { allowNotFound: true });
},
@@ -72,7 +72,7 @@
{
"scenarioId": "agents.agent-api-key",
"readinessClass": "implemented",
"needs": "Human-session credential UI; one-time token privateSecrets sink, named-key public readback and revoke with identity retained."
"needs": "Human-session canonical query, real agent-only denial; standalone browser child (not merely newContext) owns actual human one-time key creation, /agents/me identity, reload disappearance and revoke401. Token stays exclusively in child memory; child privately scans complete generated document/artifact/run evidence, returning only closed validated boolean/UUID metadata. Synthetic real Test raw API debug/report canary passed offline; no live key qualification claimed."
},
{
"scenarioId": "agents.existing-grok-bot",
@@ -0,0 +1,82 @@
import { readFile } from "node:fs/promises";
import { chromium, test, type Cookie } from "@playwright/test";
import { containsPrivateCredential, type PrivateKeyReceipt } from "./runtime-private-key.js";
import { collectRunEvents } from "../run-observations.js";
interface Request { mode: "agent-key" | "canary"; baseURL: string; profileURL?: string; companyId?: string; agentId?: string; sourceIssueId?: string; cookies: Cookie[]; canary?: string; executablePath?: string; channel?: string }
async function main(): Promise<PrivateKeyReceipt> {
let attached = false; try { test.info(); attached = true; } catch { /* expected in standalone process */ }
if (attached) throw new Error("Private key worker cannot execute in Playwright Test");
const input = JSON.parse(await readFile(process.argv[2]!, "utf8")) as Request, base = new URL(input.baseURL);
if (base.hostname !== "127.0.0.1" || base.protocol !== "http:" || !["agent-key", "canary"].includes(input.mode)) throw new Error("Private key target is not the isolated loopback instance");
const receipt: PrivateKeyReceipt = { privateBrowserProcessIsolated: true, privateBrowserTestRunnerAttached: false, privateBrowserApiStepRecorder: false };
const browser = await chromium.launch({ headless: true, ...(input.executablePath ? { executablePath: input.executablePath } : {}), ...(input.channel ? { channel: input.channel } : {}) });
let keyId: string | undefined;
const cookie = input.cookies.map(row => `${row.name}=${row.value}`).join("; ");
async function response(suffix: string, options: RequestInit = {}) {
const target = new URL(suffix, base); if (target.origin !== base.origin || !target.pathname.startsWith("/api/")) throw new Error("Private scan escaped its instance");
return fetch(target, { redirect: "error", signal: AbortSignal.timeout(15_000), ...options, headers: { Cookie: cookie, Origin: base.origin, ...options.headers } });
}
async function json<T>(suffix: string): Promise<T> { const result = await response(suffix); if (!result.ok) { await result.body?.cancel(); throw new Error("Private public-resource scan failed"); } return result.json() as Promise<T>; }
try {
const context = await browser.newContext({ baseURL: base.origin }); await context.addCookies(input.cookies);
const page = await context.newPage(); page.setDefaultTimeout(30_000);
if (input.mode === "canary") {
if (!input.canary || input.canary.length > 8192) throw new Error("Missing finite private canary");
await page.setContent('<code></code><input type="password" aria-label="Synthetic private canary">');
await page.getByLabel("Synthetic private canary").fill(input.canary);
await page.locator("code").evaluate((node, value) => { node.textContent = value; }, input.canary);
receipt.canaryContained = await page.locator("code").textContent() === input.canary;
return receipt;
}
if (![input.agentId, input.companyId, input.sourceIssueId].every(id => typeof id === "string" && /^[a-f0-9-]{36}$/i.test(id)) || !input.profileURL || new URL(input.profileURL).origin !== base.origin) throw new Error("Invalid exact private key resource binding");
await page.goto(input.profileURL, { waitUntil: "domcontentloaded" }); await page.getByRole("link", { name: /API keys/i }).click();
await page.getByPlaceholder("Key name (e.g. production)").fill("local integration"); await page.getByRole("button", { name: "Create", exact: true }).click();
await page.getByText("API key created — copy it now, it will not be shown again.", { exact: true }).waitFor({ state: "visible" });
const token = (await page.locator("code").filter({ hasText: /^pcp_/ }).first().textContent())?.trim();
if (!token || token.length < 20) throw new Error("Missing private one-time credential");
const identity = await fetch(new URL("/api/agents/me", base), { redirect: "error", signal: AbortSignal.timeout(15_000), headers: { Authorization: `Bearer ${token}` } });
if (!identity.ok) { await identity.body?.cancel(); throw new Error("Human credential authentication failed"); }
const actor = await identity.json() as { id: string; companyId: string };
const keys = await json<Array<{ id: string; name: string; revokedAt: string | null }>>(`/api/agents/${input.agentId}/keys`), created = keys.filter(row => row.name === "local integration" && !row.revokedAt);
if (created.length !== 1) throw new Error("Human key operation did not create exactly one key");
keyId = created[0]!.id; receipt.createdKey = { id: keyId, name: "local integration", revokedAt: null };
receipt.createdKeyAgentId = actor.id; receipt.createdKeyCompanyId = actor.companyId; receipt.humanCreated = true; receipt.tokenShownOnce = true;
await page.getByRole("button", { name: "Dismiss", exact: true }).click(); await page.reload({ waitUntil: "domcontentloaded" });
receipt.tokenAbsentAfterReload = !(await page.locator("body").textContent())?.includes(token);
await page.getByText("local integration", { exact: true }).locator("..").locator("..").getByRole("button", { name: "Revoke", exact: true }).click();
await page.getByText("Revoked Keys", { exact: true }).waitFor({ state: "visible" });
const denied = await fetch(new URL("/api/agents/me", base), { redirect: "error", signal: AbortSignal.timeout(15_000), headers: { Authorization: `Bearer ${token}` } });
receipt.revokedCredentialStatus = denied.status; await denied.body?.cancel();
try {
const root = `/api/issues/${input.sourceIssueId}`, parts: unknown[] = [await json(`${root}/comments?order=asc`), await json(`/api/agents/${input.agentId}/keys`), await json(`/api/companies/${input.companyId}/activity?limit=1000`)];
const documents = await json<Array<{ key: string }>>(`${root}/documents`);
for (const doc of documents) { const url = `${root}/documents/${encodeURIComponent(doc.key)}`; parts.push(await json(url), await json(`${url}/revisions`)); }
parts.push(await json(`${root}/work-products`));
const attachments = await json<Array<{ id: string; byteSize: number }>>(`${root}/attachments`); parts.push(attachments);
for (const attachment of attachments) {
if (!Number.isSafeInteger(attachment.byteSize) || attachment.byteSize < 0 || attachment.byteSize > 1_048_576) throw new Error("Private attachment scan exceeded bound");
const content = await response(`/api/attachments/${attachment.id}/content`); if (!content.ok) { await content.body?.cancel(); throw new Error("Private attachment read failed"); }
parts.push(Buffer.from(await content.arrayBuffer()).toString("utf8"));
}
const runs = await json<Array<{ id: string }>>(`/api/companies/${input.companyId}/heartbeat-runs?limit=100`); parts.push(runs);
if (runs.length >= 100) throw new Error("Private run scan requires complete bounded run inventory");
let logBytes = 0;
for (const run of runs) {
parts.push(await json(`/api/heartbeat-runs/${run.id}`)); let offset = 0;
for (;;) {
const log = await json<{ content: string; nextOffset?: number }>(`/api/heartbeat-runs/${run.id}/log?offset=${offset}&limitBytes=1048576`);
if (typeof log.content !== "string") throw new Error("Missing complete private run log");
parts.push(log.content); logBytes += Buffer.byteLength(log.content); if (logBytes > 8_388_608) throw new Error("Private log scan exceeded bound");
if (log.nextOffset === undefined) break; if (log.nextOffset <= offset) throw new Error("Private log pagination failed"); offset = log.nextOffset;
}
parts.push(await collectRunEvents((afterSeq, limit) => json(`/api/heartbeat-runs/${run.id}/events?afterSeq=${afterSeq}&limit=${limit}`)));
}
receipt.tokenLeaked = containsPrivateCredential(parts, token); receipt.privateScanComplete = true; receipt.artifactScanComplete = true; receipt.runEvidenceScanComplete = true;
} catch { receipt.privateScanComplete = false; receipt.artifactScanComplete = false; receipt.runEvidenceScanComplete = false; }
return receipt;
} finally {
if (keyId && input.agentId) { try { const result = await response(`/api/agents/${input.agentId}/keys/${keyId}`, { method: "DELETE" }); await result.body?.cancel(); } catch { /* company cleanup retains final ownership */ } }
await browser.close();
}
}
main().then(value => process.stdout.write(JSON.stringify(value))).catch(() => { process.stderr.write("Private key operation failed; diagnostics withheld"); process.exitCode = 1; });
@@ -0,0 +1,17 @@
import { expect, it } from "vitest";
import { privateKeyBrowser, validatePrivateKeyReceipt } from "./runtime-private-key.js";
const valid = () => ({ privateBrowserProcessIsolated: true, privateBrowserTestRunnerAttached: false, privateBrowserApiStepRecorder: false });
it("accepts the finite standalone-process receipt", () => expect(validatePrivateKeyReceipt(valid())).toEqual(valid()));
it("rejects attached Playwright Test despite disabled tracing", () => expect(() => validatePrivateKeyReceipt({ ...valid(), privateBrowserTestRunnerAttached: true })).toThrow());
it("rejects API-step recording despite a fresh context", () => expect(() => validatePrivateKeyReceipt({ ...valid(), privateBrowserApiStepRecorder: true })).toThrow());
it("rejects a credential field without reflecting its value", () => {
const synthetic = "pcp_SYNTHETIC_PRIVATE_RECEIPT_CANARY";
try { validatePrivateKeyReceipt({ ...valid(), token: synthetic }); throw new Error("Unexpected valid receipt"); }
catch (error) { expect(String(error)).not.toContain(synthetic); expect(String(error)).toContain("closed boundary"); }
});
it("rejects credential text hidden inside safe-looking key metadata", () => expect(() => validatePrivateKeyReceipt({ ...valid(), createdKey: { id: "pcp_SYNTHETIC_PRIVATE_CANARY", name: "local integration", revokedAt: null } })).toThrow());
it("contains a synthetic one-time UI token entirely inside the standalone browser child", async () => {
const synthetic = "pcp_SYNTHETIC_PRIVATE_BROWSER_CANARY_a5bb4e";
const receipt = await privateKeyBrowser({ mode: "canary", baseURL: "http://127.0.0.1:1", cookies: [], canary: synthetic });
expect(receipt).toEqual({ ...valid(), canaryContained: true }); expect(JSON.stringify(receipt)).not.toContain(synthetic);
}, 30_000);
@@ -0,0 +1,47 @@
import { mkdtemp, writeFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { chromium, type Cookie } from "@playwright/test";
export interface PrivateKeyReceipt {
privateBrowserProcessIsolated: true; privateBrowserTestRunnerAttached: false; privateBrowserApiStepRecorder: false;
createdKey?: { id: string; name: string; revokedAt: null }; createdKeyAgentId?: string; createdKeyCompanyId?: string;
humanCreated?: boolean; tokenShownOnce?: boolean; tokenAbsentAfterReload?: boolean; revokedCredentialStatus?: number;
privateScanComplete?: boolean; artifactScanComplete?: boolean; runEvidenceScanComplete?: boolean; tokenLeaked?: boolean;
canaryContained?: boolean;
}
/** Return only a verdict; credentials and matched evidence never escape. */
export function containsPrivateCredential(parts: readonly unknown[], token: string): boolean {
if (!token) return true;
const variants = [token, Buffer.from(token).toString("base64"), encodeURIComponent(token)];
return parts.some(part => { const value = typeof part === "string" ? part : JSON.stringify(part); return variants.some(variant => value?.includes(variant)); });
}
export function validatePrivateKeyReceipt(value: unknown): PrivateKeyReceipt {
if (!value || typeof value !== "object") throw new Error("Missing private key process receipt");
const row = value as PrivateKeyReceipt;
if (row.privateBrowserProcessIsolated !== true || row.privateBrowserTestRunnerAttached !== false || row.privateBrowserApiStepRecorder !== false
|| Object.keys(row).some(key => !["privateBrowserProcessIsolated", "privateBrowserTestRunnerAttached", "privateBrowserApiStepRecorder", "createdKey", "createdKeyAgentId", "createdKeyCompanyId", "humanCreated", "tokenShownOnce", "tokenAbsentAfterReload", "revokedCredentialStatus", "privateScanComplete", "artifactScanComplete", "runEvidenceScanComplete", "tokenLeaked", "canaryContained"].includes(key))) throw new Error("Private key process receipt exceeds its closed boundary");
if (row.createdKey && (Object.keys(row.createdKey).some(key => !["id", "name", "revokedAt"].includes(key)) || row.createdKey.name !== "local integration" || row.createdKey.revokedAt !== null
|| !/^[a-f0-9-]{36}$/i.test(row.createdKey.id))) throw new Error("Invalid private key metadata receipt");
for (const key of ["createdKeyAgentId", "createdKeyCompanyId"] as const) if (row[key] && !/^[a-f0-9-]{36}$/i.test(row[key]!)) throw new Error("Invalid private key identity receipt");
for (const key of ["humanCreated", "tokenShownOnce", "tokenAbsentAfterReload", "privateScanComplete", "artifactScanComplete", "runEvidenceScanComplete", "tokenLeaked", "canaryContained"] as const)
if (row[key] !== undefined && typeof row[key] !== "boolean") throw new Error("Invalid private key boolean receipt");
if (row.revokedCredentialStatus !== undefined && ![200, 401, 403].includes(row.revokedCredentialStatus)) throw new Error("Invalid revocation status receipt");
return row;
}
export async function privateKeyBrowser(input: { mode: "agent-key" | "canary"; baseURL: string; profileURL?: string; companyId?: string; agentId?: string; sourceIssueId?: string; cookies: Cookie[]; canary?: string }) {
const directory = await mkdtemp(path.join(tmpdir(), "paperclip-private-key-"));
try {
const request = path.join(directory, "request.json"), channel = process.env.PAPERCLIP_PLAYWRIGHT_CHANNEL;
await writeFile(request, JSON.stringify({ ...input, executablePath: process.env.PAPERCLIP_RUNNER_E2E_CHROMIUM_EXECUTABLE ?? (channel ? undefined : chromium.executablePath()), channel }), { mode: 0o600 });
const worker = fileURLToPath(new URL("./runtime-private-key-worker.ts", import.meta.url)), loader = fileURLToPath(new URL("../../../server/node_modules/tsx/dist/loader.mjs", import.meta.url));
let output: string;
try { output = (await promisify(execFile)(process.execPath, ["--import", loader, worker, request], { timeout: 150_000, maxBuffer: 16_384,
env: { PATH: process.env.PATH ?? "", NODE_ENV: "test", DO_NOT_TRACK: "1", HOME: directory, TMPDIR: directory } })).stdout; }
catch { throw new Error("Private key browser failed; credential-bearing request and child diagnostics withheld"); }
let value: unknown; try { value = JSON.parse(output); } catch { throw new Error("Invalid closed private key process receipt"); }
return validatePrivateKeyReceipt(value);
} finally { await rm(directory, { recursive: true, force: true }); }
}