源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)

This commit is contained in:
agent-radar
2026-09-02 01:05:41 +08:00
commit 04bac1f6e2
2200 changed files with 489415 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
import { readFileSync } from "node:fs";
import { X509Certificate } from "node:crypto";
import assert from "node:assert/strict";
import { test } from "node:test";
import {
createBlipSchedule,
denyHostsFromOutboundManifest,
opensslCertificateCommands,
opensslFlavor,
outboundManifestFromUnknown,
parseClientHelloVersions,
resolveEgressProfileConfig,
startEgressLab,
} from "../src/egress.ts";
import { productDiagnosticsPrecondition } from "@openwork/behaviors";
import { matchVerdictExpectations } from "@openwork/matchers";
function hi(value: number): number {
return (value >> 8) & 0xff;
}
function lo(value: number): number {
return value & 0xff;
}
function clientHelloFixture(versions: number[]): Buffer {
const supportedVersions = versions.flatMap((version) => [hi(version), lo(version)]);
const extensions = supportedVersions.length > 0
? [0x00, 0x2b, 0x00, supportedVersions.length + 1, supportedVersions.length, ...supportedVersions]
: [];
const body = [
0x03,
0x03,
...Array.from({ length: 32 }, () => 0),
0x00,
0x00,
0x02,
0x00,
0x2f,
0x01,
0x00,
hi(extensions.length),
lo(extensions.length),
...extensions,
];
const handshakeLength = body.length;
const recordLength = handshakeLength + 4;
return Buffer.from([
0x16,
0x03,
0x01,
hi(recordLength),
lo(recordLength),
0x01,
0x00,
hi(handshakeLength),
lo(handshakeLength),
...body,
]);
}
test("ClientHello parser distinguishes TLS 1.2-only from TLS 1.3-capable clients", () => {
const tls12 = parseClientHelloVersions(clientHelloFixture([0x0303]));
if (tls12.kind !== "parsed") throw new Error(`unexpected parse result: ${tls12.kind}`);
assert.equal(tls12.offersTls13, false);
assert.deepEqual(tls12.supportedVersionLabels, ["TLSv1.2"]);
const tls13 = parseClientHelloVersions(clientHelloFixture([0x0304, 0x0303]));
if (tls13.kind !== "parsed") throw new Error(`unexpected parse result: ${tls13.kind}`);
assert.equal(tls13.offersTls13, true);
assert.deepEqual(tls13.supportedVersionLabels, ["TLSv1.3", "TLSv1.2"]);
});
test("profile config resolution normalizes defaults", () => {
const config = resolveEgressProfileConfig({
profile: "deny",
port: 0,
denyHosts: ["GitHub.com", "github.com.", ""],
denyMode: "blackhole",
slow: { totalBytes: 10, chunkBytes: 4, delayMs: 0, latencyMs: 1 },
blip: { route: "api/den", count: 2, fault: "reset" },
});
assert.equal(config.port, null);
assert.deepEqual(config.denyHosts, ["github.com"]);
assert.equal(config.denyMode, "blackhole");
assert.equal(config.slow.totalBytes, 10);
assert.equal(config.blip.route, "/api/den");
assert.equal(config.blip.count, 2);
assert.equal(config.blip.fault, "reset");
});
test("openssl argv construction includes CA, AIA, and fullchain prerequisites", () => {
const commands = opensslCertificateCommands({
dir: "/tmp/openwork-egress-test",
hostname: "localhost",
aiaUrl: "http://127.0.0.1:9000/__egress-lab/intermediate.der",
corporateIssuer: true,
});
const labels = commands.map((command) => command.label);
assert.deepEqual(labels, [
"root-key",
"root-csr",
"root-cert",
"intermediate-key",
"intermediate-csr",
"intermediate-cert",
"intermediate-der",
"leaf-key",
"leaf-csr",
"leaf-cert",
]);
assert.ok(commands.some((command) => command.args.includes("/CN=OpenWork Egress Lab Corporate Interception CA")));
assert.ok(commands.some((command) => command.args.includes("-extfile")));
const rootCert = commands.find((command) => command.label === "root-cert");
assert.ok(rootCert, "root-cert command must exist");
assert.ok(
rootCert.args.includes("-extfile"),
"root CA extensions must come from -extfile; openssl 1.1.1 ignores `req -x509 -addext`",
);
assert.ok(!rootCert.args.includes("-addext"), "root-cert must not depend on -addext");
});
test("openssl flavor probe returns a known value", async () => {
const flavor = await opensslFlavor();
assert.ok(["openssl", "libressl", "unknown"].includes(flavor));
});
test("deny-list seeding reads installer-critical hosts from the outbound manifest", () => {
const manifest = outboundManifestFromUnknown({
hosts: [
{ host: "github.com", kind: "fetched", components: ["installer"], requirement: "required-in-practice", blockedEffect: "installer dead" },
{ host: "release-assets.githubusercontent.com", kind: "redirect-target", components: ["installer"], requirement: "required-in-practice", blockedEffect: "download fails" },
{ host: "cdn.simpleicons.org", kind: "fetched", components: ["renderer"], requirement: "optional", blockedEffect: "icons missing" },
],
});
if (!manifest) throw new Error("manifest fixture did not parse");
assert.deepEqual(denyHostsFromOutboundManifest(manifest), ["github.com", "release-assets.githubusercontent.com"]);
});
test("blip schedule fires once, then stops", () => {
const schedule = createBlipSchedule({ route: "/v1/me", count: 1, fault: "401", status: 401, body: "proxy" });
const first = schedule.next("/v1/me");
const second = schedule.next("/v1/me");
assert.deepEqual(first, { kind: "status", status: 401, body: "proxy" });
assert.deepEqual(second, { kind: "pass" });
assert.equal(schedule.snapshot()[0]?.remaining, 0);
});
test("verdict matcher names injected faults and rejects vague output", () => {
assert.equal(matchVerdictExpectations("LIKELY TLS VERSION/HANDSHAKE FAULT: TLS 1.3 timed out while TLS 1.2 completed", "tls12-only").ok, true);
assert.equal(matchVerdictExpectations("endpoint_tls_handshake_timeout_tls12_comparison_failed: TLS 1.3 timed out and the runtime TLS 1.2 comparison also timed out", "tls12-only").ok, true);
assert.equal(matchVerdictExpectations("LIKELY MISSING INTERMEDIATE OR UNTRUSTED ROOT", "broken-chain").ok, true);
assert.equal(matchVerdictExpectations("LIKELY TLS INTERCEPTION: endpoint leaf is re-signed by Corporate CA", "intercept").ok, true);
assert.equal(matchVerdictExpectations("BLOCKED HOST / PROXY DENY: github.com is blocked", "deny").ok, true);
assert.deepEqual(matchVerdictExpectations("TypeError: fetch failed", ["tls12-only", "broken-chain"]), {
ok: false,
missing: ["tls12-only", "broken-chain"],
});
});
test("product diagnostics precondition skips clearly when Bun is unavailable", () => {
const reason = productDiagnosticsPrecondition({ PATH: "/definitely-no-bun-here" });
if (!reason) throw new Error("Expected a missing-Bun skip reason");
assert.ok(reason.includes("Bun is required"));
assert.ok(reason.includes("product-verdict egress proofs"));
});
test("generated egress lab CA certificates carry basicConstraints on every openssl build", async () => {
await using lab = await startEgressLab({ profile: "tls12-only" });
assert.ok(lab.rootPem, "lab must expose its root PEM");
const root = new X509Certificate(lab.rootPem);
// openssl 1.1.1 silently produced a non-CA root, which broke chain building
// only on runners shipping 1.1.1 (macos-14).
assert.equal(root.ca, true, `root must be a CA (subject: ${root.subject})`);
assert.ok(lab.intermediatePemPath, "lab must expose its intermediate path");
const intermediate = new X509Certificate(readFileSync(lab.intermediatePemPath, "utf8"));
assert.equal(intermediate.ca, true, `intermediate must be a CA (subject: ${intermediate.subject})`);
});
@@ -0,0 +1,198 @@
import assert from "node:assert/strict";
import { X509Certificate } from "node:crypto";
import { access, chmod, mkdtemp, readFile, rm, stat, symlink, writeFile } from "node:fs/promises";
import http from "node:http";
import https from "node:https";
import { tmpdir } from "node:os";
import path from "node:path";
import tls from "node:tls";
import { test } from "node:test";
import { stageTrustedEnterpriseTlsRoot, startEnterpriseTlsReverseEdge } from "../src/egress.ts";
function listen(server: http.Server): Promise<number> {
return new Promise((resolve, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", () => {
const address = server.address();
if (!address || typeof address === "string") return reject(new Error("server did not bind"));
resolve(address.port);
});
});
}
function close(server: http.Server): Promise<void> {
return new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
}
function request(url: string, options: { ca?: string; method?: string; path?: string; body?: string } = {}): Promise<string> {
return new Promise((resolve, reject) => {
const target = new URL(url);
const outgoing = https.request({
hostname: target.hostname,
port: target.port,
ca: options.ca,
method: options.method,
path: options.path ?? `${target.pathname}${target.search}`,
}, (response) => {
const chunks: Buffer[] = [];
response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
response.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
});
outgoing.on("error", reject);
outgoing.end(options.body);
});
}
function peerCertificatePem(url: string, ca: string): Promise<string> {
const target = new URL(url);
return new Promise((resolve, reject) => {
const socket = tls.connect({ host: target.hostname, port: Number(target.port), ca, servername: "localhost" }, () => {
const raw = socket.getPeerCertificate().raw;
socket.end();
if (!raw) reject(new Error("peer did not provide a certificate"));
else resolve(new X509Certificate(raw).toString());
});
socket.on("error", reject);
});
}
function manifest(rootPemPath: string): string {
return `${JSON.stringify({
pid: process.pid,
candidateUrl: "https://localhost:8443",
negativeUrl: "https://localhost:9443",
adminUrl: "http://127.0.0.1:8445",
rootPemPath,
})}\n`;
}
test("enterprise TLS privileged trust material is validated and staged", async (t) => {
const edge = await startEnterpriseTlsReverseEdge({ upstream: "http://127.0.0.1:1" });
const dir = await mkdtemp(path.join(tmpdir(), "openwork-enterprise-tls-validation-test-"));
const uid = typeof process.getuid === "function" ? process.getuid() : 0;
try {
await t.test("accepts an owned regular manifest and CA PEM", async () => {
const rootPemPath = path.join(dir, "happy-root.pem");
const manifestPath = path.join(dir, "happy-manifest.json");
await writeFile(rootPemPath, edge.rootPem, { mode: 0o600 });
await writeFile(manifestPath, manifest(rootPemPath), { mode: 0o600 });
const staged = await stageTrustedEnterpriseTlsRoot(manifestPath, [uid]);
try {
assert.deepEqual(staged.rootPem, Buffer.from(edge.rootPem));
assert.deepEqual(await readFile(staged.stagedRootPemPath), staged.rootPem);
assert.notEqual(staged.stagedRootPemPath, rootPemPath);
assert.equal((await stat(staged.stagedRootPemPath)).mode & 0o777, 0o600);
} finally {
await staged.cleanup();
}
});
await t.test("rejects a symlinked manifest", async () => {
const rootPemPath = path.join(dir, "manifest-link-root.pem");
const targetPath = path.join(dir, "manifest-target.json");
const manifestPath = path.join(dir, "manifest-link.json");
await writeFile(rootPemPath, edge.rootPem, { mode: 0o600 });
await writeFile(targetPath, manifest(rootPemPath), { mode: 0o600 });
await symlink(targetPath, manifestPath);
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid]), { name: "ENTERPRISE_TLS_MANIFEST_UNTRUSTED" });
});
await t.test("rejects a symlinked PEM", async () => {
const targetPath = path.join(dir, "pem-target.pem");
const rootPemPath = path.join(dir, "pem-link.pem");
const manifestPath = path.join(dir, "pem-link-manifest.json");
await writeFile(targetPath, edge.rootPem, { mode: 0o600 });
await symlink(targetPath, rootPemPath);
await writeFile(manifestPath, manifest(rootPemPath), { mode: 0o600 });
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid]), { name: "ENTERPRISE_TLS_ROOT_PEM_UNTRUSTED" });
});
await t.test("rejects a world-writable PEM", async () => {
const rootPemPath = path.join(dir, "writable-root.pem");
const manifestPath = path.join(dir, "writable-manifest.json");
await writeFile(rootPemPath, edge.rootPem, { mode: 0o600 });
await chmod(rootPemPath, 0o666);
await writeFile(manifestPath, manifest(rootPemPath), { mode: 0o600 });
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid]), { name: "ENTERPRISE_TLS_ROOT_PEM_UNTRUSTED" });
});
await t.test("rejects non-CA and unparseable PEM files", async () => {
const manifestPath = path.join(dir, "invalid-manifest.json");
const rootPemPath = path.join(dir, "invalid-root.pem");
await writeFile(manifestPath, manifest(rootPemPath), { mode: 0o600 });
await writeFile(rootPemPath, await peerCertificatePem(edge.candidateUrl, edge.rootPem), { mode: 0o600 });
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid]), /certificate is not a CA/u);
await writeFile(rootPemPath, "not a certificate\n", { mode: 0o600 });
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid]), { name: "ENTERPRISE_TLS_ROOT_PEM_UNTRUSTED" });
});
await t.test("rejects a relative rootPemPath", async () => {
const manifestPath = path.join(dir, "relative-manifest.json");
await writeFile(manifestPath, manifest("relative-root.pem"), { mode: 0o600 });
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid]), /rootPemPath must be absolute/u);
});
await t.test("rejects an owner outside the explicit allowed uid set", async () => {
const rootPemPath = path.join(dir, "owner-root.pem");
const manifestPath = path.join(dir, "owner-manifest.json");
await writeFile(rootPemPath, edge.rootPem, { mode: 0o600 });
await writeFile(manifestPath, manifest(rootPemPath), { mode: 0o600 });
await assert.rejects(stageTrustedEnterpriseTlsRoot(manifestPath, [uid + 1]), /owner uid .* is not allowed/u);
});
} finally {
await edge.stop();
await rm(dir, { recursive: true, force: true });
}
});
test("enterprise TLS edge pins its upstream and exposes selective trust", async () => {
const upstreamRequests: { method: string; url: string; body: string }[] = [];
const upstream = http.createServer(async (incoming, response) => {
const chunks: Buffer[] = [];
for await (const chunk of incoming) chunks.push(Buffer.from(chunk));
upstreamRequests.push({ method: incoming.method ?? "GET", url: incoming.url ?? "/", body: Buffer.concat(chunks).toString("utf8") });
response.end("from-pinned-upstream");
});
const attackerHits: string[] = [];
const attacker = http.createServer((incoming, response) => {
attackerHits.push(incoming.url ?? "/");
response.end("attacker");
});
const upstreamPort = await listen(upstream);
const attackerPort = await listen(attacker);
const edge = await startEnterpriseTlsReverseEdge({ upstream: `http://127.0.0.1:${upstreamPort}` });
const rootPath = edge.rootPemPath;
try {
await assert.rejects(request(`${edge.candidateUrl}/default-trust`));
assert.equal(await request(`${edge.candidateUrl}/v1/me?full=1`, { ca: edge.rootPem, method: "POST", body: "payload" }), "from-pinned-upstream");
await assert.rejects(request(`${edge.negativeUrl}/negative`, { ca: edge.rootPem }));
const absoluteTarget = `http://127.0.0.1:${attackerPort}/stolen?token=yes`;
assert.equal(await request(edge.candidateUrl, { ca: edge.rootPem, path: absoluteTarget }), "from-pinned-upstream");
assert.deepEqual(attackerHits, []);
assert.deepEqual(upstreamRequests, [
{ method: "POST", url: "/v1/me?full=1", body: "payload" },
{ method: "GET", url: "/stolen?token=yes", body: "" },
]);
assert.deepEqual(edge.requests.map(({ endpoint, method, path, body }) => ({ endpoint, method, path, body })), [
{ endpoint: "trusted-candidate", method: "POST", path: "/v1/me?full=1", body: "payload" },
{ endpoint: "trusted-candidate", method: "GET", path: "/stolen?token=yes", body: "" },
]);
assert.equal(edge.linuxTrust.restartApplication, true);
assert.equal(edge.linuxTrust.install()[1]?.file, "/usr/sbin/update-ca-certificates");
assert.equal(edge.linuxTrust.prerequisiteFailures.root, "ENTERPRISE_TLS_LINUX_ROOT_REQUIRED");
const prerequisites = await edge.linuxTrust.checkPrerequisites();
if (!prerequisites.ok) {
assert.ok([
"ENTERPRISE_TLS_LINUX_ROOT_REQUIRED",
"ENTERPRISE_TLS_UPDATE_CA_CERTIFICATES_REQUIRED",
].includes(prerequisites.failure));
}
} finally {
await edge.stop();
await Promise.all([close(upstream), close(attacker)]);
}
await assert.rejects(access(rootPath));
await assert.rejects(request(edge.candidateUrl, { ca: edge.rootPem }));
});
+124
View File
@@ -0,0 +1,124 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
buildBlockedUserResponse,
buildOidcClaims,
buildRs256SigningArgv,
buildWrongDomainEmail,
matchSsoExpectation,
normalizeCertificateMaterial,
normalizeDomain,
normalizeMockIdpConfig,
startMockIdpLab,
subjectWithKnobs,
validateSsoConfiguration,
} from "../src/idp.ts";
test("mock IdP config normalization trims issuer, domain, and credentials", () => {
const config = normalizeMockIdpConfig({
issuer: " https://idp.example.test/ ",
domain: " @Acme.TEST. ",
clientId: " client-one ",
clientSecret: " secret-one ",
});
assert.equal(config.issuer, "https://idp.example.test");
assert.equal(config.domain, "acme.test");
assert.equal(config.clientId, "client-one");
assert.equal(config.clientSecret, "secret-one");
assert.equal(config.defaultSubject.email, "sso.user@acme.test");
});
test("certificate normalizer names the trailing-newline paste bug", () => {
const cert = "-----BEGIN CERTIFICATE-----\nabc\n-----END CERTIFICATE-----\n";
const normalized = normalizeCertificateMaterial(cert);
const validation = validateSsoConfiguration({ configuredDomain: "acme.test", cert, subjectEmail: "maya@acme.test" });
const match = matchSsoExpectation(validation, { code: "sso_cert_trailing_newline", includes: ["trailing newline", "certificate"] });
assert.equal(normalized.hadTrailingNewline, true);
assert.equal(normalized.value.endsWith("\n"), false);
assert.equal(validation.ok, false);
assert.equal(match.passed, true);
});
test("domain mismatch normalizer names IdP email domains that do not match the org", () => {
const wrongEmail = buildWrongDomainEmail("maya@acme.test", "acme.test");
const validation = validateSsoConfiguration({ configuredDomain: "ACME.test", subjectEmail: wrongEmail });
const match = matchSsoExpectation(validation, { code: "sso_domain_mismatch", includes: ["wrong-acme.test", "acme.test"] });
assert.equal(wrongEmail, "maya@wrong-acme.test");
assert.equal(normalizeDomain(" @ACME.test. "), "acme.test");
assert.equal(validation.normalizedDomain, "acme.test");
assert.equal(match.passed, true);
});
test("claim builder supports present, absent, and unexpected group claim shapes", () => {
const baseConfig = normalizeMockIdpConfig({ domain: "acme.test" });
const subject = subjectWithKnobs(baseConfig, { email: "dev@acme.test", name: "Dev User" });
const present = buildOidcClaims({ issuer: baseConfig.issuer, clientId: baseConfig.clientId, subject, knobs: baseConfig.knobs });
const absentConfig = normalizeMockIdpConfig({ knobs: { groupClaims: "absent" } });
const absent = buildOidcClaims({ issuer: absentConfig.issuer, clientId: absentConfig.clientId, subject, knobs: absentConfig.knobs });
const oddConfig = normalizeMockIdpConfig({ knobs: { groupClaims: "unexpected-shape" } });
const odd = buildOidcClaims({ issuer: oddConfig.issuer, clientId: oddConfig.clientId, subject, knobs: oddConfig.knobs });
assert.deepEqual(present.groups, ["Engineering", "OpenWork Lab"]);
assert.equal("groups" in absent, false);
assert.deepEqual(odd.groups, { primary: "Engineering", all: ["Engineering", "OpenWork Lab"] });
});
test("email mismatch and guest-user knobs shape SSO subjects", () => {
const mismatchConfig = normalizeMockIdpConfig({ knobs: { emailMismatch: "other@acme.test" } });
const guestConfig = normalizeMockIdpConfig({ knobs: { guestUser: true } });
assert.equal(subjectWithKnobs(mismatchConfig, { email: "invited@acme.test" }).email, "other@acme.test");
assert.equal(subjectWithKnobs(guestConfig, { email: "guest@external.test" }).sub, "guest:guest@external.test");
});
test("RS256 signing argv documents the dependency-free node:crypto path", () => {
assert.deepEqual(buildRs256SigningArgv({ keyId: "kid-one", payload: "abc" }), [
"node:crypto",
"createSign",
"RSA-SHA256",
"--kid",
"kid-one",
"--payload-bytes",
"3",
]);
});
test("blocked-user response uses the Entra-style policy wording", () => {
const response = buildBlockedUserResponse({ email: "blocked@acme.test" });
assert.equal(response.status, 403);
assert.equal(response.error, "access_denied");
assert.match(response.errorDescription, /administrator has configured the application to block users/);
assert.match(response.message, /IdP administrator/);
assert.match(response.html, /OpenWork Mock IdP policy/);
});
test("mock IdP escapes request-derived blocked-user HTML", async () => {
const loginHint = "blocked@acme.test<script>alert(1)</script>";
await using lab = await startMockIdpLab({ knobs: { blockedUser: loginHint } });
const url = new URL(lab.authorizationEndpoint);
url.searchParams.set("client_id", lab.config.clientId);
url.searchParams.set("redirect_uri", "http://127.0.0.1/callback");
url.searchParams.set("login_hint", loginHint);
const response = await fetch(url);
const body = await response.text();
assert.equal(response.status, 403);
// Plain substring checks: stricter than a tag regex (`<script` also catches
// `<script src=...`) and they cannot be mistaken for a tag-filtering sanitizer.
assert.ok(!body.includes("<script"), `escaped body must not contain raw markup: ${body}`);
assert.ok(body.includes("&lt;script&gt;"), `escaped body must contain the escaped payload: ${body}`);
});
test("expectation matcher fails with actionable detail when the named error is missing", () => {
const validation = validateSsoConfiguration({ configuredDomain: "acme.test", subjectEmail: "maya@acme.test" });
const match = matchSsoExpectation(validation, { code: "sso_domain_mismatch" });
assert.equal(match.passed, false);
assert.deepEqual(match.actualCodes, []);
assert.match(match.detail, /Expected sso_domain_mismatch/);
});
@@ -0,0 +1,338 @@
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { createServer } from "node:http";
import type { Server } from "node:http";
import type { AddressInfo } from "node:net";
import test from "node:test";
import { startMockGoogle } from "../src/mock-google.ts";
import type { MockGoogleHandle } from "../src/mock-google.ts";
interface CallbackLab {
url: string;
callbacks: URL[];
stop(): Promise<void>;
[Symbol.asyncDispose](): Promise<void>;
}
interface OAuthTokens {
accessToken: string;
idToken: string;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function isAddressInfo(value: ReturnType<Server["address"]>): value is AddressInfo {
return typeof value === "object"
&& value !== null
&& typeof value.address === "string"
&& typeof value.family === "string"
&& typeof value.port === "number";
}
function close(server: Server): Promise<void> {
return new Promise((resolve, reject) => {
server.close((error) => {
if (error) {
reject(error);
return;
}
resolve();
});
server.closeIdleConnections();
});
}
async function startCallbackLab(): Promise<CallbackLab> {
const callbacks: URL[] = [];
const server = createServer((request, response) => {
callbacks.push(new URL(request.url ?? "/", "http://127.0.0.1"));
response.writeHead(200, { "content-type": "text/plain" });
response.end("OAuth callback served");
});
const address = await new Promise<AddressInfo>((resolve, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", () => {
server.off("error", reject);
const value = server.address();
if (isAddressInfo(value)) {
resolve(value);
return;
}
reject(new Error("Callback lab did not expose a TCP port."));
});
});
let stopped = false;
const stop = async (): Promise<void> => {
if (stopped) return;
stopped = true;
await close(server);
};
return {
url: `http://127.0.0.1:${address.port}/callback`,
callbacks,
stop,
[Symbol.asyncDispose]: stop,
};
}
function tokenFingerprint(accessToken: string): string {
return createHash("sha256").update(accessToken).digest("hex").slice(0, 12);
}
async function authorize(
google: MockGoogleHandle,
callback: CallbackLab,
email: string,
clientId: string,
): Promise<OAuthTokens> {
const verifier = `verifier-${clientId}`;
const challenge = createHash("sha256").update(verifier).digest("base64url");
const authorizeUrl = new URL(google.authorizeUrl);
authorizeUrl.searchParams.set("client_id", clientId);
authorizeUrl.searchParams.set("redirect_uri", callback.url);
authorizeUrl.searchParams.set("response_type", "code");
authorizeUrl.searchParams.set("scope", "openid email profile https://www.googleapis.com/auth/gmail.compose");
authorizeUrl.searchParams.set("state", `state-${clientId}`);
authorizeUrl.searchParams.set("prompt", "consent select_account");
authorizeUrl.searchParams.set("code_challenge", challenge);
authorizeUrl.searchParams.set("code_challenge_method", "S256");
const since = new Date().toISOString();
const callbackCount = callback.callbacks.length;
const chooser = await fetch(authorizeUrl, { redirect: "manual" });
const chooserHtml = await chooser.text();
assert.equal(chooser.status, 200);
assert.match(chooserHtml, /Choose an account/);
assert.match(chooserHtml, new RegExp(`data-account-email="${email.replaceAll(".", "\\.")}"`));
const observed = await google.authorizeRequestSince(since, { timeoutMs: 2_000 });
assert.equal(observed.params.get("prompt"), "consent select_account");
await google.chooseAccount(email, { timeoutMs: 2_000 });
assert.equal(callback.callbacks.length, callbackCount + 1, "chooseAccount must wait until the callback server receives the request");
const callbackUrl = callback.callbacks.at(-1);
const code = callbackUrl?.searchParams.get("code");
assert.ok(code, "callback must carry an authorization code");
const response = await fetch(google.tokenUrl, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "authorization_code",
code,
code_verifier: verifier,
client_id: clientId,
client_secret: `secret-${clientId}`,
redirect_uri: callback.url,
}),
});
const body: unknown = await response.json();
assert.equal(response.status, 200);
assert.ok(isRecord(body));
if (typeof body.access_token !== "string" || typeof body.id_token !== "string") {
throw new Error(`Token response omitted access_token or id_token: ${JSON.stringify(body)}`);
}
return { accessToken: body.access_token, idToken: body.id_token };
}
function idTokenPayload(idToken: string): Record<string, unknown> {
const payload = idToken.split(".")[1];
assert.ok(payload, "id_token must have a JWT payload");
const parsed: unknown = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
assert.ok(isRecord(parsed));
return parsed;
}
async function userinfo(google: MockGoogleHandle, accessToken: string): Promise<Record<string, unknown>> {
const response = await fetch(google.userinfoUrl, { headers: { authorization: `Bearer ${accessToken}` } });
const body: unknown = await response.json();
assert.equal(response.status, 200);
assert.ok(isRecord(body));
return body;
}
async function submitDraft(
google: MockGoogleHandle,
accessToken: string,
message: string,
threadId?: string,
): Promise<void> {
const requestMessage: { raw: string; threadId?: string } = {
raw: Buffer.from(message, "utf8").toString("base64url"),
};
if (threadId) requestMessage.threadId = threadId;
const response = await fetch(`${google.apiUrl}/gmail/v1/users/me/drafts`, {
method: "POST",
headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
body: JSON.stringify({ message: requestMessage }),
});
assert.equal(response.status, 200);
}
async function createDraft(
google: MockGoogleHandle,
accessToken: string,
to: string,
body: string,
threadId?: string,
): Promise<void> {
const message = [
`To: ${to}`,
"Subject: Fixture witness",
"MIME-Version: 1.0",
'Content-Type: text/plain; charset="UTF-8"',
"Content-Transfer-Encoding: base64",
"",
Buffer.from(body, "utf8").toString("base64"),
].join("\r\n");
await submitDraft(google, accessToken, message, threadId);
}
test("mock Google issues independent account identities and credential fingerprints", async () => {
const accountA = "jordan@acme.test";
const accountB = "jordan@acmelabs.test";
await using google = await startMockGoogle({ accounts: [accountA, accountB], port: 0, autoApprove: false });
await using callback = await startCallbackLab();
const tokensA = await authorize(google, callback, accountA, "client-a");
const tokensB = await authorize(google, callback, accountB, "client-b");
assert.notEqual(tokenFingerprint(tokensA.accessToken), tokenFingerprint(tokensB.accessToken));
assert.equal(idTokenPayload(tokensA.idToken).email, accountA);
assert.equal(idTokenPayload(tokensB.idToken).email, accountB);
assert.equal((await userinfo(google, tokensA.accessToken)).email, accountA);
assert.equal((await userinfo(google, tokensB.accessToken)).email, accountB);
await createDraft(google, tokensA.accessToken, "archive@acme.test", "Account A", "thread-a");
await createDraft(google, tokensB.accessToken, "archive@acmelabs.test", "Account B", "thread-b");
const draftsA = await google.draftsFor(accountA);
const draftsB = await google.draftsFor(accountB);
assert.equal(draftsA[0]?.tokenId, tokenFingerprint(tokensA.accessToken));
assert.equal(draftsB[0]?.tokenId, tokenFingerprint(tokensB.accessToken));
assert.notEqual(draftsA[0]?.tokenId, draftsB[0]?.tokenId);
});
test("mock Google attributes drafts to one mailbox and returns an empty mailbox promptly", async () => {
const accountA = "jordan@acme.test";
const accountB = "jordan@acmelabs.test";
await using google = await startMockGoogle({ accounts: [accountA, accountB], port: 0, autoApprove: false });
await using callback = await startCallbackLab();
const tokensA = await authorize(google, callback, accountA, "client-a");
const since = new Date().toISOString();
await createDraft(google, tokensA.accessToken, "supplier@parts.test", "Mailbox isolation witness", "thread-one");
const draftsA = await google.draftsFor(accountA, { since, atLeast: 1, timeoutMs: 2_000 });
const startedAt = Date.now();
const draftsB = await google.draftsFor(accountB, { since, timeoutMs: 5_000 });
const elapsedMs = Date.now() - startedAt;
assert.deepEqual(draftsB, []);
assert.ok(elapsedMs < 1_000, `empty mailbox read blocked for ${elapsedMs}ms`);
assert.equal(draftsA.length, 1);
assert.deepEqual(draftsA[0], {
to: "supplier@parts.test",
body: "Mailbox isolation witness",
threadId: "thread-one",
tokenId: tokenFingerprint(tokensA.accessToken),
at: draftsA[0]?.at,
});
});
test("mock Google decodes text/plain nested inside mixed and alternative MIME", async () => {
const account = "jordan@acme.test";
await using google = await startMockGoogle({ accounts: [account], port: 0, autoApprove: false });
await using callback = await startCallbackLab();
const tokens = await authorize(google, callback, account, "client-nested-mime");
const plainBody = "Nested multipart body marker";
const mixedBoundary = "fixture-mixed";
const alternativeBoundary = "fixture-alternative";
const message = [
"To: archive@acme.test",
"Subject: Nested MIME witness",
"MIME-Version: 1.0",
`Content-Type: multipart/mixed; boundary="${mixedBoundary}"`,
"",
`--${mixedBoundary}`,
`Content-Type: multipart/alternative; boundary="${alternativeBoundary}"`,
"",
`--${alternativeBoundary}`,
'Content-Type: text/plain; charset="UTF-8"',
"Content-Transfer-Encoding: base64",
"",
Buffer.from(plainBody, "utf8").toString("base64"),
`--${alternativeBoundary}`,
'Content-Type: text/html; charset="UTF-8"',
"Content-Transfer-Encoding: base64",
"",
Buffer.from(`<div>${plainBody}</div>`, "utf8").toString("base64"),
`--${alternativeBoundary}--`,
`--${mixedBoundary}`,
'Content-Type: application/octet-stream; name="witness.bin"',
'Content-Disposition: attachment; filename="witness.bin"',
"Content-Transfer-Encoding: base64",
"",
Buffer.from("attachment bytes", "utf8").toString("base64"),
`--${mixedBoundary}--`,
"",
].join("\r\n");
await submitDraft(google, tokens.accessToken, message);
const drafts = await google.draftsFor(account);
assert.equal(drafts[0]?.body, plainBody);
});
test("mock Google witnesses exact Gmail attachment and Drive upload bytes", async () => {
const account = "jordan@acme.test";
const fixture = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x00, 0xff, 0x80, 0x13, 0x0a]);
await using google = await startMockGoogle({ accounts: [account], port: 0, autoApprove: false });
await using callback = await startCallbackLab();
const tokens = await authorize(google, callback, account, "client-binary-witness");
const mixedBoundary = "fixture-mixed-binary";
const message = [
"To: archive@acme.test",
"Subject: Binary witness",
"MIME-Version: 1.0",
`Content-Type: multipart/mixed; boundary="${mixedBoundary}"`,
"",
`--${mixedBoundary}`,
'Content-Type: text/plain; charset="UTF-8"',
"Content-Transfer-Encoding: base64",
"",
Buffer.from("Binary body", "utf8").toString("base64"),
`--${mixedBoundary}`,
'Content-Type: image/png; name="witness.png"',
'Content-Disposition: attachment; filename="witness.png"',
"Content-Transfer-Encoding: base64",
"",
fixture.toString("base64"),
`--${mixedBoundary}--`,
"",
].join("\r\n");
await submitDraft(google, tokens.accessToken, message);
const drafts = await google.draftsFor(account, { atLeast: 1, timeoutMs: 2_000 });
assert.equal(drafts[0]?.attachments?.[0]?.filename, "witness.png");
assert.equal(drafts[0]?.attachments?.[0]?.mimeType, "image/png");
assert.deepEqual(drafts[0]?.attachments?.[0]?.content, fixture);
const driveBoundary = "fixture-drive-binary";
const metadata = Buffer.from(`--${driveBoundary}\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"name":"witness.png"}\r\n`, "utf8");
const contentHeader = Buffer.from(`--${driveBoundary}\r\nContent-Type: image/png\r\n\r\n`, "utf8");
const footer = Buffer.from(`\r\n--${driveBoundary}--\r\n`, "utf8");
const uploadBody = Buffer.concat([metadata, contentHeader, fixture, footer]);
const uploadBytes = new Uint8Array(uploadBody.byteLength);
uploadBytes.set(uploadBody);
const response = await fetch(`${google.apiUrl}/upload/drive/v3/files?uploadType=multipart`, {
method: "POST",
headers: {
authorization: `Bearer ${tokens.accessToken}`,
"content-type": `multipart/related; boundary=${driveBoundary}`,
},
body: uploadBytes,
});
assert.equal(response.status, 200);
const uploads = await google.driveUploadsFor(account, { atLeast: 1, timeoutMs: 2_000 });
assert.equal(uploads[0]?.filename, "witness.png");
assert.equal(uploads[0]?.mimeType, "image/png");
assert.deepEqual(uploads[0]?.content, fixture);
});
+95
View File
@@ -0,0 +1,95 @@
import assert from "node:assert/strict";
import test from "node:test";
import { allocateFreePort } from "@openwork/cdp";
import { startMockMcp } from "../src/mock-mcp.ts";
test("records an unauthenticated initialize attempt as a handshake", async () => {
await using mock = await startMockMcp({ port: await allocateFreePort() });
const startedAt = new Date().toISOString();
const response = await fetch(mock.mcpUrl, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: "2025-06-18",
capabilities: {},
clientInfo: { name: "mock-handshake-test", version: "1.0.0" },
},
}),
});
assert.equal(response.status, 401);
const handshakes = await mock.handshakes({ sinceIso: startedAt });
assert.equal(handshakes.length, 1);
assert.equal(handshakes[0]?.method, "POST");
assert.equal(handshakes[0]?.path, "/mcp");
});
function completionBody(marker: string, completedTools: number): Record<string, unknown> {
return {
model: "mock-agent-workload-model",
stream: true,
tools: [
{ type: "function", function: { name: "write", parameters: { type: "object" } } },
{ type: "function", function: { name: "read", parameters: { type: "object" } } },
],
messages: [
{ role: "user", content: `run ${marker}` },
...Array.from({ length: completedTools }, (_, index) => ({
role: "tool",
tool_call_id: `call-${index}`,
content: `tool result ${index}`,
})),
],
};
}
test("scripts and records deterministic OpenAI-compatible agent tool rounds", async () => {
const marker = "agent-workload-unit-marker";
await using mock = await startMockMcp({
port: await allocateFreePort(),
agentWorkloads: [{
promptMarker: marker,
finalReply: "unit workload complete",
steps: [
{ tool: "write", arguments: { filePath: "/tmp/unit.txt", content: marker } },
{ tool: "read", arguments: { filePath: "/tmp/unit.txt" } },
],
}],
});
const startedAt = new Date().toISOString();
const first = await fetch(`${mock.url}/v1/chat/completions`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(completionBody(marker, 0)),
});
const firstText = await first.text();
assert.equal(first.status, 200);
assert.match(firstText, /"name":"write"/);
assert.match(firstText, /unit\.txt/);
const second = await fetch(`${mock.url}/v1/chat/completions`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(completionBody(marker, 1)),
});
assert.match(await second.text(), /"name":"read"/);
const final = await fetch(`${mock.url}/v1/chat/completions`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(completionBody(marker, 2)),
});
assert.match(await final.text(), /unit workload complete/);
const requests = await mock.agentRequests({ promptMarker: marker, sinceIso: startedAt, atLeast: 3, timeoutMs: 5_000 });
assert.deepEqual(requests.map((request) => request.kind), ["tool", "tool", "final"]);
assert.deepEqual(requests.map((request) => request.completedTools), [0, 1, 2]);
assert.deepEqual(requests.map((request) => request.matchedMarkers), [[marker], [marker], [marker]]);
});