release: WRNexusJS 0.7.0

This commit is contained in:
2026-08-01 10:04:42 +05:30
parent c54144f2e4
commit 87507edf59
207 changed files with 12607 additions and 679 deletions
+76
View File
@@ -0,0 +1,76 @@
import console from "node:console";
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
import { runBenchmark, assertBenchmarkBudget } from "../packages/benchmark/src/index.ts";
import { TagCache } from "../packages/cache/src/memory.ts";
import { secureJsonStringify } from "../packages/security/src/serialization.ts";
import { parse } from "../packages/syntax/src/index.ts";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const componentSource = readFileSync(
join(root, "packages", "ui", "components", "button.wrn"),
"utf8",
);
const hydrationPayload = {
route: "/benchmark",
user: { id: "user-1", displayName: "WRNexus", token: "must-redact" },
items: Array.from({ length: 100 }, (_, index) => ({ id: index, label: `Item ${index}` })),
};
const cache = new TagCache({ maxEntries: 1000 });
for (let index = 0; index < 500; index++) cache.set(`item:${index}`, index, { tags: ["items"] });
const benchmarks = [
{
result: await runBenchmark("syntax-parse-component", () => parse(componentSource), {
iterations: 100,
warmup: 10,
}),
budget: { maxAbsoluteMs: 50, minOperationsPerSecond: 20 },
},
{
result: await runBenchmark(
"secure-hydration-serialization",
() => secureJsonStringify(hydrationPayload),
{ iterations: 250, warmup: 20 },
),
budget: { maxAbsoluteMs: 20, minOperationsPerSecond: 100 },
},
{
result: await runBenchmark(
"tag-cache-read-100",
() => {
for (let index = 0; index < 100; index++) cache.get(`item:${index}`);
},
{ iterations: 250, warmup: 20 },
),
budget: { maxAbsoluteMs: 20, minOperationsPerSecond: 100 },
},
];
for (const benchmark of benchmarks) {
assertBenchmarkBudget(benchmark.result, undefined, benchmark.budget);
}
const report = {
schemaVersion: 1,
frameworkVersion: "0.7.0",
environment: { runtime: process.version, platform: process.platform, arch: process.arch },
benchmarks: benchmarks.map(({ result, budget }) => ({ result, budget })),
};
const reportDir = join(root, ".wrnexus", "reports");
mkdirSync(reportDir, { recursive: true });
writeFileSync(join(reportDir, "benchmark-0.7.0.json"), `${JSON.stringify(report, null, 2)}\n`);
console.log(
JSON.stringify(
report.benchmarks.map(({ result }) => ({
name: result.name,
meanMs: result.meanMs,
p95Ms: result.p95Ms,
operationsPerSecond: result.operationsPerSecond,
})),
null,
2,
),
);
+112
View File
@@ -0,0 +1,112 @@
import console from "node:console";
import { createHash } from "node:crypto";
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const rootManifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
const components = [];
function npmPurl(name, version) {
if (name.startsWith("@")) {
const slash = name.indexOf("/");
return `pkg:npm/%40${encodeURIComponent(name.slice(1, slash))}/${encodeURIComponent(name.slice(slash + 1))}@${version}`;
}
return `pkg:npm/${encodeURIComponent(name)}@${version}`;
}
for (const entry of readdirSync(join(root, "packages"), { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const file = join(root, "packages", entry.name, "package.json");
try {
const manifest = JSON.parse(readFileSync(file, "utf8"));
if (!manifest.name?.startsWith("@wrnexus/")) continue;
components.push({
type: "library",
name: manifest.name,
version: manifest.version,
"bom-ref": npmPurl(manifest.name, manifest.version),
purl: npmPurl(manifest.name, manifest.version),
properties: [
{ name: "wrnexus:workspace", value: "true" },
{ name: "wrnexus:private", value: String(manifest.publishConfig?.access !== "public") },
],
});
} catch {
// Not a workspace package.
}
}
// Bun's text lockfile is JSON with optional trailing commas. Package tuples use
// ["name@version", resolved, metadata, integrity], which is enough to include
// every resolved transitive dependency without requiring node_modules.
try {
const lockSource = readFileSync(join(root, "bun.lock"), "utf8").replace(/,\s*([}\]])/g, "$1");
const lock = JSON.parse(lockSource);
const external = new Map();
for (const value of Object.values(lock.packages ?? {})) {
if (!Array.isArray(value) || typeof value[0] !== "string") continue;
const specifier = value[0];
const split = specifier.lastIndexOf("@");
if (split <= 0) continue;
const name = specifier.slice(0, split);
const version = specifier.slice(split + 1);
if (!name || !version || name.startsWith("@wrnexus/")) continue;
const ref = npmPurl(name, version);
const component = {
type: "library",
name,
version,
"bom-ref": ref,
purl: ref,
properties: [{ name: "wrnexus:dependency-source", value: "bun.lock" }],
};
const integrity = typeof value[3] === "string" ? value[3] : "";
if (integrity.startsWith("sha512-")) {
component.hashes = [{ alg: "SHA-512", content: integrity.slice("sha512-".length) }];
}
external.set(ref, component);
}
components.push(...external.values());
} catch (error) {
throw new Error(
`Unable to parse bun.lock for the SBOM: ${error instanceof Error ? error.message : String(error)}`,
{ cause: error },
);
}
components.sort((a, b) => {
const left = `${a.name}@${a.version}`;
const right = `${b.name}@${b.version}`;
return left < right ? -1 : left > right ? 1 : 0;
});
function deterministicUuid(value) {
const hash = createHash("sha256").update(value).digest("hex").slice(0, 32).split("");
hash[12] = "5";
hash[16] = ((Number.parseInt(hash[16], 16) & 0x3) | 0x8).toString(16);
const hex = hash.join("");
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
const version = String(rootManifest.version);
const identity = JSON.stringify({ framework: "WRNexusJS", version, components });
const document = {
bomFormat: "CycloneDX",
specVersion: "1.5",
serialNumber: `urn:uuid:${deterministicUuid(identity)}`,
version: 1,
metadata: {
component: {
type: "framework",
name: "WRNexusJS",
version,
"bom-ref": `pkg:generic/WRNexusJS@${version}`,
},
},
components,
};
const file = join(root, `SBOM-${version}.cdx.json`);
writeFileSync(file, `${JSON.stringify(document, null, 2)}\n`);
console.log(`Generated ${file} with ${components.length} workspace and transitive components.`);
+76
View File
@@ -0,0 +1,76 @@
import { createHash } from "node:crypto";
import { readdirSync, readFileSync } from "node:fs";
import { basename, join, relative } from "node:path";
export interface StagedFileIntegrity {
path: string;
bytes: number;
sha256: string;
}
export interface StagedPackageIntegrity {
name: string;
version: string;
files: StagedFileIntegrity[];
}
const forbiddenStageName =
/^(?:\.env(?:\..*)?|focus-shims\.d\.ts|tsconfig\.focus\.json|id_rsa|id_ed25519|.*\.(?:pem|key|p12|pfx))$/i;
const highConfidenceSecret =
/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----|\bAKIA[0-9A-Z]{16}\b|\bnpm_[A-Za-z0-9]{30,}\b|\bgh[pousr]_[A-Za-z0-9]{30,}\b/;
function listFiles(root: string): string[] {
const files: string[] = [];
for (const entry of readdirSync(root, { recursive: true, withFileTypes: true })) {
if (!entry.isFile()) continue;
files.push(join(entry.parentPath, entry.name));
}
return files.sort((a, b) => {
const left = relative(root, a).replace(/\\/g, "/");
const right = relative(root, b).replace(/\\/g, "/");
return left < right ? -1 : left > right ? 1 : 0;
});
}
export function validateAndHashStage(
stage: string,
manifest: Record<string, unknown>,
): StagedPackageIntegrity {
const name = String(manifest.name ?? "unknown package");
const files = listFiles(stage);
if (!files.length) throw new Error(`${name} staged no files.`);
const integrity: StagedFileIntegrity[] = [];
for (const file of files) {
const path = relative(stage, file).replace(/\\/g, "/");
const filename = basename(file);
if (forbiddenStageName.test(filename)) {
throw new Error(`${name} staged forbidden secret-like file ${path}.`);
}
if (path.endsWith(".map")) {
throw new Error(`${name} staged source map ${path}; package source maps are disabled.`);
}
if (path.endsWith(".ts") && !path.endsWith(".d.ts")) {
throw new Error(`${name} staged TypeScript source ${path}.`);
}
const value = readFileSync(file);
if (value.byteLength <= 2 * 1024 * 1024) {
const source = value.toString("utf8");
if (highConfidenceSecret.test(source)) {
throw new Error(`${name} staged content matching a high-confidence secret in ${path}.`);
}
}
integrity.push({
path,
bytes: value.byteLength,
sha256: createHash("sha256").update(value).digest("hex"),
});
}
return {
name,
version: String(manifest.version ?? "unknown"),
files: integrity,
};
}
+21 -2
View File
@@ -26,6 +26,8 @@ import {
} from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
import { validateAndHashStage, type StagedPackageIntegrity } from "./lib/package-integrity.ts";
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
const packagesDir = join(repoRoot, "packages");
@@ -240,6 +242,7 @@ async function main() {
mkdirSync(stageRoot, { recursive: true });
const order: string[] = [];
const packageIntegrity: StagedPackageIntegrity[] = [];
for (const p of pkgs) {
const entries = entriesOf(p.dir, p.manifest);
process.stdout.write(`${p.name}`);
@@ -297,11 +300,27 @@ async function main() {
);
}
packageIntegrity.push(validateAndHashStage(stage, manifest));
order.push(p.name);
console.log("staged");
console.log("staged + verified");
}
console.log(`\n✓ Staged ${order.length} package(s) under .publish/ (access: ${ACCESS})`);
const integrityDocument = {
schemaVersion: 1,
frameworkVersion: String(
JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")).version,
),
access: ACCESS,
packages: packageIntegrity,
};
writeFileSync(
join(stageRoot, "PACKAGE-INTEGRITY.json"),
`${JSON.stringify(integrityDocument, null, 2)}\n`,
);
console.log(
`\n✓ Staged and verified ${order.length} package(s) under .publish/ (access: ${ACCESS})`,
);
console.log("Publish order (deps first):");
for (const n of order) {
console.log(` npm publish .publish/${n.replace("@wrnexus/", "")} --access ${ACCESS}`);
+44 -5
View File
@@ -13,6 +13,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
import { updateMigrationVersions } from "../packages/cli/src/update.ts";
import { validateAndHashStage } from "./lib/package-integrity.ts";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const docsRoot = resolve(process.env.WRNEXUS_DOCS_ROOT ?? "D:\\Company\\wrnexusjs");
@@ -106,6 +107,18 @@ function requireMigration(version: string) {
}
function validateStaging(all: PackageInfo[], version: string) {
const integrityPath = join(root, ".publish", "PACKAGE-INTEGRITY.json");
if (!existsSync(integrityPath)) {
throw new Error("Missing .publish/PACKAGE-INTEGRITY.json; stage verification did not run.");
}
const integrity = JSON.parse(readFileSync(integrityPath, "utf8"));
const recorded = new Map(
(Array.isArray(integrity.packages) ? integrity.packages : []).map((entry: any) => [
entry.name,
entry,
]),
);
for (const pkg of all) {
const stage = join(root, ".publish", pkg.dir);
const manifestPath = join(stage, "package.json");
@@ -117,6 +130,18 @@ function validateStaging(all: PackageInfo[], version: string) {
if (manifest.version !== version || manifest.publishConfig?.access !== "restricted") {
throw new Error(`${pkg.name} staging is not restricted ${version}.`);
}
const actual = validateAndHashStage(stage, manifest);
const expected = recorded.get(pkg.name);
if (!expected || JSON.stringify(expected) !== JSON.stringify(actual)) {
throw new Error(`${pkg.name} staging integrity does not match PACKAGE-INTEGRITY.json.`);
}
}
if (recorded.size !== all.length) {
throw new Error(
`Staging integrity lists ${recorded.size} packages but the workspace contains ${all.length}.`,
);
}
}
@@ -199,6 +224,11 @@ function prepare(all: PackageInfo[], version: string) {
run(process.execPath, ["run", "scripts/generate-ui-component-reference.mjs"], root);
run(process.execPath, ["run", "format"]);
run(process.execPath, ["run", "check:workspace"]);
run(process.execPath, ["run", "validate:0.7"]);
run(process.execPath, ["run", "security:framework"]);
run(process.execPath, ["run", "sbom"]);
run(process.execPath, ["run", "benchmark:framework"]);
run(process.execPath, ["run", "check"]);
run(process.execPath, ["run", "scripts/publish-packages.ts"]);
validateStaging(all, version);
@@ -230,11 +260,17 @@ function verifyUiComponentReference(): void {
throw new Error(`Failed to generate the UI component reference.${detail ? `\n${detail}` : ""}`);
}
// Format generated files before comparing them with Git.
// The generator expands JSON arrays, while Prettier may place short arrays
// on one line. Comparing before formatting creates a permanent false diff.
// The generator intentionally produces stable semantic JSON, while Prettier
// controls repository formatting. Format only the generated files before the
// Git comparison so short arrays and Windows line endings cannot create a
// permanent generate/format release loop.
run(process.execPath, ["x", "prettier", "--write", ...generatedFiles], root);
// Do not use `git status --short` here. On Windows, the generator writes LF
// while an autocrlf checkout may contain CRLF. `git status` can report those
// files as modified even when their canonical Git content is identical.
// `git diff --quiet` applies Git's normal text conversion and only fails for
// a real generated-content difference.
const changedStatus = run("git", ["diff", "--quiet", "--", ...generatedFiles], root, {
capture: true,
allowFailure: true,
@@ -254,9 +290,9 @@ function verifyUiComponentReference(): void {
"",
"Run:",
" bun run scripts/generate-ui-component-reference.mjs",
" bunx prettier --write packages/ui/component-catalog.json packages/ui/component-reference.json packages/ui/COMPONENTS.md",
" bun run format",
" git add packages/ui/component-catalog.json packages/ui/component-reference.json packages/ui/COMPONENTS.md",
' git commit -m \\"docs(ui): refresh component reference\\"',
' git commit -m "docs(ui): refresh component reference"',
" git push origin main",
].join("\n"),
);
@@ -265,6 +301,9 @@ function verifyUiComponentReference(): void {
function publish(all: PackageInfo[], version: string) {
if (!existsSync(docsRoot)) throw new Error(`Docs repository not found: ${docsRoot}`);
requireMigration(version);
run(process.execPath, ["run", "check:workspace"]);
run(process.execPath, ["run", "validate:0.7"]);
run(process.execPath, ["run", "security:framework"]);
requireCleanAndPushed(root, "Framework");
requireCleanAndPushed(docsRoot, "Docs");
+99
View File
@@ -0,0 +1,99 @@
import console from "node:console";
import { execFileSync } from "node:child_process";
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const dryRun = process.argv.includes("--check");
const removed = [];
const untracked = [];
const warnings = [];
function removeLocal(path) {
const absolute = join(root, path);
if (!existsSync(absolute)) return;
if (!dryRun) unlinkSync(absolute);
removed.push(path);
}
function git(args, capture = false) {
return execFileSync("git", args, {
cwd: root,
encoding: "utf8",
stdio: capture ? ["ignore", "pipe", "pipe"] : ["ignore", "ignore", "pipe"],
});
}
function isGitRepository() {
try {
return git(["rev-parse", "--is-inside-work-tree"], true).trim() === "true";
} catch {
return false;
}
}
function trackedFiles() {
try {
return git(["ls-files", "-z"], true).split("\0").filter(Boolean);
} catch {
return [];
}
}
function ensureIgnoreRules() {
const path = join(root, ".gitignore");
const current = existsSync(path) ? readFileSync(path, "utf8") : "";
const required = [
".env",
".env.*",
"!.env.example",
"!.env.*.example",
"focus-shims.d.ts",
"tsconfig.focus.json",
];
const lines = new Set(current.split(/\r?\n/).map((line) => line.trim()));
const missing = required.filter((line) => !lines.has(line));
if (missing.length === 0) return;
if (!dryRun) {
const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
writeFileSync(path, `${current}${separator}${missing.join("\n")}\n`);
}
warnings.push(`Added missing .gitignore rules: ${missing.join(", ")}`);
}
removeLocal("focus-shims.d.ts");
removeLocal("tsconfig.focus.json");
ensureIgnoreRules();
if (isGitRepository()) {
const secretPattern = /(?:^|\/)(?:\.env(?:\..+)?|id_rsa|id_ed25519|.*\.(?:pem|p12|pfx|key))$/i;
const safeTemplate = /(?:^|\/)\.env(?:\.[^/]+)*\.(?:example|sample|template)$/i;
const temporaryPattern = /(?:^|\/)(?:focus-shims\.d\.ts|tsconfig\.focus\.json)$/i;
const unsafeTracked = trackedFiles().filter(
(path) => temporaryPattern.test(path) || (secretPattern.test(path) && !safeTemplate.test(path)),
);
for (const path of unsafeTracked) {
if (!dryRun) git(["rm", "--cached", "--ignore-unmatch", "--", path]);
untracked.push(path);
}
} else {
warnings.push(
"Git metadata was not found, so tracked secret files could not be removed from the Git index.",
);
}
console.log(dryRun ? "Workspace repair check:" : "Workspace repaired:");
console.log(
`- ${dryRun ? "would remove" : "removed"} temporary files: ${removed.length ? removed.join(", ") : "none"}`,
);
console.log(
`- ${dryRun ? "would remove" : "removed"} from Git tracking: ${untracked.length ? untracked.join(", ") : "none"}`,
);
for (const warning of warnings) console.warn(`- warning: ${warning}`);
if (dryRun && (removed.length > 0 || untracked.length > 0)) {
console.error("Workspace repair is required. Run: bun run repair:workspace");
process.exitCode = 1;
}
+204
View File
@@ -0,0 +1,204 @@
import console from "node:console";
import { execFileSync } from "node:child_process";
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync, mkdirSync } from "node:fs";
import { dirname, extname, join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const issues = [];
const warnings = [];
const checks = [];
function addCheck(name, passed, detail) {
checks.push({ name, passed, detail });
if (!passed) issues.push({ severity: "error", code: name, detail });
}
function addWarning(name, detail) {
warnings.push({ severity: "warning", code: name, detail });
}
function walk(dir, output = []) {
for (const entry of readdirSync(dir, { withFileTypes: true })) {
if (["node_modules", ".git", ".publish", "dist", ".wrnexus"].includes(entry.name)) continue;
const path = join(dir, entry.name);
if (entry.isDirectory()) walk(path, output);
else output.push(path);
}
return output;
}
function listGitTrackedFiles() {
try {
const output = execFileSync("git", ["ls-files", "-z"], {
cwd: root,
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
});
return output
.split("\0")
.filter(Boolean)
.map((path) => join(root, path))
.filter((path) => existsSync(path) && statSync(path).isFile());
} catch {
// Source archives do not contain .git metadata. In that environment the
// archive itself is the release boundary, so scanning every included file
// is the correct fallback.
return walk(root);
}
}
const allFiles = walk(root);
const trackedFiles = listGitTrackedFiles();
const trackedSet = new Set(trackedFiles.map((path) => resolve(path)));
const manifests = trackedFiles
.filter((path) => path.startsWith(join(root, "packages")) && path.endsWith("package.json"))
.map((path) => ({ path, value: JSON.parse(readFileSync(path, "utf8")) }))
.filter(({ value }) => value.name?.startsWith("@wrnexus/"));
addCheck(
"SEC-PACKAGE-VERSION",
manifests.every(({ value }) => value.version === "0.7.0"),
"Every @wrnexus package must use version 0.7.0.",
);
addCheck(
"SEC-PRIVATE-PUBLISH",
manifests.every(({ value }) => value.publishConfig?.access !== "public"),
"No framework package may opt into public access in a private release.",
);
const secretNames = /(?:^|\/)(?:\.env(?:\..+)?|id_rsa|id_ed25519|.*\.(?:pem|p12|pfx|key))$/i;
const safeSecretTemplates = /(?:^|\/)\.env(?:\.[^/]+)*\.(?:example|sample|template)$/i;
function isSecretLike(path) {
const normalized = relative(root, path).replace(/\\/g, "/");
return secretNames.test(normalized) && !safeSecretTemplates.test(normalized);
}
const trackedSecretFiles = trackedFiles.filter(isSecretLike);
addCheck(
"SEC-NO-TRACKED-SECRET-FILES",
trackedSecretFiles.length === 0,
trackedSecretFiles.length > 0
? `${trackedSecretFiles.map((path) => relative(root, path)).join(", ")}; run: bun run repair:workspace`
: "No tracked secret-like files found.",
);
const temporaryTypecheckPattern = /(?:^|\/)(?:focus-shims\.d\.ts|tsconfig\.focus\.json)$/i;
const trackedTypecheckHelpers = trackedFiles.filter((path) =>
temporaryTypecheckPattern.test(relative(root, path).replace(/\\/g, "/")),
);
addCheck(
"SEC-NO-TRACKED-TYPECHECK-SHIMS",
trackedTypecheckHelpers.length === 0,
trackedTypecheckHelpers.length > 0
? `${trackedTypecheckHelpers.map((path) => relative(root, path)).join(", ")}; run: bun run repair:workspace`
: "No temporary typecheck helpers are tracked.",
);
const localTypecheckHelpers = allFiles.filter(
(path) =>
temporaryTypecheckPattern.test(relative(root, path).replace(/\\/g, "/")) &&
!trackedSet.has(resolve(path)),
);
if (localTypecheckHelpers.length > 0) {
addWarning(
"SEC-LOCAL-TYPECHECK-SHIMS",
`Temporary local typecheck helpers are ignored by the root TypeScript program and can be removed with bun run repair:workspace: ${localTypecheckHelpers
.map((path) => relative(root, path))
.join(", ")}`,
);
}
const localSecretFiles = allFiles.filter(
(path) => isSecretLike(path) && !trackedSet.has(resolve(path)),
);
if (localSecretFiles.length > 0) {
addWarning(
"SEC-LOCAL-SECRET-FILES",
`Ignored or untracked local secret files were not included in the release audit: ${localSecretFiles
.map((path) => relative(root, path))
.join(", ")}`,
);
}
const wrnFiles = trackedFiles.filter((path) => extname(path) === ".wrn");
const dangerousUrls = [];
for (const path of wrnFiles) {
const source = readFileSync(path, "utf8");
if (
/\b(?:href|src|action|formaction)\s*=\s*["']\s*(?:javascript:|vbscript:|file:)/i.test(source)
) {
dangerousUrls.push(relative(root, path));
}
}
addCheck(
"SEC-NO-DANGEROUS-STATIC-URLS",
dangerousUrls.length === 0,
dangerousUrls.join(", ") || "No dangerous static URLs found.",
);
const productionFiles = trackedFiles.filter((path) =>
/packages\/(?:security|cache|image|observability|ssr|core)\/src\/.+\.ts$/.test(
path.replace(/\\/g, "/"),
),
);
const dynamicCode = [];
for (const path of productionFiles) {
const source = readFileSync(path, "utf8");
if (/\beval\s*\(|\bnew\s+Function\s*\(/.test(source)) dynamicCode.push(relative(root, path));
}
addCheck(
"SEC-FOUNDATION-NO-DYNAMIC-CODE",
dynamicCode.length === 0,
dynamicCode.join(", ") || "No dynamic code execution in security foundation packages.",
);
const runtimePath = join(root, "packages", "csr", "src", "reactive-runtime.ts");
addCheck(
"PERF-RUNTIME-SIZE",
statSync(runtimePath).size < 250_000,
`Reactive runtime source is ${statSync(runtimePath).size} bytes.`,
);
addCheck(
"PERF-ZERO-JS-ANALYSIS",
existsSync(join(root, "packages", "compiler", "src", "analysis.ts")),
"Static/interactive route analysis must exist.",
);
addCheck(
"PERF-BROTLI",
readFileSync(join(root, "packages", "dev-server", "src", "runtime.ts"), "utf8").includes(
"brotliCompressSync",
),
"Production runtime should prefer Brotli.",
);
addCheck(
"OBS-METRICS",
existsSync(join(root, "packages", "observability", "src", "metrics.ts")),
"Metrics registry must exist.",
);
addCheck(
"SUPPLY-SBOM",
existsSync(join(root, "scripts", "generate-sbom.mjs")),
"SBOM generator must exist.",
);
const report = {
schemaVersion: 2,
frameworkVersion: "0.7.0",
generatedAt: new Date().toISOString(),
passed: issues.length === 0,
checks,
warnings,
issues,
};
const reportDir = join(root, ".wrnexus", "reports");
mkdirSync(reportDir, { recursive: true });
writeFileSync(
join(reportDir, "security-performance-0.7.0.json"),
JSON.stringify(report, null, 2) + "\n",
);
for (const check of checks)
console.log(`${check.passed ? "ok" : "FAIL"} ${check.name}${check.detail}`);
for (const warning of warnings) console.warn(`warn ${warning.code}${warning.detail}`);
if (issues.length) process.exitCode = 1;
+66
View File
@@ -0,0 +1,66 @@
import console from "node:console";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { validateAndHashStage } from "./lib/package-integrity.ts";
const root = mkdtempSync(join(tmpdir(), "wrnexus-stage-integrity-"));
const manifest = { name: "@wrnexus/probe", version: "0.7.0" };
try {
const safe = join(root, "safe");
mkdirSync(join(safe, "dist"), { recursive: true });
writeFileSync(join(safe, "dist", "index.js"), "export const safe = true;\n");
writeFileSync(join(safe, "dist", "index.d.ts"), "export declare const safe: true;\n");
const result = validateAndHashStage(safe, manifest);
if (result.files.length !== 2 || result.files.some((file) => file.sha256.length !== 64)) {
throw new Error("Safe stage did not produce deterministic SHA-256 records.");
}
const forbidden = join(root, "forbidden");
mkdirSync(forbidden);
writeFileSync(join(forbidden, ".env"), "TOKEN=secret\n");
let rejected = false;
try {
validateAndHashStage(forbidden, manifest);
} catch {
rejected = true;
}
if (!rejected) throw new Error("Secret-like stage file was not rejected.");
const temporaryShim = join(root, "temporary-shim");
mkdirSync(temporaryShim);
writeFileSync(join(temporaryShim, "focus-shims.d.ts"), "declare const Bun: any;\n");
rejected = false;
try {
validateAndHashStage(temporaryShim, manifest);
} catch {
rejected = true;
}
if (!rejected) throw new Error("Temporary typecheck shim was not rejected.");
const sourceMap = join(root, "source-map");
mkdirSync(sourceMap);
writeFileSync(join(sourceMap, "index.js.map"), "{}\n");
rejected = false;
try {
validateAndHashStage(sourceMap, manifest);
} catch {
rejected = true;
}
if (!rejected) throw new Error("Source map was not rejected.");
const leaked = join(root, "leaked-secret");
mkdirSync(leaked);
writeFileSync(join(leaked, "index.js"), 'export const key = "-----BEGIN PRIVATE KEY-----";\n');
rejected = false;
try {
validateAndHashStage(leaked, manifest);
} catch {
rejected = true;
}
if (!rejected) throw new Error("High-confidence secret content was not rejected.");
console.log("Package staging integrity probes passed.");
} finally {
rmSync(root, { recursive: true, force: true });
}
+91
View File
@@ -0,0 +1,91 @@
import console from "node:console";
import { execFileSync } from "node:child_process";
import process from "node:process";
import {
cpSync,
existsSync,
mkdtempSync,
mkdirSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const frameworkRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const root = mkdtempSync(join(tmpdir(), "wrnexus-workspace-repair-"));
function git(args) {
return execFileSync("git", args, {
cwd: root,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
}
try {
mkdirSync(join(root, "scripts"), { recursive: true });
mkdirSync(join(root, "examples", "basic-app"), { recursive: true });
cpSync(
join(frameworkRoot, "scripts", "repair-workspace.mjs"),
join(root, "scripts", "repair-workspace.mjs"),
);
writeFileSync(
join(root, ".gitignore"),
[".env", ".env.*", "!.env.example", "!.env.*.example", ""].join("\n"),
);
writeFileSync(join(root, "examples", "basic-app", ".env.example"), "TOKEN=replace-me\n");
writeFileSync(join(root, "examples", "basic-app", ".env.uat.example"), "TOKEN=replace-me\n");
git(["init", "-q"]);
git(["config", "user.email", "test@wrnexus.invalid"]);
git(["config", "user.name", "WRNexus Test"]);
git(["add", "-A"]);
git(["commit", "-qm", "baseline"]);
writeFileSync(join(root, "examples", "basic-app", ".env"), "TOKEN=keep-local\n");
writeFileSync(join(root, "examples", "basic-app", ".env.uat"), "TOKEN=keep-local-uat\n");
writeFileSync(join(root, "focus-shims.d.ts"), "declare const Bun: any;\n");
writeFileSync(join(root, "tsconfig.focus.json"), "{}\n");
git([
"add",
"-f",
"examples/basic-app/.env",
"examples/basic-app/.env.uat",
"focus-shims.d.ts",
"tsconfig.focus.json",
]);
git(["commit", "-qm", "unsafe local state"]);
execFileSync(process.execPath, [join(root, "scripts", "repair-workspace.mjs")], {
cwd: root,
stdio: "pipe",
});
if (readFileSync(join(root, "examples", "basic-app", ".env"), "utf8") !== "TOKEN=keep-local\n") {
throw new Error("Local .env value was modified or removed.");
}
if (
readFileSync(join(root, "examples", "basic-app", ".env.uat"), "utf8") !==
"TOKEN=keep-local-uat\n"
) {
throw new Error("Local .env.uat value was modified or removed.");
}
if (existsSync(join(root, "focus-shims.d.ts")) || existsSync(join(root, "tsconfig.focus.json"))) {
throw new Error("Temporary typecheck files were not removed.");
}
const tracked = git(["ls-files", "-z"]).split("\0").filter(Boolean);
const secretPattern = /(?:^|\/)(?:\.env(?:\..+)?|focus-shims\.d\.ts|tsconfig\.focus\.json)$/i;
const safeTemplate = /(?:^|\/)\.env(?:\.[^/]+)*\.(?:example|sample|template)$/i;
const forbidden = tracked.filter((path) => secretPattern.test(path) && !safeTemplate.test(path));
if (forbidden.length > 0) {
throw new Error(`Unsafe files remain tracked: ${forbidden.join(", ")}`);
}
console.log("Workspace repair regression test passed.");
} finally {
rmSync(root, { recursive: true, force: true });
}
+13 -8
View File
@@ -32,16 +32,20 @@ function walk(dir, predicate = () => true) {
const packageDirs = readdirSync(join(root, "packages"))
.filter((name) => existsSync(join(root, "packages", name, "package.json")))
.sort();
if (packageDirs.length !== 33) fail(`Expected 33 framework packages, found ${packageDirs.length}`);
else pass("33 framework packages are present");
const frameworkVersion = readJson(join(root, "package.json")).version;
if (packageDirs.length < 33)
fail(`Expected at least 33 framework packages, found ${packageDirs.length}`);
else pass(`${packageDirs.length} framework packages are present`);
for (const name of packageDirs) {
const manifest = readJson(join(root, "packages", name, "package.json"));
if (manifest.version !== "0.6.0")
fail(`packages/${name} is ${manifest.version ?? "unversioned"}`);
if (manifest.version !== frameworkVersion) {
fail(`packages/${name} is ${manifest.version ?? "unversioned"}; expected ${frameworkVersion}`);
}
}
if (!failures.some((item) => item.startsWith("packages/"))) {
pass(`All framework packages are version ${frameworkVersion}`);
}
if (!failures.some((item) => item.startsWith("packages/")))
pass("All framework packages are version 0.6.0");
for (const [label, path] of [
["root", "package.json"],
@@ -49,8 +53,9 @@ for (const [label, path] of [
["managed CAPTCHA service", "services/managed-captcha/package.json"],
]) {
const version = readJson(join(root, path)).version;
if (version !== "0.6.0") fail(`${label} version is ${version}`);
else pass(`${label} version is 0.6.0`);
if (version !== frameworkVersion)
fail(`${label} version is ${version}; expected ${frameworkVersion}`);
else pass(`${label} version is ${frameworkVersion}`);
}
for (const path of [
+245
View File
@@ -0,0 +1,245 @@
import console from "node:console";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
let passed = 0;
let failed = 0;
let warned = 0;
const failures = [];
function check(name, condition, detail = "") {
if (condition) {
passed += 1;
console.log(` ok ${name}`);
return;
}
failed += 1;
failures.push(detail ? `${name}: ${detail}` : name);
console.error(` FAIL ${name}${detail ? `${detail}` : ""}`);
}
function warn(name, detail = "") {
warned += 1;
console.warn(` warn ${name}${detail ? `${detail}` : ""}`);
}
function text(path) {
return readFileSync(join(root, path), "utf8");
}
function has(path, pattern) {
const value = text(path);
return typeof pattern === "string" ? value.includes(pattern) : pattern.test(value);
}
const packageDirs = readdirSync(join(root, "packages"), { withFileTypes: true })
.filter(
(entry) =>
entry.isDirectory() && existsSync(join(root, "packages", entry.name, "package.json")),
)
.map((entry) => entry.name);
const manifests = packageDirs
.map((dir) => ({
dir,
manifest: JSON.parse(text(`packages/${dir}/package.json`)),
}))
.filter(({ manifest }) => manifest.name?.startsWith("@wrnexus/"));
check("root version is 0.7.0", JSON.parse(text("package.json")).version === "0.7.0");
const temporaryTypecheckFiles = ["focus-shims.d.ts", "tsconfig.focus.json"].filter((path) =>
existsSync(join(root, path)),
);
const rootTsconfig = JSON.parse(text("tsconfig.json"));
const rootExcludes = new Set(rootTsconfig.exclude ?? []);
check(
"root typecheck excludes temporary focused files",
rootExcludes.has("focus-shims.d.ts") &&
rootExcludes.has("tsconfig.focus.json") &&
rootExcludes.has("**/focus-shims.d.ts") &&
rootExcludes.has("**/tsconfig.focus.json"),
"Keep the temporary focused typecheck files outside the root TypeScript program.",
);
if (temporaryTypecheckFiles.length > 0) {
warn(
"temporary focused typecheck files are local leftovers",
`${temporaryTypecheckFiles.join(", ")} will be removed by: bun run repair:workspace`,
);
}
check(
"lint and formatting ignore temporary focused files",
has("eslint.config.js", '"focus-shims.d.ts"') &&
has("eslint.config.js", '"tsconfig.focus.json"') &&
has(".prettierignore", "focus-shims.d.ts") &&
has(".prettierignore", "tsconfig.focus.json"),
"Temporary focused helpers must not create lint or formatting cascades before workspace repair.",
);
check(
"all framework package versions align",
manifests.every(({ manifest }) => manifest.version === "0.7.0"),
[...new Set(manifests.map(({ manifest }) => manifest.version))].join(", "),
);
for (const name of ["security", "cache", "image", "observability", "benchmark"]) {
check(
`@wrnexus/${name} package exists`,
existsSync(join(root, "packages", name, "src", "index.ts")),
);
}
check(
"context-aware URL sanitizer is wired into compiler",
has("packages/compiler/src/codegen.ts", "sanitizeUrlAttribute"),
);
check(
"URL security checks avoid lint-blocked control-character regexes",
has("packages/compiler/src/codegen.ts", "stripAsciiControlAndSpace") &&
has("packages/security/src/url.ts", "hasAsciiControlOrSpace") &&
has("packages/syntax/src/diagnostics.ts", "stripAsciiControlAndSpace") &&
!has("packages/compiler/src/codegen.ts", /\\u0000-\\u0020/) &&
!has("packages/security/src/url.ts", /\\u0000-\\u0020/) &&
!has("packages/syntax/src/diagnostics.ts", /\\u0000-\\u0020/),
"Use character-code checks instead of control-character regular expressions.",
);
check(
"trusted HTML requires an explicit policy",
has("packages/security/src/trusted-html.ts", "createTrustedHtml"),
);
check(
"reactive URL updates are sanitized",
has("packages/csr/src/reactive-runtime.ts", "sanitizeReactiveUrl"),
);
check(
"SSR store state uses secure serialization",
has("packages/ssr/src/store-context.ts", "serializeForHtml"),
);
check("prototype pollution keys are rejected", has("packages/security/src/object.ts", "__proto__"));
check(
"SSRF helper blocks private networks",
has("packages/security/src/fetch.ts", "isPrivateAddress"),
);
check(
"CSRF checks Origin and Fetch Metadata",
has("packages/core/src/csrf.ts", /sec-fetch-site|validateOrigin/),
);
check(
"security headers include CSP and isolation",
has("packages/core/src/headers.ts", "Origin-Agent-Cluster"),
);
check(
"request limits are automatic runtime middleware",
has("packages/dev-server/src/runtime.ts", "requestHardening"),
);
check(
"gateway enforces request limits",
has("packages/dev-server/src/gateway.ts", "GatewayRequestLimits"),
);
check(
"gateway enforces WebSocket limits",
has("packages/dev-server/src/gateway.ts", "maxQueuedMessages"),
);
check(
"realtime enforces per-room security",
has("packages/core/src/realtime.ts", "RealtimeSecurityOptions"),
);
check(
"database instrumentation detects N+1 patterns",
has("packages/db/src/performance.ts", "WRN-DB-DUPLICATE-QUERY"),
);
check(
"CSS performance audit is available",
has("packages/styles/src/audit.ts", "WRN-CSS-TRANSITION-ALL"),
);
check(
"static runtime analysis is exported",
has("packages/compiler/src/analysis.ts", "analyzeRuntimeRequirements"),
);
check(
"static pages default to zero framework JavaScript",
has("packages/dev-server/src/runtime.ts", 'navigation.mode ?? "auto"') &&
has("packages/dev-server/src/runtime.ts", "scripts.length > 0"),
);
check(
"Brotli delivery is preferred",
has("packages/dev-server/src/runtime.ts", "brotliCompressSync"),
);
check(
"Happy DOM validation events and elements use one DOM type system",
has("packages/validation/test/validation.test.ts", "type Event as HappyDOMEvent") &&
has(
"packages/validation/test/validation.test.ts",
"type HTMLInputElement as HappyDOMHTMLInputElement",
) &&
has(
"packages/validation/test/validation.test.ts",
"type HTMLFormElement as HappyDOMHTMLFormElement",
) &&
has(
"packages/validation/test/validation.test.ts",
"function windowEvent(win: Window, type: string, init?: IEventInit): HappyDOMEvent",
) &&
!has(
"packages/validation/test/validation.test.ts",
/as unknown as (?:HTMLInputElement|HTMLFormElement|HTMLElement)/,
),
"Use Happy DOM Event and element types together; do not mix them with browser DOM globals.",
);
check(
"DevToolbar security checks include CSRF",
has("packages/dev-toolbar/src/rules/security.ts", "security/missing-csrf"),
);
check(
"DevToolbar performance checks include hydration",
has("packages/dev-toolbar/src/rules/performance.ts", "performance/hydration-count"),
);
check("release migration includes 0.7.0", has("packages/cli/src/update.ts", 'version: "0.7.0"'));
check(
"21-point implementation matrix exists",
existsSync(join(root, "docs", "SECURITY-PERFORMANCE-0.7.md")),
);
check(
"production audit script exists",
existsSync(join(root, "scripts", "security-performance-audit.mjs")),
);
check(
"workspace repair command exists",
existsSync(join(root, "scripts", "repair-workspace.mjs")) &&
existsSync(join(root, "scripts", "test-workspace-repair.mjs")) &&
JSON.parse(text("package.json")).scripts?.["repair:workspace"] ===
"node scripts/repair-workspace.mjs" &&
JSON.parse(text("package.json")).scripts?.["check:workspace"] ===
"node scripts/repair-workspace.mjs --check" &&
has("scripts/release.ts", "check:workspace"),
);
check(
"security audit scans Git-tracked release files",
has("scripts/security-performance-audit.mjs", 'execFileSync("git", ["ls-files", "-z"]') &&
has("scripts/security-performance-audit.mjs", "SEC-NO-TRACKED-SECRET-FILES"),
);
check("SBOM generator exists", existsSync(join(root, "scripts", "generate-sbom.mjs")));
check(
"SBOM includes transitive bun.lock packages",
has("scripts/generate-sbom.mjs", "lock.packages"),
);
check(
"SBOM parse errors preserve their original cause",
has("scripts/generate-sbom.mjs", "{ cause: error }") &&
has("scripts/test-workspace-repair.mjs", 'import process from "node:process"'),
);
check(
"staged packages are secret-scanned and hashed",
has("scripts/publish-packages.ts", "validateAndHashStage") &&
has("scripts/publish-packages.ts", "PACKAGE-INTEGRITY.json"),
);
check("benchmark runner exists", existsSync(join(root, "scripts", "benchmark-framework.mjs")));
check("release gate formats generated UI references", has("scripts/release.ts", "--write"));
console.log(`\n${passed} passed`);
console.log(`${warned} warnings`);
console.log(`${failed} failed`);
if (failed) {
console.error("\nFailures:");
for (const failure of failures) console.error(`- ${failure}`);
process.exitCode = 1;
}