rea/tests/composition/setup-lifecycle/browserConfig.test.ts

114 lines
3.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { parseConfig } from "../../../src/config.js";
describe("browser runtime configuration", () => {
it("builds an exact-origin browser observation ceiling only when enabled", () => {
const result = parseConfig({
REA_BROWSER_OBSERVE_ENABLED: "true",
REA_BROWSER_CDP_ENDPOINTS_JSON: '["http://127.0.0.1:9222"]',
REA_BROWSER_ALLOWED_ORIGINS_JSON:
'["https://app.example.test", "http://127.0.0.1:3000"]',
});
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.permissionCeilings).toContainEqual({
capability: "browser_observe",
roots: [],
executables: [],
environment_names: [],
origins: [
"http://127.0.0.1:9222",
"http://127.0.0.1:3000",
"https://app.example.test",
],
network: "external",
mount: false,
});
expect(result.value.administratorPermissionGrants).toContainEqual(
expect.objectContaining({
capability: "browser_observe",
lifetime: "administrator",
}),
);
});
it("classifies IPv6 browser origins as loopback network scope", () => {
const result = parseConfig({
REA_BROWSER_OBSERVE_ENABLED: "true",
REA_BROWSER_CDP_ENDPOINTS_JSON: '["http://127.0.0.1:9222"]',
REA_BROWSER_ALLOWED_ORIGINS_JSON: '["http://[::1]:3000"]',
});
if (!result.ok) throw result.error;
expect(result.value.permissionCeilings).toContainEqual(
expect.objectContaining({
capability: "browser_observe",
network: "loopback",
}),
);
});
it("requires an explicit grant for exact-scope browser automation", () => {
const environment = {
REA_BROWSER_SCENARIO_ENABLED: "true",
REA_BROWSER_SCENARIO_EXECUTABLE_ROOTS_JSON: '["/opt/chromium"]',
REA_BROWSER_SCENARIO_CDP_ENDPOINTS_JSON: '["http://127.0.0.1:9222"]',
REA_BROWSER_SCENARIO_ALLOWED_ORIGINS_JSON: '["https://app.example.test"]',
REA_BROWSER_SCENARIO_ALLOWED_ENV_JSON: '["REA_TEST_PASSWORD"]',
};
const result = parseConfig(environment);
if (!result.ok) throw result.error;
expect(result.value.browserScenarioPolicy).toEqual({
enabled: true,
executableRoots: ["/opt/chromium"],
cdpEndpoints: ["http://127.0.0.1:9222"],
allowedOrigins: ["https://app.example.test"],
allowedEnvironment: ["REA_TEST_PASSWORD"],
});
expect(result.value.permissionCeilings).toContainEqual({
capability: "browser_automate",
roots: [],
executables: ["/opt/chromium"],
environment_names: ["REA_TEST_PASSWORD"],
origins: ["http://127.0.0.1:9222", "https://app.example.test"],
network: "external",
mount: false,
});
expect(result.value.administratorPermissionGrants).not.toContainEqual(
expect.objectContaining({ capability: "browser_automate" }),
);
const automatic = parseConfig({
...environment,
REA_BROWSER_SCENARIO_AUTO_GRANT: "true",
});
if (!automatic.ok) throw automatic.error;
expect(automatic.value.administratorPermissionGrants).toContainEqual(
expect.objectContaining({
capability: "browser_automate",
lifetime: "administrator",
}),
);
});
it.each([
'["http://localhost:9222"]',
'["http://192.168.1.5:9222"]',
'["https://127.0.0.1:9222"]',
])("rejects unsafe browser CDP endpoint scopes: %s", (encoded) => {
expect(parseConfig({ REA_BROWSER_CDP_ENDPOINTS_JSON: encoded }).ok).toBe(
false,
);
});
it.each([
'["https://*.example.test"]',
'["https://app.example.test/private"]',
'["https://user:pass@app.example.test"]',
'["file:///tmp/application.html"]',
])("rejects non-exact browser origin scopes: %s", (encoded) => {
expect(parseConfig({ REA_BROWSER_ALLOWED_ORIGINS_JSON: encoded }).ok).toBe(
false,
);
});
});