feat: verify frontend supply chain

This commit is contained in:
donghyeon-ka
2026-07-26 17:37:51 +09:00
parent a64708f3de
commit 8b4f875c1c
35 changed files with 8910 additions and 141 deletions
-35
View File
@@ -1,6 +1,4 @@
import { expect, test } from "../support/browser/strict-browser-test.js";
import { successEnvelope } from "../mocks/contracts/envelopes.js";
import { ROUTE_REGISTRY } from "../../src/features/installed-feature-contracts.js";
test("boots the public app shell", async ({ page }) => {
await page.goto("/");
@@ -26,39 +24,6 @@ test("navigates to a registry-backed example without a page reload", async ({
).toBeFocused();
});
test("opens the protected integration route through the local demo seam", async ({
page,
}) => {
const protectedRoute = Object.values(ROUTE_REGISTRY).find(
(definition) => definition.access === "integration-defined",
);
if (!protectedRoute) throw new Error("An integration route is required");
await page.route(
"http://localhost:8080/api/reference-resources?*",
(route) =>
route.fulfill({
json: successEnvelope([
{
id: "browser-reference",
name: "Browser reference",
createdAt: "2026-07-26T00:00:00.000Z",
},
]),
}),
);
await page.goto(protectedRoute.path);
await expect(
page.getByRole("heading", { name: "세션이 필요합니다." }),
).toBeVisible();
await page.getByRole("button", { name: "로그인 시작" }).click();
await expect(
page.getByRole("heading", { name: protectedRoute.title }),
).toBeVisible();
await expect(page.getByText("인증됨")).toBeVisible();
});
test("provides an escape-dismissible mobile navigation", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto("/");
+36
View File
@@ -0,0 +1,36 @@
import { expect, test } from "../support/browser/strict-browser-test.js";
import { successEnvelope } from "../mocks/contracts/envelopes.js";
import { ROUTE_REGISTRY } from "../../src/features/installed-feature-contracts.js";
test("opens the protected integration route through the local demo seam", async ({
page,
}) => {
const protectedRoute = Object.values(ROUTE_REGISTRY).find(
(definition) => definition.access === "integration-defined",
);
if (!protectedRoute) throw new Error("An integration route is required");
await page.route(
"http://localhost:8080/api/reference-resources?*",
(route) =>
route.fulfill({
json: successEnvelope([
{
id: "browser-reference",
name: "Browser reference",
createdAt: "2026-07-26T00:00:00.000Z",
},
]),
}),
);
await page.goto(protectedRoute.path);
await expect(
page.getByRole("heading", { name: "세션이 필요합니다." }),
).toBeVisible();
await page.getByRole("button", { name: "로그인 시작" }).click();
await expect(
page.getByRole("heading", { name: protectedRoute.title }),
).toBeVisible();
await expect(page.getByText("인증됨")).toBeVisible();
});
@@ -0,0 +1 @@
export const client_secret = "fixture-only-secret-value";
@@ -0,0 +1,9 @@
{
"schemaVersion": 1,
"trackedRoots": [
"tests/fixtures/security/secret-detection/forbidden"
],
"generatedRoots": [],
"excludedPaths": [],
"allowlist": []
}
@@ -0,0 +1,3 @@
{
"client_secret": "synthetic-forbidden-secret"
}
@@ -0,0 +1 @@
globalThis.password = "synthetic-built-secret";
@@ -0,0 +1 @@
export const leaked = "AKIAABCDEFGHIJKLMNOP";
+89
View File
@@ -0,0 +1,89 @@
import { describe, expect, it } from "vitest";
import {
diffDependencyInventories,
isValidSha512Integrity,
parsePnpmLockfilePackages,
supplyChainDigest,
validateDependencyReview,
validateLicensePolicy,
} from "../../scripts/lib/supply-chain.mjs";
const integrity = `sha512-${Buffer.alloc(64, 7).toString("base64")}`;
const dependency = {
name: "fixture",
version: "1.0.0",
direct: true,
scope: "production",
optional: false,
license: "MIT",
integrity,
dependencies: [],
};
describe("supply-chain policy", () => {
it("parses every top-level lockfile package and validates SRI", () => {
const parsed = parsePnpmLockfilePackages(`
packages:
'@scope/one@1.0.0':
resolution: {integrity: ${integrity}}
two@2.0.0:
resolution: {integrity: ${integrity}}
snapshots:
`);
expect(parsed).toEqual([
{ name: "@scope/one", version: "1.0.0", integrity },
{ name: "two", version: "2.0.0", integrity },
]);
expect(parsed.every((entry) => isValidSha512Integrity(entry.integrity))).toBe(
true,
);
});
it("keeps inventory digests stable when dependency ordering changes", () => {
const other = { ...dependency, name: "other" };
expect(supplyChainDigest([dependency, other])).toBe(
supplyChainDigest([other, dependency]),
);
});
it("calculates actual additions and requires independent high-risk review", () => {
const before = { dependencies: [] };
const after = { dependencies: [dependency] };
const diff = diffDependencyInventories(before, after);
expect(diff.added).toEqual(["fixture@1.0.0"]);
expect(
validateDependencyReview(diff, after, {
changes: [
{
changeId: "add:fixture@1.0.0",
owner: "one",
reviewer: "one",
reason: "fixture",
rollback: "remove",
},
],
}).passed,
).toBe(false);
});
it("allows explicit policy licenses and rejects denied licenses", () => {
expect(
validateLicensePolicy(
{ dependencies: [dependency] },
{ allowedLicenses: ["MIT"], deniedLicensePatterns: ["AGPL"] },
).passed,
).toBe(true);
expect(
validateLicensePolicy(
{
dependencies: [{ ...dependency, license: "AGPL-3.0" }],
},
{ allowedLicenses: ["MIT"], deniedLicensePatterns: ["AGPL"] },
).passed,
).toBe(false);
});
});