34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, it } from "node:test";
|
|
|
|
const staticRunbook = readFileSync(
|
|
fileURLToPath(new URL("../../deploy/STATIC.md", import.meta.url)),
|
|
"utf8",
|
|
);
|
|
|
|
describe("production media permissions policy", () => {
|
|
const policy = staticRunbook.match(/Permissions-Policy\s+"([^"]+)"/)?.[1] ?? "";
|
|
|
|
it("allows only same-origin contextual camera and display prompts", () => {
|
|
assert.match(policy, /(?:^|,\s*)display-capture=\(self\)(?:,|$)/);
|
|
assert.match(policy, /(?:^|,\s*)camera=\(self\)(?:,|$)/);
|
|
assert.doesNotMatch(policy, /camera=\(\*\)/);
|
|
assert.doesNotMatch(policy, /display-capture=\(\*\)/);
|
|
});
|
|
|
|
it("keeps audio and unrelated high-risk capabilities denied", () => {
|
|
for (const capability of ["microphone", "geolocation", "payment", "usb"]) {
|
|
assert.match(policy, new RegExp(`(?:^|,\\s*)${capability}=\\(\\)(?:,|$)`));
|
|
}
|
|
});
|
|
|
|
it("documents denial, indicator, stop, and page lifecycle acceptance", () => {
|
|
assert.match(staticRunbook, /denying the browser prompt/i);
|
|
assert.match(staticRunbook, /active indicator/i);
|
|
assert.match(staticRunbook, /stop on the in-product control or `pagehide`/i);
|
|
assert.match(staticRunbook, /neither webcam faces nor office screens request audio/i);
|
|
});
|
|
});
|