Files
tyx_AI_xhs/tests/api/wp0-03-browser-gate.test.ts
T

258 lines
8.4 KiB
TypeScript

import { mkdirSync, writeFileSync } from "node:fs";
import { resolve } from "node:path";
import { afterAll, describe, expect, it, vi } from "vitest";
import { createApp } from "../../apps/api/src/app.js";
import {
browserSupportFixture,
testBrowserSupportRelease,
} from "../helpers/browser-support-fixture.js";
const supportedEdge = browserSupportFixture({
brand: "Microsoft Edge",
fullVersion: "150.0.4078.99",
});
const rejectedIdentityCases = [
{
expectedReason: "platform_unsupported",
fixture: browserSupportFixture({
brand: "Microsoft Edge",
fullVersion: "150.0.4078.99",
platform: "macOS",
}),
name: "non-Windows platform",
},
{
expectedReason: "brand_unsupported",
fixture: browserSupportFixture({ brand: "Opera", fullVersion: "150.0.0.0" }),
name: "other brand",
},
{
expectedReason: "version_unsupported",
fixture: browserSupportFixture({ brand: "Microsoft Edge", fullVersion: "149.0.0.0" }),
name: "wrong major",
},
] as const;
const unavailableIdentityCases = [
{ mutate: () => ({ headers: { host: "127.0.0.1:43121" }, payload: supportedEdge.body }), name: "missing UA-CH" },
{
mutate: () => ({
headers: { ...supportedEdge.headers, "sec-ch-ua-full-version-list": '"broken"' },
payload: supportedEdge.body,
}),
name: "unparseable UA-CH",
},
{
mutate: () => ({
headers: supportedEdge.headers,
payload: { ...supportedEdge.body, platform: "macOS" },
}),
name: "conflicting UA-CH",
},
] as const;
function supportCookie(response: { headers: Record<string, string | string[] | undefined> }) {
const header = response.headers["set-cookie"];
const value = Array.isArray(header) ? header[0] : header;
return value?.split(";", 1)[0];
}
afterAll(async () => {
const evidenceDirectory = process.env.DADA_EVIDENCE_DIR_BRW_BLOCKED;
if (!evidenceDirectory) return;
const responses = [];
const app = await createApp({ browserSupportRelease: testBrowserSupportRelease } as never);
for (const testCase of rejectedIdentityCases) {
const response = await app.inject({
headers: testCase.fixture.headers,
method: "POST",
payload: testCase.fixture.body,
url: "/api/v1/support/check",
});
responses.push({ body: response.json(), name: testCase.name, status_code: response.statusCode });
}
for (const testCase of unavailableIdentityCases) {
const input = testCase.mutate();
const response = await app.inject({
headers: input.headers,
method: "POST",
payload: input.payload,
url: "/api/v1/support/check",
});
responses.push({ body: response.json(), name: testCase.name, status_code: response.statusCode });
}
const bootstrap = vi.fn(() => ({
app_version: "0.0.0",
dependencies: [],
model_summary: {
config_set_version: null,
configured_default_model_id: null,
recommended_model_id: null,
runtime_availability_version: null,
},
public_features: [],
}));
const rawApp = await createApp({ bootstrap, browserSupportRelease: testBrowserSupportRelease } as never);
const rawResponse = await rawApp.inject({
headers: { host: "127.0.0.1:43121", "user-agent": "raw-client" },
method: "GET",
url: "/api/v1/bootstrap",
});
responses.push({ body: rawResponse.json(), name: "raw product API", status_code: rawResponse.statusCode });
await rawApp.close();
await app.close();
if (responses.some(({ status_code }) => status_code !== 426) || bootstrap.mock.calls.length !== 0) {
throw new Error("Hard-block evidence did not preserve the 426 zero-business-access boundary.");
}
mkdirSync(evidenceDirectory, { recursive: true });
writeFileSync(
resolve(evidenceDirectory, "response.json"),
`${JSON.stringify({ cases: responses, status: "passed" }, null, 2)}\n`,
);
writeFileSync(
resolve(evidenceDirectory, "db-access.json"),
`${JSON.stringify({ business_provider_calls: 0, reads: 0, status: "passed", writes: 0 }, null, 2)}\n`,
);
writeFileSync(
resolve(evidenceDirectory, "external-calls.json"),
`${JSON.stringify({ configured_clients: [], observed_calls: 0, status: "passed" }, null, 2)}\n`,
);
});
describe("TDD-WP0-BRW-001 supported browser contract", () => {
it("cross-checks UA-CH and issues only a short-lived signed support cookie", async () => {
const app = await createApp({ browserSupportRelease: testBrowserSupportRelease } as never);
const checked = await app.inject({
headers: supportedEdge.headers,
method: "POST",
payload: supportedEdge.body,
url: "/api/v1/support/check",
});
expect(checked.statusCode).toBe(200);
expect(checked.json()).toEqual({
app_version: "1.2.3-test",
browser: { brand: "Microsoft Edge", major: 150 },
status: "supported",
supported_browsers: [
{ brand: "Google Chrome", major: 150 },
{ brand: "Microsoft Edge", major: 150 },
],
});
expect(checked.headers["set-cookie"]).toContain("dada_browser_support=");
expect(checked.headers["set-cookie"]).toContain("HttpOnly");
expect(checked.headers["set-cookie"]).toContain("SameSite=Strict");
expect(checked.headers["set-cookie"]).toContain("Max-Age=86400");
const cookie = supportCookie(checked);
expect(cookie).toBeDefined();
const product = await app.inject({
headers: {
cookie,
host: "127.0.0.1:43121",
"sec-ch-ua": supportedEdge.headers["sec-ch-ua"],
},
method: "GET",
url: "/api/v1/bootstrap",
});
expect(product.statusCode).toBe(200);
await app.close();
const restarted = await createApp({ browserSupportRelease: testBrowserSupportRelease } as never);
const staleCookie = await restarted.inject({
headers: {
cookie,
host: "127.0.0.1:43121",
"sec-ch-ua": supportedEdge.headers["sec-ch-ua"],
},
method: "GET",
url: "/api/v1/bootstrap",
});
expect(staleCookie.statusCode).toBe(426);
await restarted.close();
});
});
describe("TDD-WP0-BRW-002 hard block", () => {
it.each(rejectedIdentityCases)("returns 426 for $name", async ({ expectedReason, fixture }) => {
const app = await createApp({ browserSupportRelease: testBrowserSupportRelease } as never);
const response = await app.inject({
headers: fixture.headers,
method: "POST",
payload: fixture.body,
url: "/api/v1/support/check",
});
expect(response.statusCode).toBe(426);
expect(response.json()).toMatchObject({
error: {
code: "BROWSER_UNSUPPORTED",
details: {
reason: expectedReason,
supported_browsers: [
{ brand: "Google Chrome", major: 150 },
{ brand: "Microsoft Edge", major: 150 },
],
},
message_key: "browser.unsupported",
},
});
expect(response.body).not.toContain("Opera");
await app.close();
});
it.each(unavailableIdentityCases)("fails closed for $name", async ({ mutate }) => {
const app = await createApp({ browserSupportRelease: testBrowserSupportRelease } as never);
const input = mutate();
const response = await app.inject({
headers: input.headers,
method: "POST",
payload: input.payload,
url: "/api/v1/support/check",
});
expect(response.statusCode).toBe(426);
expect(response.json()).toMatchObject({
error: { details: { reason: "identity_unavailable" } },
});
await app.close();
});
it("blocks raw product API access before any business provider runs", async () => {
const bootstrap = vi.fn(() => ({
app_version: "0.0.0",
dependencies: [],
model_summary: {
config_set_version: null,
configured_default_model_id: null,
recommended_model_id: null,
runtime_availability_version: null,
},
public_features: [],
}));
const app = await createApp({
bootstrap,
browserSupportRelease: testBrowserSupportRelease,
} as never);
const response = await app.inject({
headers: { host: "127.0.0.1:43121", "user-agent": "Mozilla/5.0 Chrome/150" },
method: "GET",
url: "/api/v1/bootstrap",
});
expect(response.statusCode).toBe(426);
expect(response.json()).toMatchObject({
error: {
code: "BROWSER_UNSUPPORTED",
details: { reason: "identity_unavailable" },
},
});
expect(bootstrap).not.toHaveBeenCalled();
await app.close();
});
});