101 lines
3.9 KiB
TypeScript
101 lines
3.9 KiB
TypeScript
// @vitest-environment node
|
|
import { spawnSync } from "node:child_process";
|
|
import path from "node:path";
|
|
import { describe, expect, test } from "vitest";
|
|
|
|
const entrypoint = path.join(process.cwd(), "start.sh");
|
|
const commonEnv = {
|
|
PATH: process.env.PATH,
|
|
RLS_RUNTIME_MODE: "required",
|
|
DATABASE_URL: "postgresql://runtime.invalid/hivegrid",
|
|
};
|
|
|
|
function runEntrypoint(env: Record<string, string | undefined>) {
|
|
return spawnSync("sh", [entrypoint], {
|
|
cwd: process.cwd(),
|
|
env: { ...commonEnv, ...env },
|
|
encoding: "utf8",
|
|
});
|
|
}
|
|
|
|
describe("web runtime entrypoint surface boundary", () => {
|
|
test("fails closed when the production surface is missing or invalid", () => {
|
|
for (const surface of [undefined, "customer"]) {
|
|
const result = runEntrypoint({ WEB_RUNTIME_SURFACE: surface });
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain("WEB_RUNTIME_SURFACE must be explicitly set to core, admin, or portal");
|
|
}
|
|
});
|
|
|
|
test("requires the core role and forbids the portal session secret", () => {
|
|
const wrongRole = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "core",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_portal",
|
|
SESSION_SECRET: "core-secret",
|
|
});
|
|
const crossedSecret = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "core",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_app",
|
|
SESSION_SECRET: "core-secret",
|
|
PORTAL_SESSION_SECRET: "portal-secret",
|
|
});
|
|
|
|
expect(wrongRole.stderr).toContain("DATABASE_RUNTIME_ROLE=hivegrid_app is mandatory for the web runtime");
|
|
expect(crossedSecret.stderr).toContain("PORTAL_SESSION_SECRET is forbidden in the core web runtime");
|
|
});
|
|
|
|
test("requires the dedicated portal role and secret while rejecting core authority", () => {
|
|
const wrongRole = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "portal",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_app",
|
|
PORTAL_SESSION_SECRET: "portal-secret",
|
|
});
|
|
const crossedSecret = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "portal",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_portal",
|
|
PORTAL_SESSION_SECRET: "portal-secret",
|
|
SESSION_SECRET: "core-secret",
|
|
});
|
|
const adminAuthority = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "portal",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_portal",
|
|
PORTAL_SESSION_SECRET: "portal-secret",
|
|
AUTHENTIK_ADMIN_JIT_DATABASE_URL: "postgresql://hivegrid_authentik_jit:secret@db.invalid/hivegrid",
|
|
});
|
|
|
|
expect(wrongRole.stderr).toContain("DATABASE_RUNTIME_ROLE=hivegrid_portal is mandatory for the portal web runtime");
|
|
expect(crossedSecret.stderr).toContain("SESSION_SECRET is forbidden in the portal web runtime");
|
|
expect(adminAuthority.stderr).toContain("AUTHENTIK_ADMIN_JIT_DATABASE_URL is forbidden in the portal web runtime");
|
|
});
|
|
|
|
test("requires a fail-closed Admin runtime with Authentik and no password fallback", () => {
|
|
const missingSso = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "admin",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_app",
|
|
SESSION_SECRET: "admin-session-secret",
|
|
ADMIN_FALLBACK_LOGIN_ENABLED: "false",
|
|
});
|
|
const fallbackEnabled = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "admin",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_app",
|
|
SESSION_SECRET: "admin-session-secret",
|
|
ADMIN_FALLBACK_LOGIN_ENABLED: "true",
|
|
});
|
|
|
|
expect(missingSso.stderr).toContain("AUTHENTIK_ISSUER_URL is required for the admin web runtime");
|
|
expect(fallbackEnabled.stderr).toContain("ADMIN_FALLBACK_LOGIN_ENABLED=false is mandatory for the admin web runtime");
|
|
});
|
|
|
|
test("rejects a pre-set internal build surface that crosses the runtime boundary", () => {
|
|
const result = runEntrypoint({
|
|
WEB_RUNTIME_SURFACE: "portal",
|
|
HIVEGRID_RUNTIME_SURFACE: "core",
|
|
DATABASE_RUNTIME_ROLE: "hivegrid_portal",
|
|
PORTAL_SESSION_SECRET: "portal-secret",
|
|
});
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain("HIVEGRID_RUNTIME_SURFACE must match WEB_RUNTIME_SURFACE");
|
|
});
|
|
});
|