feat: verify frontend supply chain
This commit is contained in:
@@ -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("/");
|
||||
|
||||
@@ -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";
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user