← Files DataARCHIVED FILE
templates/data-app/base/scripts/authorize-protected-change.mjs
3.06 KB · Sep 30, 2026 · 23:19 UTC
import { spawnSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { digestProtectedFile } from "./protected-file-digest.mjs";
const root = dirname(dirname(fileURLToPath(import.meta.url)));
const argumentsList = process.argv.slice(2);
const scopes = [];
let reason = "";
for (let index = 0; index < argumentsList.length; index += 1) {
if (argumentsList[index] === "--scope") {
scopes.push(argumentsList[index + 1] ?? "");
index += 1;
} else if (argumentsList[index] === "--reason") {
reason = argumentsList[index + 1] ?? "";
index += 1;
}
}
function fail(message) {
console.error(message);
process.exitCode = 1;
}
if (!argumentsList.includes("--confirmed") || process.env.DATA_APP_USER_CONFIRMED !== "1") {
fail("A protected Data app change requires an explicit user request or approval; the request itself is sufficient authorization.");
} else if (!scopes.length || !reason.trim()) {
fail("Confirmed protected changes require at least one --scope and an explicit --reason.");
} else {
const manifest = JSON.parse(readFileSync(join(root, "protected-runtime.json"), "utf8"));
const uniqueScopes = [...new Set(scopes)];
const invalidScopes = uniqueScopes.filter((scope) => !Object.hasOwn(manifest.files, scope));
if (invalidScopes.length) {
fail(`Requested protected-change scope is not a protected runtime file: ${invalidScopes.join(", ")}`);
} else {
const changed = Object.entries(manifest.files).flatMap(([path, expected]) => {
const absolute = join(root, path);
if (!existsSync(absolute)) {
fail(`Protected runtime files cannot be removed by scoped authorization: ${path}`);
return [path];
}
try {
const actual = digestProtectedFile(path, readFileSync(absolute));
return actual === expected ? [] : [path];
} catch (error) {
fail(error instanceof Error ? error.message : String(error));
return [path];
}
});
const unapproved = changed.filter((path) => !uniqueScopes.includes(path));
const unchanged = uniqueScopes.filter((path) => !changed.includes(path));
if (unapproved.length) {
fail(`Unrelated protected runtime changes are not authorized: ${unapproved.join(", ")}`);
} else if (unchanged.length) {
fail(`Confirmed protected-change scope contains unchanged files: ${unchanged.join(", ")}`);
} else if (!process.exitCode) {
const update = spawnSync(
process.execPath,
[join(root, "scripts/verify-protected-runtime.mjs"), "--update", "--maintainer"],
{
cwd: root,
encoding: "utf8",
env: { ...process.env, DATA_APP_MAINTAINER: "1" },
},
);
if (update.status !== 0) {
fail(update.stderr || update.stdout || "Unable to update the authorized protected runtime.");
} else {
process.stdout.write(update.stdout);
console.log(`User-confirmed protected change authorized only for: ${uniqueScopes.join(", ")}.`);
}
}
}
}
SHA-256: 9b9f012d65c34a1f9ac4d107ba226f82aadabde72980c2d393c63e9d68eff6a3