← Files DataARCHIVED FILE
templates/data-app/base/scripts/verify-protected-runtime.mjs
12.7 KB · Sep 30, 2026 · 23:19 UTC
import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import { dirname, join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { digestProtectedFile } from "./protected-file-digest.mjs";
const authoredOnly = process.argv.includes("--authored-only");
const root = authoredOnly
? resolve(process.argv[process.argv.indexOf("--authored-only") + 1] ?? ".")
: dirname(dirname(fileURLToPath(import.meta.url)));
const manifestPath = join(root, "protected-runtime.json");
const editablePaths = ["src/content/", "src/theme.css", "src/data.json"];
const protectedRootPaths = [
"AGENTS.md",
".openai/hosting.json",
"index.html",
"package-lock.json",
"package.json",
"scripts/authorize-protected-change.mjs",
"scripts/protected-file-digest.mjs",
"scripts/verify-protected-runtime.mjs",
"vite.config.js",
];
function listFiles(directory) {
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
const path = join(directory, entry.name);
return entry.isDirectory() ? listFiles(path) : [path];
});
}
function portablePath(path) {
return relative(root, path).split("\\").join("/");
}
function isEditablePath(path) {
return editablePaths.some((approved) => (approved.endsWith("/") ? path.startsWith(approved) : path === approved));
}
function currentProtectedPaths() {
const sourcePaths = listFiles(join(root, "src"))
.map(portablePath)
.filter((path) => !isEditablePath(path));
const documentationPaths = listFiles(join(root, "docs/components")).map(portablePath);
return [...protectedRootPaths, ...sourcePaths, ...documentationPaths].sort();
}
function digest(path) {
return digestProtectedFile(path, readFileSync(join(root, path)));
}
const protectedChromeSelector =
/(?:\.dashboard-topbar(?:-[\w-]+)?|\.topbar-[\w-]+|\.dashboard-refresh-[\w-]+|\.freshness(?:-[\w-]+)?|\.theme-drawer(?:-[\w-]+)?|\.source-sidebar(?:-[\w-]+)?|\.dashboard-publish(?:-[\w-]+)?|\.dashboard-overflow|\[data-data-app-chrome(?:[\]=]|\s))/iu;
const protectedAncestorSelector = /(?:\.dashboard-root\b|#root\b|(?:^|,)\s*header(?=$|[\s.#[:,>+~]))/iu;
const globalDocumentSelector = /(?:^|[\s,>+~])(html|body)(?=$|[\s.#[:,>+~])/iu;
const appSurfaceSelector = /^(?:\.page|\.report-page|main|\[data-data-app-content(?:=[^\]]+)?\])$/iu;
const sharedThemeToken =
/^--(?:background|surface(?:-raised)?|muted|control(?:-hover|-radius)?|text|secondary|border(?:-strong)?|accent|positive|negative|chart-\d+|font-sans|card-radius)$/iu;
function authoredCssRules(css) {
const cleaned = css.replace(/\/\*[\s\S]*?\*\//gu, "");
return [...cleaned.matchAll(/(?:^|(?<=[{}]))\s*([^{}]+?)\s*\{([^{}]*)\}/gu)].map(([, selector, declarations]) => ({
selector: selector.trim(),
declarations,
}));
}
function normalizeCssSelector(selector) {
return selector
.replace(/\\(?:\r\n|[\n\r\f])/gu, "")
.replace(/\\([0-9a-f]{1,6})(?:\r\n|[ \t\r\n\f])?/giu, (_, value) => {
const point = Number.parseInt(value, 16);
return !point || point > 0x10ffff || (point >= 0xd800 && point <= 0xdfff)
? "\uFFFD"
: String.fromCodePoint(point);
})
.replace(/\\([^0-9a-f\r\n\f])/giu, "$1");
}
function verifyAuthoredStyles(path) {
const css = readFileSync(join(root, path), "utf8");
const rules = authoredCssRules(css);
const intent = [...css.matchAll(/--data-app-layout-intent\s*:\s*([\w-]+)/gu)].map(([, value]) => value).at(-1);
if (intent && !["standard", "wide", "full-bleed", "user-requested", "authored-report"].includes(intent)) {
throw new Error(`Authored stylesheet "${path}" uses an unrecognized layout intent: ${intent}.`);
}
for (const { selector, declarations } of rules) {
const normalizedSelector = normalizeCssSelector(selector);
if (normalizedSelector.startsWith("@")) continue;
if (protectedChromeSelector.test(normalizedSelector) || protectedAncestorSelector.test(normalizedSelector)) {
throw new Error(
`Authored stylesheet "${path}" targets protected application chrome: ${selector}. Use approved theme tokens instead.`,
);
}
if (
globalDocumentSelector.test(normalizedSelector) ||
normalizedSelector.split(",").some((part) => /^\s*\*(?=$|[\s.#[:,>+~])/u.test(part))
) {
throw new Error(`Authored stylesheet "${path}" targets the global document: ${selector}.`);
}
if (
path.startsWith("src/content/") &&
normalizedSelector.split(",").some((part) => appSurfaceSelector.test(part.trim()))
) {
const overlayProperties = [...declarations.matchAll(/(?:^|;)\s*([\w-]+)\s*:\s*([^;]+)/gu)]
.filter(([, property, value]) => {
const normalizedValue = value.trim().replace(/\s*!important$/iu, "");
if (property === "position") return /^(?:absolute|fixed|sticky)$/iu.test(normalizedValue);
if (property === "z-index") return normalizedValue !== "auto";
if (property === "pointer-events") return normalizedValue !== "auto";
return /^(?:inset(?:-[\w-]+)?|top|right|bottom|left|transform|translate)$/iu.test(property);
})
.map(([, property]) => property);
if (overlayProperties.length) {
throw new Error(
`Authored app surface in "${path}" can cover or disable protected application chrome: ${overlayProperties.join(
", ",
)}. Apply positioning and stacking only to scoped content inside the app surface.`,
);
}
const tokens = [...declarations.matchAll(/(?:^|;)\s*([\w-]+)\s*:/gu)]
.map(([, name]) => name)
.filter((name) => sharedThemeToken.test(name));
if (tokens.length) {
throw new Error(
`App-wide theme tokens in "${path}" must be defined on :root in src/theme.css so the page, chrome, controls, and authored content stay consistent: ${tokens.join(
", ",
)}.`,
);
}
const width = declarations.match(/(?:^|;)\s*max-width\s*:\s*([^;]+)/u)?.[1].trim();
const customContentWidth = declarations.match(/(?:^|;)\s*--data-app-content-width\s*:\s*([^;]+)/u)?.[1].trim();
const customGutter = declarations.match(/(?:^|;)\s*--data-app-layout-gutter\s*:\s*([^;]+)/u)?.[1].trim();
const approvedFrame =
width && /var\(--data-app-content-width\)/u.test(width) && /var\(--data-app-layout-gutter\)/u.test(width);
const authoredReport = intent === "authored-report" && path.startsWith("src/content/report/")
&& normalizedSelector.split(",").every((part) => part.trim() === ".report-page");
const customLayout = intent === "user-requested" || authoredReport;
if (width && !approvedFrame && !(width === "none" && intent === "full-bleed") && !customLayout) {
throw new Error(
`Authored layout in "${path}" overrides the standard content frame. Use the approved width tokens, the full-bleed preset, or mark an explicitly user-requested custom width with --data-app-layout-intent: user-requested.`,
);
}
if (
customContentWidth &&
!/^var\(--data-app-(?:dashboard-content|dashboard-wide-content|report-evidence)-width\)$/u.test(
customContentWidth,
) &&
!customLayout
) {
throw new Error(
`Authored layout in "${path}" uses an arbitrary content width. Use an approved preset or mark an explicitly user-requested width with --data-app-layout-intent: user-requested.`,
);
}
if (
customContentWidth?.includes("--data-app-dashboard-wide-content-width") &&
!["wide", "full-bleed", "user-requested"].includes(intent) && !authoredReport
) {
throw new Error(
`Authored layout in "${path}" must explicitly mark the dashboard wide token with --data-app-layout-intent: wide.`,
);
}
if (
customGutter &&
!/^var\(--data-app-(?:dashboard|report)(?:-mobile)?-gutter\)$/u.test(customGutter) &&
!customLayout
) {
throw new Error(
`Authored layout in "${path}" uses a nonstandard gutter without an explicitly user-requested layout intent.`,
);
}
}
if (/^:root(?:\s*,\s*:root)*$/u.test(normalizedSelector)) {
const properties = [...declarations.matchAll(/(?:^|;)\s*([\w-]+)\s*:/gu)].map(([, name]) => name);
const disallowed = properties.filter((name) => !name.startsWith("--") && name !== "color-scheme");
if (disallowed.length) {
throw new Error(`Theme root in "${path}" may contain only approved styling tokens: ${disallowed.join(", ")}.`);
}
}
}
}
function verifyAuthoredCode(path) {
const source = readFileSync(join(root, path), "utf8");
if (/<main(?:\s|>)/u.test(source)) {
throw new Error(
`Authored content "${path}" creates a nested main landmark. The protected shell owns the only application main; use an article, section, or div for authored content.`,
);
}
if (
/(?:\bfrom\s*|\bimport\s*(?:\(\s*)?|\brequire\s*\(\s*)["'`][^"'`]*(?:\/components\/|\/charting\/|DataAppShell|DataAppContext|data-app-actions)/u.test(
source,
)
) {
throw new Error(`Authored content "${path}" must import protected behavior through data-app-public.jsx.`);
}
if (
/document\s*\.\s*(?:body|documentElement)\s*\.\s*(?:remove|replaceChildren|replaceWith|innerHTML)/u.test(source) ||
/document\s*\.\s*querySelector\s*\([^)]*(?:dashboard-topbar|data-data-app-chrome|theme-drawer|freshness)[^)]*\)\s*\??\.\s*(?:remove|replaceWith|setAttribute)/u.test(
source,
) ||
/createPortal\s*\([^)]*document\s*\.\s*body/u.test(source)
) {
throw new Error(`Authored content "${path}" directly modifies or overlays protected application chrome.`);
}
}
function verifyAuthoredBoundaries() {
const contentRoot = join(root, "src/content");
if (!existsSync(contentRoot)) throw new Error("The approved authored-content directory is missing: src/content/");
for (const file of listFiles(contentRoot)) {
const path = portablePath(file);
if (/\.(?:css|scss)$/u.test(path)) verifyAuthoredStyles(path);
if (/\.(?:jsx?|tsx?|mjs)$/u.test(path)) verifyAuthoredCode(path);
}
verifyAuthoredStyles("src/theme.css");
}
function updateManifest() {
if (!process.argv.includes("--maintainer") || process.env.DATA_APP_MAINTAINER !== "1") {
throw new Error(
"Protected runtime updates are maintainer-only. Run DATA_APP_MAINTAINER=1 npm run integrity:update after reviewing infrastructure changes.",
);
}
const files = Object.fromEntries(currentProtectedPaths().map((path) => [path, digest(path)]));
writeFileSync(manifestPath, `${JSON.stringify({ version: 1, editablePaths, files }, null, 2)}\n`);
console.log(`Updated protected Data app runtime manifest (${Object.keys(files).length} files).`);
}
function verifyManifest() {
if (!existsSync(manifestPath)) {
throw new Error("Missing protected Data app runtime manifest: protected-runtime.json");
}
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
if (JSON.stringify(manifest.editablePaths) !== JSON.stringify(editablePaths)) {
throw new Error("The approved model-authored file allowlist was modified.");
}
const expectedPaths = Object.keys(manifest.files).sort();
for (const path of expectedPaths) {
if (!existsSync(join(root, path))) {
throw new Error(`Protected Data app runtime file is missing: ${path}`);
}
if (digest(path) !== manifest.files[path]) {
throw new Error(
`Protected Data app runtime file was modified: ${path}. Models may edit only ${editablePaths.join(", ")}.`,
);
}
}
const unexpected = currentProtectedPaths().filter((path) => !expectedPaths.includes(path));
if (unexpected.length) {
throw new Error(`Unapproved protected Data app runtime files were added: ${unexpected.join(", ")}`);
}
const packageMetadata = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
if (
packageMetadata.scripts?.prebuild !== "node scripts/verify-protected-runtime.mjs" ||
!packageMetadata.scripts?.build?.startsWith("node scripts/verify-protected-runtime.mjs &&")
) {
throw new Error("The Data app build must verify its protected runtime before invoking Vite.");
}
verifyAuthoredBoundaries();
console.log(`Protected Data app runtime verified (${expectedPaths.length} files).`);
}
try {
if (authoredOnly) {
if (
process.argv.length !== 4 ||
process.argv[2] !== "--authored-only" ||
!process.argv[3]?.trim() ||
process.argv[3].startsWith("--")
) {
throw new Error("Use --authored-only <project-directory> without update or authorization options.");
}
verifyAuthoredBoundaries();
console.log("Data app authored content verified.");
} else if (process.argv.includes("--update")) updateManifest();
else verifyManifest();
} catch (error) {
console.error(error instanceof Error ? error.message : error);
process.exitCode = 1;
}
SHA-256: 47d95847a9135cd125581a4b994208adc3822cbef4a2c8bfaf562f0d2ef3a9af