release: WRNexusJS 0.8.0
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
+243
View File
@@ -0,0 +1,243 @@
import console from "node:console";
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, join, relative, resolve } from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const require = createRequire(import.meta.url);
const componentPackages = new Set([
"auth",
"captcha",
"i18n",
"image",
"realtime",
"ui",
"uploader",
"validation",
]);
const requestedHelperFiles = {
auth: "src/helpers.ts",
captcha: "src/helpers.ts",
db: "src/helpers.ts",
encryption: "src/http.ts",
i18n: "src/index.ts",
image: "src/index.ts",
jwt: "src/helpers.ts",
realtime: "src/messages.ts",
uploader: "src/helpers.ts",
validation: "src/helpers.ts",
};
function writeIfChanged(path, source) {
if (existsSync(path) && readFileSync(path, "utf8") === source) return false;
writeFileSync(path, source, "utf8");
return true;
}
function walkFiles(directory, pattern) {
const files = [];
if (!existsSync(directory)) return files;
const visit = (current) => {
for (const entry of readdirSync(current, { withFileTypes: true })) {
const path = join(current, entry.name);
if (entry.isDirectory()) visit(path);
else if (entry.isFile() && pattern.test(entry.name)) files.push(path);
}
};
visit(directory);
return files.sort();
}
function helperIsPublic(entrySource, helperFile, main) {
if (!helperFile || helperFile === main) return true;
const relativeHelper = `./${relative(dirname(main), helperFile).replace(/\\/g, "/").replace(/\.ts$/, ".ts")}`;
const withoutExtension = relativeHelper.replace(/\.ts$/, "");
return entrySource.includes(relativeHelper) || entrySource.includes(withoutExtension);
}
const compiler = require(join(root, "editors", "vscode", "src", "compiler.cjs"));
const uiCatalog = JSON.parse(
readFileSync(join(root, "packages", "ui", "component-catalog.json"), "utf8"),
);
const uiComponentNames = new Set(uiCatalog.components.map((entry) => entry.name));
const packageDirectories = readdirSync(join(root, "packages"), { withFileTypes: true })
.filter(
(entry) =>
entry.isDirectory() && existsSync(join(root, "packages", entry.name, "package.json")),
)
.map((entry) => entry.name)
.sort();
const packages = [];
const failures = [];
let componentCount = 0;
let helperPackageCount = 0;
for (const directory of packageDirectories) {
const packageRoot = join(root, "packages", directory);
const manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
const main = String(manifest.main ?? manifest.exports?.["."] ?? "src/index.ts").replace(
/^\.\//,
"",
);
const entry = join(packageRoot, main);
const entrySource = existsSync(entry) ? readFileSync(entry, "utf8") : "";
const componentsDir = join(packageRoot, "components");
const components = existsSync(componentsDir)
? readdirSync(componentsDir)
.filter((name) => name.endsWith(".wrn"))
.sort()
: [];
const tests = walkFiles(join(packageRoot, "test"), /\.(?:test|spec)\.[cm]?[jt]s$/).map((path) =>
relative(join(packageRoot, "test"), path).replace(/\\/g, "/"),
);
const sourceFiles = walkFiles(join(packageRoot, "src"), /\.[cm]?ts$/);
const allSource = sourceFiles.map((path) => readFileSync(path, "utf8")).join("\n");
const exported = [
...allSource.matchAll(
/\bexport\s+(?:declare\s+)?(?:async\s+)?(?:function|class|const|let|var|interface|type|enum)\s+([A-Za-z_$][\w$]*)/g,
),
].map((match) => match[1]);
const helperFile = requestedHelperFiles[directory];
const hasHelperKit = helperFile
? existsSync(join(packageRoot, helperFile))
: exported.length > 0 ||
/export\s+\{/.test(allSource) ||
/export\s+\*/.test(allSource) ||
directory === "cli";
const publicHelper = helperIsPublic(entrySource, helperFile, main);
if (hasHelperKit) helperPackageCount++;
componentCount += components.length;
if (manifest.version !== "0.8.0")
failures.push(`${manifest.name}: version is ${manifest.version}`);
if (!existsSync(entry)) failures.push(`${manifest.name}: missing public entry ${main}`);
if (!existsSync(join(packageRoot, "README.md")))
failures.push(`${manifest.name}: missing README.md`);
if (!tests.length) failures.push(`${manifest.name}: missing package test`);
if (!hasHelperKit) failures.push(`${manifest.name}: no public helper/API surface found`);
if (!publicHelper) failures.push(`${manifest.name}: ${helperFile} is not exported by ${main}`);
const usedUiComponents = new Set();
const componentFailures = [];
for (const component of components) {
const file = join(componentsDir, component);
const source = readFileSync(file, "utf8");
for (const match of source.matchAll(/<([A-Z][A-Za-z0-9]*)\b/g)) {
if (uiComponentNames.has(match[1])) usedUiComponents.add(match[1]);
}
try {
compiler.compileWireFile(source);
} catch (error) {
componentFailures.push(
`${component}: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
if (componentPackages.has(directory)) {
if (!components.length)
failures.push(`${manifest.name}: component package has no .wrn components`);
if (directory !== "ui" && manifest.dependencies?.["@wrnexus/ui"] !== "workspace:*") {
failures.push(`${manifest.name}: component package must depend on @wrnexus/ui`);
}
if (directory !== "ui" && usedUiComponents.size === 0) {
failures.push(`${manifest.name}: package blocks do not compose any @wrnexus/ui component`);
}
if (directory !== "ui" && !manifest.exports?.["./plugin"]) {
failures.push(`${manifest.name}: component package must export ./plugin`);
}
}
for (const issue of componentFailures) failures.push(`${manifest.name}: ${issue}`);
packages.push({
name: manifest.name,
directory,
version: manifest.version,
kind: componentPackages.has(directory) ? "component-kit" : "helper-kit",
entry: relative(root, entry).replace(/\\/g, "/"),
helperFile: helperFile ?? null,
helperIsPublic: publicHelper,
publicExportCount: exported.length,
components,
uiComponents: [...usedUiComponents].sort(),
tests,
readme: existsSync(join(packageRoot, "README.md")),
usesUi: directory === "ui" || manifest.dependencies?.["@wrnexus/ui"] === "workspace:*",
});
}
const authSource = readdirSync(join(root, "packages", "auth", "components"))
.filter((name) => name.endsWith(".wrn"))
.map((name) => readFileSync(join(root, "packages", "auth", "components", name), "utf8"))
.join("\n");
if (/<(?:button|select|textarea)\b/.test(authSource)) {
failures.push("@wrnexus/auth: visible native controls must use @wrnexus/ui components");
}
for (const match of authSource.matchAll(/<input\b[\s\S]*?>/g)) {
if (!/\btype=(?:"hidden"|'hidden')/i.test(match[0])) {
failures.push(
"@wrnexus/auth: visible native input must use @wrnexus/ui Input/PinInput components",
);
break;
}
}
const report = {
version: "0.8.0",
summary: {
packageCount: packages.length,
helperPackageCount,
componentPackageCount: packages.filter((entry) => entry.kind === "component-kit").length,
componentCount,
failures: failures.length,
},
packages,
failures,
};
const markdown = [
"# WRNexusJS 0.8.0 Package Kits",
"",
"Every framework package has a public API/helper surface, package tests, and documentation. Packages that directly render developer-facing UI additionally provide package-owned `.wrn` blocks composed from `@wrnexus/ui`.",
"",
`- Packages: ${report.summary.packageCount}`,
`- Helper/API kits: ${report.summary.helperPackageCount}`,
`- Component kits: ${report.summary.componentPackageCount}`,
`- Package-owned components: ${report.summary.componentCount}`,
"",
"| Package | Kit | Helper/API entry | Components | UI composition | Tests |",
"|---|---|---|---:|---|---:|",
...packages.map(
(entry) =>
`| \`${entry.name}\` | ${entry.kind} | ${entry.helperFile ? `\`${entry.helperFile}\`` : `\`${entry.entry}\``} | ${entry.components.length} | ${entry.uiComponents.length ? entry.uiComponents.map((name) => `\`${name}\``).join(", ") : "—"} | ${entry.tests.length} |`,
),
"",
"## Component-kit rule",
"",
"Infrastructure-only packages remain helper/API kits and do not pull browser UI into server code. UI-facing packages own complete blocks and register them through their package plugin.",
"",
"## Security boundary for encrypted HTTP bodies",
"",
"`@wrnexus/encryption` encrypted HTTP envelopes add application-layer confidentiality, replay checks, and method/path/request binding. They do not replace HTTPS and cannot hide data from a browser user who receives the decryption key. Use them for service-to-service, native/mobile, controlled agents, or field-level protection with server-managed keys.",
"",
failures.length
? "## Failures\n\n" + failures.map((failure) => `- ${failure}`).join("\n") + "\n"
: "## Audit result\n\nAll package-kit requirements pass.\n",
].join("\n");
if (process.argv.includes("--write")) {
const reportDir = join(root, ".wrnexus", "reports");
mkdirSync(reportDir, { recursive: true });
writeIfChanged(
join(reportDir, "PACKAGE-KITS-0.8.0.json"),
`${JSON.stringify(report, null, 2)}\n`,
);
writeIfChanged(join(reportDir, "PACKAGE-KITS-0.8.0.md"), `${markdown}\n`);
}
console.log(JSON.stringify(report.summary, null, 2));
for (const failure of failures) console.error(`FAIL ${failure}`);
if (failures.length) process.exitCode = 1;
+6 -2
View File
@@ -9,6 +9,7 @@ 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 frameworkVersion = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version;
const componentSource = readFileSync(
join(root, "packages", "ui", "components", "button.wrn"),
"utf8",
@@ -55,13 +56,16 @@ for (const benchmark of benchmarks) {
const report = {
schemaVersion: 1,
frameworkVersion: "0.7.0",
frameworkVersion,
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`);
writeFileSync(
join(reportDir, `benchmark-${frameworkVersion}.json`),
`${JSON.stringify(report, null, 2)}\n`,
);
console.log(
JSON.stringify(
report.benchmarks.map(({ result }) => ({
+16 -5
View File
@@ -1,4 +1,4 @@
import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, join, relative, resolve, sep } from "node:path";
import process from "node:process";
@@ -128,7 +128,18 @@ module.exports = __load("packages/compiler/src/index.ts");
`;
const destination = join(root, "editors", "vscode", "src", "compiler.cjs");
writeFileSync(destination, output, "utf8");
process.stdout.write(
`Built ${relative(root, destination)} from ${sourceFiles.length} TypeScript modules.\n`,
);
if (process.argv.includes("--check")) {
if (!existsSync(destination) || readFileSync(destination, "utf8") !== output) {
throw new Error(
`${relative(root, destination)} is stale. Run bun run --cwd editors/vscode build and commit the result.`,
);
}
process.stdout.write(
`Verified ${relative(root, destination)} matches ${sourceFiles.length} TypeScript modules.\n`,
);
} else {
writeFileSync(destination, output, "utf8");
process.stdout.write(
`Built ${relative(root, destination)} from ${sourceFiles.length} TypeScript modules.\n`,
);
}
+31
View File
@@ -0,0 +1,31 @@
import console from "node:console";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, relative, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import process from "node:process";
const root = resolve(import.meta.dirname, "..");
const source = join(root, "editors", "vscode", "src", "extension.js");
const destination = join(root, "editors", "vscode", "src", "extension.bundle.cjs");
const check = process.argv.includes("--check");
const temporary = check ? mkdtempSync(join(tmpdir(), "wrnexus-editor-extension-")) : null;
const output = temporary ? join(temporary, "extension.bundle.cjs") : destination;
try {
const built = spawnSync(
process.env.WRNEXUS_BUN_BINARY || "bun",
["build", source, "--target=node", "--format=cjs", "--external=vscode", `--outfile=${output}`],
{ cwd: root, encoding: "utf8" },
);
if (built.status !== 0)
throw new Error(built.stderr || built.stdout || "extension bundle failed");
if (check) {
if (!existsSync(destination) || readFileSync(destination).compare(readFileSync(output)) !== 0)
throw new Error(
`${relative(root, destination)} is stale. Run bun run --cwd editors/vscode build.`,
);
console.log(`Verified ${relative(root, destination)} matches extension sources.`);
} else console.log(`Built ${relative(root, destination)}.`);
} finally {
if (temporary) rmSync(temporary, { recursive: true, force: true });
}
+30
View File
@@ -0,0 +1,30 @@
import console from "node:console";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, relative, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import process from "node:process";
const root = resolve(import.meta.dirname, "..");
const source = join(root, "packages", "language-server", "src", "server.ts");
const destination = join(root, "editors", "vscode", "src", "language-server.cjs");
const check = process.argv.includes("--check");
const temporary = check ? mkdtempSync(join(tmpdir(), "wrnexus-editor-lsp-")) : null;
const output = temporary ? join(temporary, "language-server.cjs") : destination;
try {
const built = spawnSync(
process.env.WRNEXUS_BUN_BINARY || "bun",
["build", source, "--target=node", "--format=cjs", `--outfile=${output}`],
{ cwd: root, encoding: "utf8" },
);
if (built.status !== 0) throw new Error(built.stderr || built.stdout || "LSP bundle failed");
if (check) {
if (!existsSync(destination) || readFileSync(destination).compare(readFileSync(output)) !== 0)
throw new Error(
`${relative(root, destination)} is stale. Run bun run --cwd editors/vscode build.`,
);
console.log(`Verified ${relative(root, destination)} matches the language server sources.`);
} else console.log(`Built ${relative(root, destination)}.`);
} finally {
if (temporary) rmSync(temporary, { recursive: true, force: true });
}
+31
View File
@@ -0,0 +1,31 @@
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join, relative, resolve } from "node:path";
import { diagnose, formatWrn } from "../packages/syntax/src/index.ts";
const root = resolve(import.meta.dirname, "..");
const examples = join(root, "examples");
function walk(directory: string): string[] {
return readdirSync(directory).flatMap((name) => {
if (["node_modules", ".wrnexus", "dist", "build"].includes(name)) return [];
const path = join(directory, name);
return statSync(path).isDirectory() ? walk(path) : path.endsWith(".wrn") ? [path] : [];
});
}
const failures: string[] = [];
const files = walk(examples);
for (const file of files) {
const source = readFileSync(file, "utf8");
for (const diagnostic of diagnose(source, { file, accessibility: true })) {
if (diagnostic.severity !== "info")
failures.push(`${relative(root, file)}: ${diagnostic.code} ${diagnostic.message}`);
}
const formatted = formatWrn(source);
if (formatWrn(formatted) !== formatted)
failures.push(`${relative(root, file)}: formatter is not idempotent`);
}
if (failures.length) throw new Error(`Example page validation failed:\n${failures.join("\n")}`);
console.log(
`Validated ${files.length} example .wrn pages with compiler, accessibility, and formatter checks.`,
);
+82
View File
@@ -0,0 +1,82 @@
import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import console from "node:console";
import { dirname, join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
import ts from "typescript";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const baselinePath = join(root, "docs", "public-api-0.8.json");
function flattenTargets(value) {
if (typeof value === "string") return [value];
if (Array.isArray(value)) return value.flatMap(flattenTargets);
if (value && typeof value === "object") return Object.values(value).flatMap(flattenTargets);
return [];
}
const entries = [];
for (const directory of readdirSync(join(root, "packages"), { withFileTypes: true })) {
if (!directory.isDirectory()) continue;
const packageRoot = join(root, "packages", directory.name);
const manifestPath = join(packageRoot, "package.json");
if (!existsSync(manifestPath)) continue;
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
const exportsMap =
manifest.exports && typeof manifest.exports === "object"
? manifest.exports
: { ".": manifest.main ?? "./src/index.ts" };
for (const [subpath, value] of Object.entries(exportsMap)) {
const target = flattenTargets(value).find((candidate) => /\.[cm]?[jt]sx?$/.test(candidate));
if (!target) continue;
const absolute = resolve(packageRoot, target);
if (existsSync(absolute)) entries.push({ package: manifest.name, subpath, absolute });
}
}
const config = ts.parseJsonConfigFileContent(
ts.readConfigFile(join(root, "tsconfig.json"), ts.sys.readFile).config,
ts.sys,
root,
);
const program = ts.createProgram(
[...new Set(entries.map(({ absolute }) => absolute))],
config.options,
);
const checker = program.getTypeChecker();
const packages = {};
for (const entry of entries.sort(
(left, right) =>
left.package.localeCompare(right.package) || left.subpath.localeCompare(right.subpath),
)) {
const source = program.getSourceFile(entry.absolute);
if (!source)
throw new Error(`Public API entry was not loaded: ${relative(root, entry.absolute)}`);
const symbol = checker.getSymbolAtLocation(source);
const names = symbol
? checker
.getExportsOfModule(symbol)
.map((item) => item.getName())
.filter((name) => name !== "__esModule")
.sort()
: [];
(packages[entry.package] ??= {})[entry.subpath] = names;
}
const report = { schemaVersion: 1, releaseLine: "0.8", packages };
const output = `${JSON.stringify(report, null, 2)}\n`;
if (process.argv.includes("--write")) {
writeFileSync(baselinePath, output, "utf8");
console.log(`Wrote ${relative(root, baselinePath)}`);
} else {
if (!existsSync(baselinePath)) {
throw new Error("Public API baseline is missing. Run `bun run generate:public-api`.");
}
const expected = readFileSync(baselinePath, "utf8");
if (expected !== output) {
throw new Error(
"Public API changed. Review compatibility, then run `bun run generate:public-api` intentionally.",
);
}
console.log(`Public API baseline matches ${Object.keys(packages).length} packages.`);
}
+41
View File
@@ -0,0 +1,41 @@
import { existsSync, readFileSync } from "node:fs";
import console from "node:console";
import { resolve } from "node:path";
import process from "node:process";
const root = resolve(import.meta.dirname, "..");
const mapPath = resolve(root, "docs/SECURITY-ASVS-5.md");
const source = readFileSync(mapPath, "utf8");
const requiredIds = [
"v5.0.0-1.1.2",
"v5.0.0-1.2.1",
"v5.0.0-1.2.3",
"v5.0.0-1.2.4",
"v5.0.0-1.3.6",
"v5.0.0-3.3.1",
"v5.0.0-3.3.2",
"v5.0.0-3.3.4",
"v5.0.0-3.4.1",
"v5.0.0-3.4.2",
"v5.0.0-3.4.6",
"v5.0.0-3.5.1",
"v5.0.0-3.7.2",
"v5.0.0-16.2.5",
"v5.0.0-16.3.1",
"v5.0.0-16.3.2",
];
const missingIds = requiredIds.filter((id) => !source.includes(`\`${id}\``));
const evidence = [...source.matchAll(/`((?:packages|scripts)\/[\w./-]+)`/g)].map(
(match) => match[1],
);
const missingEvidence = evidence.filter((path) => !existsSync(resolve(root, path)));
if (missingIds.length || missingEvidence.length) {
if (missingIds.length) console.error(`Missing ASVS mappings: ${missingIds.join(", ")}`);
if (missingEvidence.length)
console.error(`Missing security evidence: ${missingEvidence.join(", ")}`);
process.exit(1);
}
console.log(
`Security map verified: ${requiredIds.length} ASVS requirements, ${evidence.length} evidence files.`,
);
+34
View File
@@ -0,0 +1,34 @@
import console from "node:console";
import { createHash } from "node:crypto";
import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import { dirname, 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 uiRoot = join(root, "packages", "ui");
const baseline = join(root, "docs", "ui-visual-contract-0.8.json");
const files = [
join(uiRoot, "ui.css"),
...readdirSync(join(uiRoot, "components"))
.filter((file) => file.endsWith(".wrn"))
.map((file) => join(uiRoot, "components", file)),
].sort();
const artifacts = Object.fromEntries(
files.map((file) => [
relative(root, file).replace(/\\/g, "/"),
createHash("sha256").update(readFileSync(file)).digest("hex"),
]),
);
const output = `${JSON.stringify({ schemaVersion: 1, releaseLine: "0.8", artifacts }, null, 2)}\n`;
if (process.argv.includes("--write")) {
writeFileSync(baseline, output, "utf8");
console.log(`Wrote ${relative(root, baseline)}`);
} else {
if (!existsSync(baseline) || readFileSync(baseline, "utf8") !== output) {
throw new Error(
"UI visual contract changed. Review rendered components, then run `bun run generate:ui-visual`.",
);
}
console.log(`UI visual contract matches ${files.length} CSS/component artifacts.`);
}
+27
View File
@@ -0,0 +1,27 @@
import { afterAll } from "bun:test";
const originalWarn = console.warn;
const warnings: string[] = [];
const allowed = (process.env.WRNEXUS_TEST_WARNING_ALLOWLIST ?? "")
.split(",")
.map((value) => value.trim())
.filter(Boolean);
console.warn = (...values: unknown[]) => {
const message = values
.map((value) => (typeof value === "string" ? value : JSON.stringify(value)))
.join(" ");
if (!allowed.some((pattern) => message.includes(pattern))) warnings.push(message);
originalWarn(...values);
};
afterAll(() => {
console.warn = originalWarn;
if (warnings.length) {
throw new Error(
`WRN-TEST-UNEXPECTED-WARNING: ${warnings.length} warning(s) emitted:\n${warnings
.map((warning) => `- ${warning}`)
.join("\n")}`,
);
}
});
+4 -2
View File
@@ -1,6 +1,6 @@
import console from "node:console";
import { createHash } from "node:crypto";
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
import { mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
@@ -107,6 +107,8 @@ const document = {
},
components,
};
const file = join(root, `SBOM-${version}.cdx.json`);
const reportDir = join(root, ".wrnexus", "reports");
mkdirSync(reportDir, { recursive: true });
const file = join(reportDir, `SBOM-${version}.cdx.json`);
writeFileSync(file, `${JSON.stringify(document, null, 2)}\n`);
console.log(`Generated ${file} with ${components.length} workspace and transitive components.`);
+64 -2
View File
@@ -1,5 +1,5 @@
import { createHash } from "node:crypto";
import { readdirSync, readFileSync } from "node:fs";
import { existsSync, readdirSync, readFileSync } from "node:fs";
import { basename, join, relative } from "node:path";
export interface StagedFileIntegrity {
@@ -17,7 +17,7 @@ export interface StagedPackageIntegrity {
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/;
/-----BEGIN ((?:RSA |EC |OPENSSH )?PRIVATE KEY)-----\r?\n[A-Za-z0-9+/=\r\n]{80,}\r?\n-----END \1-----|\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[] = [];
@@ -32,11 +32,73 @@ function listFiles(root: string): string[] {
});
}
function manifestTargets(value: unknown): string[] {
if (typeof value === "string") return [value];
if (!value || typeof value !== "object") return [];
return Object.values(value).flatMap(manifestTargets);
}
export function validateStagedManifest(stage: string, manifest: Record<string, unknown>): void {
const name = String(manifest.name ?? "unknown package");
const requiredStrings = ["name", "version", "description", "license", "main", "types"];
for (const field of requiredStrings) {
if (typeof manifest[field] !== "string" || !String(manifest[field]).trim()) {
throw new Error(`${name} staged manifest requires a non-empty ${field}.`);
}
}
if (!/^@wrnexus\/[a-z0-9-]+$/.test(name)) throw new Error(`${name} has an invalid package name.`);
if (manifest.private !== undefined) throw new Error(`${name} staged manifest must omit private.`);
if ((manifest.publishConfig as any)?.registry !== "https://registry.npmjs.org/") {
throw new Error(`${name} staged manifest has an unexpected registry.`);
}
if (!["restricted", "public"].includes(String((manifest.publishConfig as any)?.access))) {
throw new Error(`${name} staged manifest requires explicit public or restricted access.`);
}
if ((manifest.engines as any)?.bun !== ">=1.3.0") {
throw new Error(`${name} staged manifest requires the supported Bun engine.`);
}
for (const field of ["repository", "homepage", "bugs", "keywords", "files", "exports"]) {
if (manifest[field] === undefined)
throw new Error(`${name} staged manifest requires ${field}.`);
}
for (const ranges of [
manifest.dependencies,
manifest.optionalDependencies,
manifest.peerDependencies,
]) {
if (!ranges || typeof ranges !== "object") continue;
for (const [dependency, range] of Object.entries(ranges)) {
if (String(range).startsWith("workspace:")) {
throw new Error(`${name} leaked workspace range for ${dependency}.`);
}
}
}
const targets = [
...manifestTargets(manifest.main),
...manifestTargets(manifest.module),
...manifestTargets(manifest.types),
...manifestTargets(manifest.bin),
...manifestTargets(manifest.exports),
];
for (const target of new Set(targets)) {
if (!target.startsWith("./")) throw new Error(`${name} has unsafe package target ${target}.`);
const normalized = target.slice(2);
const concrete = normalized.includes("*")
? normalized.slice(0, normalized.indexOf("*"))
: normalized;
if (!existsSync(join(stage, concrete))) {
throw new Error(`${name} package target does not exist: ${target}.`);
}
}
}
export function validateAndHashStage(
stage: string,
manifest: Record<string, unknown>,
): StagedPackageIntegrity {
const name = String(manifest.name ?? "unknown package");
validateStagedManifest(stage, manifest);
const files = listFiles(stage);
if (!files.length) throw new Error(`${name} staged no files.`);
const integrity: StagedFileIntegrity[] = [];
+12 -1
View File
@@ -39,6 +39,8 @@ const REGISTRY = "https://registry.npmjs.org/";
// npm org to exist and be on a paid plan (private scoped packages need Teams).
const ACCESS = process.env.WRNEXUS_NPM_ACCESS === "public" ? "public" : "restricted";
const LICENSE = "MIT";
const REPOSITORY = "https://git.workroot.in/WorkRoot/WRNexusJS.git";
const HOMEPAGE = "https://wrnexusjs.dev";
/** Extra (non-code) files each package must ship, relative to the package root. */
const ASSETS: Record<string, string[]> = {
@@ -171,6 +173,15 @@ function publishManifest(
type: "module",
description: m.description ?? `${m.name} — part of the WrNexus framework.`,
license: LICENSE,
repository: {
type: "git",
url: REPOSITORY,
directory: `packages/${String(m.name).replace("@wrnexus/", "")}`,
},
homepage: `${HOMEPAGE}/packages/${String(m.name).replace("@wrnexus/", "")}`,
bugs: { url: `${REPOSITORY.replace(/\.git$/, "")}/issues` },
keywords: ["wrnexus", "bun", "typescript", String(m.name).replace("@wrnexus/", "")],
sideEffects: m.sideEffects ?? false,
main: m.main ? js(m.main) : "./dist/index.js",
module: m.main ? js(m.main) : "./dist/index.js",
types: m.main ? dts(m.main) : "./dist/index.d.ts",
@@ -215,7 +226,7 @@ function publishManifest(
}
}
const files = new Set(["dist"]);
const files = new Set(["dist", "README.md"]);
for (const a of packageAssets(m)) files.add(a);
out.files = [...files];
+3 -2
View File
@@ -225,12 +225,13 @@ function prepare(all: PackageInfo[], version: string) {
run(process.execPath, ["run", "format"]);
run(process.execPath, ["run", "check:workspace"]);
run(process.execPath, ["run", "validate:0.7"]);
run(process.execPath, ["run", "validate:0.8"]);
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"]);
run(process.execPath, ["run", "test:staged-consumers"]);
validateStaging(all, version);
console.log(
`\n✓ Release ${version} is prepared. Review changes, commit and push the framework repository, then run: bun run release:private\n`,
@@ -302,7 +303,7 @@ 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", "validate:0.8"]);
run(process.execPath, ["run", "security:framework"]);
requireCleanAndPushed(root, "Framework");
requireCleanAndPushed(docsRoot, "Docs");
+25 -15
View File
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
import process from "node:process";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const frameworkVersion = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version;
const issues = [];
const warnings = [];
const checks = [];
@@ -59,8 +60,8 @@ const manifests = trackedFiles
.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.",
manifests.every(({ value }) => value.version === frameworkVersion),
`Every @wrnexus package must use version ${frameworkVersion}.`,
);
addCheck(
"SEC-PRIVATE-PUBLISH",
@@ -154,12 +155,19 @@ addCheck(
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.`,
);
const runtimeBudgets = {
"reactive-runtime.ts": 150_000,
"nav-runtime.ts": 25_000,
"realtime-runtime.ts": 15_000,
};
for (const [file, budget] of Object.entries(runtimeBudgets)) {
const bytes = statSync(join(root, "packages", "csr", "src", file)).size;
addCheck(
`PERF-RUNTIME-SIZE-${file.replace(/-runtime\.ts$/, "").toUpperCase()}`,
bytes <= budget,
`${file} is ${bytes} bytes (budget ${budget}).`,
);
}
addCheck(
"PERF-ZERO-JS-ANALYSIS",
existsSync(join(root, "packages", "compiler", "src", "analysis.ts")),
@@ -185,19 +193,21 @@ addCheck(
const report = {
schemaVersion: 2,
frameworkVersion: "0.7.0",
frameworkVersion,
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",
);
if (process.argv.includes("--write")) {
const reportDir = join(root, ".wrnexus", "reports");
mkdirSync(reportDir, { recursive: true });
writeFileSync(
join(reportDir, `security-performance-${frameworkVersion}.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}`);
+32 -3
View File
@@ -5,7 +5,23 @@ 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" };
const manifest = {
name: "@wrnexus/probe",
version: "0.8.0",
description: "Integrity probe.",
license: "MIT",
main: "./dist/index.js",
module: "./dist/index.js",
types: "./dist/index.d.ts",
exports: { ".": { import: "./dist/index.js", types: "./dist/index.d.ts" } },
files: ["dist", "README.md"],
repository: { type: "git", url: "https://example.test/repository.git" },
homepage: "https://example.test",
bugs: { url: "https://example.test/issues" },
keywords: ["probe"],
engines: { bun: ">=1.3.0" },
publishConfig: { registry: "https://registry.npmjs.org/", access: "restricted" },
};
try {
const safe = join(root, "safe");
mkdirSync(join(safe, "dist"), { recursive: true });
@@ -50,8 +66,12 @@ try {
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');
mkdirSync(join(leaked, "dist"), { recursive: true });
writeFileSync(
join(leaked, "dist", "index.js"),
`-----BEGIN PRIVATE KEY-----\n${"A".repeat(64)}\n${"B".repeat(64)}\n-----END PRIVATE KEY-----\n`,
);
writeFileSync(join(leaked, "dist", "index.d.ts"), "export {};\n");
rejected = false;
try {
validateAndHashStage(leaked, manifest);
@@ -60,6 +80,15 @@ try {
}
if (!rejected) throw new Error("High-confidence secret content was not rejected.");
const keyHandlingSource = join(root, "key-handling-source");
mkdirSync(join(keyHandlingSource, "dist"), { recursive: true });
writeFileSync(
join(keyHandlingSource, "dist", "index.js"),
'export const header = "-----BEGIN PRIVATE KEY-----\\n" + generatedBytes;\n',
);
writeFileSync(join(keyHandlingSource, "dist", "index.d.ts"), "export {};\n");
validateAndHashStage(keyHandlingSource, manifest);
console.log("Package staging integrity probes passed.");
} finally {
rmSync(root, { recursive: true, force: true });
+228
View File
@@ -0,0 +1,228 @@
/* global FormData, Headers, console */
import assert from "node:assert/strict";
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
createKeyring,
createMemoryReplayStore,
encryptHttpBody,
decryptHttpBody,
createEncryptedRequest,
encryptResponse,
decryptEncryptedResponse,
} from "../packages/encryption/src/index.ts";
import {
createAccessToken,
createRefreshToken,
verifyAccessToken,
verifyRefreshToken,
hasScopes,
jwtCookie,
createTokenPair,
readJwtCookie,
} from "../packages/jwt/src/index.ts";
import { createDb, createRepository, batch, databaseHealth } from "../packages/db/src/index.ts";
import {
loadLocales,
resolveI18n,
makeT,
resolveLang,
renderI18nData,
} from "../packages/i18n/src/index.ts";
import {
createPicture,
createBlurPlaceholder,
imageCacheKey,
} from "../packages/image/src/index.ts";
import {
createRealtimeMessage,
parseRealtimeMessage,
roomMemberSummary,
} from "../packages/realtime/src/index.ts";
import { captchaFields, captchaHeaders, captchaTokenFrom } from "../packages/captcha/src/index.ts";
import { uploaderAttributes, formatFileSize } from "../packages/uploader/src/index.ts";
import { v, parseOrThrow, validationSummary } from "../packages/validation/src/index.ts";
import { authRoute, authFailure } from "../packages/auth/src/index.ts";
const keyring = createKeyring([
{ id: "active", secret: "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA=", active: true },
]);
const replayStore = createMemoryReplayStore(() => 1_000);
const envelope = await encryptHttpBody(
{ value: 42 },
{
keyring,
method: "POST",
url: "https://example.test/api/items",
requestId: "request-1",
timestamp: 1_000,
},
);
const decrypted = await decryptHttpBody(envelope, {
keyring,
method: "POST",
url: "https://example.test/api/items",
replayStore,
now: () => 1_000,
});
assert.deepEqual(decrypted.body, { value: 42 });
await assert.rejects(
() =>
decryptHttpBody(envelope, {
keyring,
method: "POST",
url: "https://example.test/api/items",
replayStore,
now: () => 1_000,
}),
/REPLAY/,
);
await assert.rejects(
() =>
decryptHttpBody(envelope, {
keyring,
method: "GET",
url: "https://example.test/api/items",
now: () => 1_000,
}),
/CONTEXT/,
);
const encryptedRequest = await createEncryptedRequest(
"https://example.test/api/items",
{ value: 42 },
{ keyring, method: "POST", requestId: "request-2" },
);
const encryptedResponse = await encryptResponse({ ok: true }, encryptedRequest, { keyring });
assert.equal(
(await decryptEncryptedResponse(encryptedResponse, encryptedRequest, { keyring })).body.ok,
true,
);
const secret = "a-secure-jwt-secret-for-package-kit-tests";
const access = await createAccessToken("user-1", secret, {
scopes: ["read", "write"],
now: 100,
expiresIn: 60,
});
const refresh = await createRefreshToken("user-1", secret, {
family: "family-1",
now: 100,
expiresIn: 600,
});
const accessClaims = await verifyAccessToken(access, secret, { now: 120 });
const refreshClaims = await verifyRefreshToken(refresh, secret, { now: 120 });
assert.equal(accessClaims.sub, "user-1");
assert.equal(refreshClaims.type, "refresh");
assert.equal(hasScopes(accessClaims, ["read", "write"]), true);
assert.match(jwtCookie(access), /^__Host-wrn_token=/);
assert.equal(readJwtCookie(`__Host-wrn_token=${access}`), access);
const tokenPair = await createTokenPair("user-1", {
accessSecret: secret,
accessOptions: { now: 100 },
refreshOptions: { now: 100 },
});
assert.equal((await verifyAccessToken(tokenPair.accessToken, secret, { now: 120 })).sub, "user-1");
const queries = [];
const driver = {
dialect: "sqlite",
async query(sql, params = []) {
queries.push({ sql, params });
if (/COUNT/.test(sql)) return [{ count: 2 }];
if (/SELECT 1 AS healthy/.test(sql)) return [{ healthy: 1 }];
return [{ id: 1, name: "One" }];
},
async exec(sql, params = []) {
queries.push({ sql, params });
return { changes: 1, lastInsertId: 1 };
},
async transaction(fn) {
return fn(this);
},
close() {},
};
const db = createDb(driver);
const repository = createRepository(db, { table: "items", allowedColumns: ["name"] });
assert.equal((await repository.find(1)).name, "One");
await repository.create({ name: "Two" });
await repository.update(1, { name: "Changed" });
assert.equal(await repository.count(), 2);
assert.deepEqual(batch([1, 2, 3, 4, 5], 2), [[1, 2], [3, 4], [5]]);
assert.equal((await databaseHealth(db)).ok, true);
assert.ok(queries.some((entry) => /INSERT INTO items/.test(entry.sql)));
assert.throws(() => batch([1, 2], Number.NaN), /finite/);
const localeDir = mkdtempSync(join(tmpdir(), "wrn-i18n-"));
try {
writeFileSync(join(localeDir, "en.json"), JSON.stringify({ common: { hello: "Hello {name}" } }));
mkdirSync(join(localeDir, "fr"));
writeFileSync(join(localeDir, "fr", "common.json"), JSON.stringify({ hello: "Bonjour {name}" }));
const i18n = resolveI18n(loadLocales(localeDir, { strict: true }), {
default: "en",
locales: ["en", "fr"],
});
assert.equal(makeT(i18n, "fr")("common.hello", { name: "Ajay" }), "Bonjour Ajay");
assert.equal(resolveLang(i18n, undefined, "fr;q=0.9,en;q=0.8"), "fr");
assert.equal(resolveLang(i18n, undefined, "*"), "en");
assert.match(renderI18nData(i18n, "fr"), /Bonjour/);
} finally {
rmSync(localeDir, { recursive: true, force: true });
}
const picture = createPicture({
src: "/hero.jpg",
alt: "Hero",
width: 1200,
height: 630,
widths: [480, 768, 1200],
formats: ["avif", "webp"],
});
assert.equal(picture.sources.length, 2);
assert.match(createBlurPlaceholder(), /^data:image\/svg\+xml/);
assert.equal(
imageCacheKey({ src: "/hero.jpg", width: 480 }),
imageCacheKey({ src: "/hero.jpg", width: 480 }),
);
const message = createRealtimeMessage({
type: "message",
room: "support",
data: { text: "Hello" },
});
assert.equal(
parseRealtimeMessage(JSON.stringify(message), { room: "support", allowedTypes: ["message"] })
.room,
"support",
);
assert.throws(
() => parseRealtimeMessage(JSON.stringify(message), { room: "other" }),
/does not match/,
);
assert.deepEqual(
roomMemberSummary([
{ userId: "1", status: "online" },
{ userId: "2", status: "away" },
]),
{ total: 2, online: 1, away: 1, busy: 0 },
);
const form = new FormData();
form.set("wrn-captcha-response", "token");
assert.equal(captchaTokenFrom(form), "token");
assert.deepEqual(captchaFields("token"), { "wrn-captcha-response": "token" });
assert.equal(new Headers(captchaHeaders("token")).get("x-wrn-captcha-token"), "token");
assert.equal(uploaderAttributes({ store: "public", multiple: true })["data-uploader"], "public");
assert.match(formatFileSize(1024), /KB/);
const schema = v.object({ email: v.string().email() });
assert.deepEqual(parseOrThrow(schema, { email: "user@example.com" }), {
email: "user@example.com",
});
assert.deepEqual(validationSummary({ email: "Invalid" }), [{ field: "email", message: "Invalid" }]);
assert.equal(authRoute("signIn", { basePath: "/auth" }), "/auth/sign-in");
assert.equal((await authFailure("invalid", "Invalid").json()).ok, false);
console.log("Package kit runtime probes passed.");
+147
View File
@@ -0,0 +1,147 @@
import console from "node:console";
import {
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
readdirSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import process from "node:process";
const root = resolve(import.meta.dirname, "..");
const stageRoot = join(root, ".publish");
const bun = process.env.WRNEXUS_BUN_BINARY || "bun";
const npmCli = join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
if (!existsSync(npmCli)) throw new Error(`Unable to locate the npm CLI at ${npmCli}.`);
const integrityPath = join(stageRoot, "PACKAGE-INTEGRITY.json");
if (!existsSync(integrityPath)) {
throw new Error("No staged packages found. Run the package staging command first.");
}
const integrity = JSON.parse(readFileSync(integrityPath, "utf8"));
const expectedPackageNames = new Set(
(Array.isArray(integrity.packages) ? integrity.packages : []).map((entry) => entry.name),
);
const packages = readdirSync(stageRoot, { withFileTypes: true })
.filter((entry) => entry.isDirectory() && existsSync(join(stageRoot, entry.name, "package.json")))
.map((entry) => ({
directory: entry.name,
manifest: JSON.parse(readFileSync(join(stageRoot, entry.name, "package.json"), "utf8")),
}))
.sort((left, right) => left.manifest.name.localeCompare(right.manifest.name));
const stagedPackageNames = new Set(packages.map((pkg) => pkg.manifest.name));
const missingPackages = [...expectedPackageNames].filter((name) => !stagedPackageNames.has(name));
const unexpectedPackages = [...stagedPackageNames].filter(
(name) => !expectedPackageNames.has(name),
);
if (
expectedPackageNames.size === 0 ||
packages.length !== expectedPackageNames.size ||
missingPackages.length > 0 ||
unexpectedPackages.length > 0
) {
throw new Error(
`Staged package set does not match PACKAGE-INTEGRITY.json (expected ${expectedPackageNames.size}, received ${packages.length}, missing: ${missingPackages.join(", ") || "none"}, unexpected: ${unexpectedPackages.join(", ") || "none"}).`,
);
}
const consumer = mkdtempSync(join(tmpdir(), "wrnexus-staged-consumer-"));
try {
const tarballRoot = join(consumer, "tarballs");
mkdirSync(tarballRoot, { recursive: true });
const dependencies = {};
for (const pkg of packages) {
const packed = spawnSync(
process.execPath,
[npmCli, "pack", join(stageRoot, pkg.directory), "--pack-destination", tarballRoot, "--json"],
{ cwd: consumer, encoding: "utf8" },
);
if (packed.status !== 0) {
throw new Error(
`Unable to pack ${pkg.manifest.name}:\n${packed.error?.message || packed.stderr || packed.stdout || `exit ${packed.status}`}`,
);
}
const result = JSON.parse(packed.stdout);
const filename = result[0]?.filename;
if (typeof filename !== "string") {
throw new Error(`npm pack returned no tarball for ${pkg.manifest.name}.`);
}
dependencies[pkg.manifest.name] = `file:${join(tarballRoot, filename).replace(/\\/g, "/")}`;
}
writeFileSync(
join(consumer, "package.json"),
JSON.stringify(
{ name: "wrnexus-staged-consumer", private: true, type: "module", dependencies },
null,
2,
) + "\n",
);
const install = spawnSync(
process.execPath,
[npmCli, "install", "--ignore-scripts", "--no-audit", "--no-fund"],
{
cwd: consumer,
encoding: "utf8",
env: { ...process.env, NO_COLOR: "1" },
},
);
if (install.status !== 0) {
throw new Error(
`Unable to install staged package tarballs:\n${install.stderr || install.stdout}`,
);
}
const importable = packages.filter((pkg) => pkg.manifest.name !== "@wrnexus/cli");
writeFileSync(
join(consumer, "probe.mjs"),
`${importable
.map(
(pkg) =>
`if (!await import(${JSON.stringify(pkg.manifest.name)})) throw new Error(${JSON.stringify(`Unable to import ${pkg.manifest.name}`)});`,
)
.join(
"\n",
)}\nconsole.log(${JSON.stringify(`Imported ${importable.length} staged package roots.`)});\n`,
);
const probe = spawnSync(bun, ["probe.mjs"], {
cwd: consumer,
encoding: "utf8",
env: { ...process.env, NO_COLOR: "1" },
});
if (probe.status !== 0)
throw new Error(`Staged package import probe failed:\n${probe.stderr || probe.stdout}`);
if (probe.stdout) process.stdout.write(probe.stdout);
writeFileSync(
join(consumer, "browser-probe.js"),
'import "@wrnexus/csr";\nimport "@wrnexus/reactive";\n',
);
const browser = spawnSync(
bun,
["build", "browser-probe.js", "--target=browser", "--outfile=browser-probe.bundle.js"],
{ cwd: consumer, encoding: "utf8", env: { ...process.env, NO_COLOR: "1" } },
);
if (browser.status !== 0 || !existsSync(join(consumer, "browser-probe.bundle.js"))) {
throw new Error(`Staged browser package build failed:\n${browser.stderr || browser.stdout}`);
}
const cli = spawnSync(
bun,
[join(consumer, "node_modules", "@wrnexus", "cli", "dist", "index.js"), "--help"],
{ cwd: consumer, encoding: "utf8", env: { ...process.env, NO_COLOR: "1" } },
);
if (cli.status !== 0 || !/wrnexus/i.test(`${cli.stdout}\n${cli.stderr}`)) {
throw new Error(`Staged CLI smoke test failed:\n${cli.stderr || cli.stdout}`);
}
console.log(
"Staged package tarballs, browser runtime bundle, and CLI passed their isolated consumer smoke tests.",
);
} finally {
rmSync(consumer, { recursive: true, force: true });
}
-3
View File
@@ -70,9 +70,6 @@ for (const path of [
"packages/csr/src/server-client.ts",
"packages/ssr/src/store-context.ts",
"packages/ssr/src/rpc.ts",
"UPGRADE-0.6.0.md",
"ROLLBACK-0.6.0.md",
"RELEASE_NOTES-0.6.0.md",
]) {
if (!existsSync(join(root, path))) fail(`Missing required v0.6 file: ${path}`);
}
+7 -2
View File
@@ -48,7 +48,12 @@ const manifests = packageDirs
}))
.filter(({ manifest }) => manifest.name?.startsWith("@wrnexus/"));
check("root version is 0.7.0", JSON.parse(text("package.json")).version === "0.7.0");
const rootVersion = JSON.parse(text("package.json")).version;
check(
"root version is compatible with the 0.7 security foundation",
/^0\.(?:7|8)\./.test(rootVersion),
rootVersion,
);
const temporaryTypecheckFiles = ["focus-shims.d.ts", "tsconfig.focus.json"].filter((path) =>
existsSync(join(root, path)),
);
@@ -78,7 +83,7 @@ check(
);
check(
"all framework package versions align",
manifests.every(({ manifest }) => manifest.version === "0.7.0"),
manifests.every(({ manifest }) => manifest.version === rootVersion),
[...new Set(manifests.map(({ manifest }) => manifest.version))].join(", "),
);
for (const name of ["security", "cache", "image", "observability", "benchmark"]) {
+236
View File
@@ -0,0 +1,236 @@
import console from "node:console";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
let passed = 0;
let failed = 0;
const failures = [];
function check(name, condition, detail = "") {
if (condition) {
passed++;
console.log(` ok ${name}`);
return;
}
failed++;
failures.push(detail ? `${name}: ${detail}` : name);
console.error(` FAIL ${name}${detail ? `${detail}` : ""}`);
}
function text(path) {
return readFileSync(join(root, path), "utf8");
}
function has(path, value) {
const source = text(path);
return typeof value === "string" ? source.includes(value) : value.test(source);
}
const rootManifest = JSON.parse(text("package.json"));
check(
"repository governance documents exist",
["LICENSE", "SECURITY.md", "CONTRIBUTING.md", "CHANGELOG.md", "CODE_OF_CONDUCT.md"].every(
(file) => existsSync(join(root, file)),
),
);
const packageManifests = readdirSync(join(root, "packages"), { withFileTypes: true })
.filter(
(entry) =>
entry.isDirectory() && existsSync(join(root, "packages", entry.name, "package.json")),
)
.map((entry) => JSON.parse(text(`packages/${entry.name}/package.json`)));
const workspaceManifests = ["packages", "examples", "services"].flatMap((directory) =>
readdirSync(join(root, directory), { withFileTypes: true })
.filter(
(entry) =>
entry.isDirectory() && existsSync(join(root, directory, entry.name, "package.json")),
)
.map((entry) => JSON.parse(text(`${directory}/${entry.name}/package.json`))),
);
check(
"package manifests avoid floating latest dependency ranges",
![rootManifest, ...workspaceManifests].some((manifest) =>
[manifest.dependencies, manifest.devDependencies, manifest.peerDependencies].some((group) =>
Object.values(group ?? {}).includes("latest"),
),
),
);
check("root version is 0.8.0", rootManifest.version === "0.8.0");
check(
"all framework packages use 0.8.0",
packageManifests.every((manifest) => manifest.version === "0.8.0"),
);
check(
"standalone realtime package exists",
existsSync(join(root, "packages/realtime/src/index.ts")) &&
existsSync(join(root, "packages/realtime/components/RealtimeRoom.wrn")),
);
check(
"auth provides helper and UI block kits",
existsSync(join(root, "packages/auth/src/helpers.ts")) &&
existsSync(join(root, "packages/auth/components/AuthShell.wrn")) &&
has("packages/auth/package.json", '"@wrnexus/ui": "workspace:*"'),
);
check(
"captcha provides helper and UI wrapper kits",
existsSync(join(root, "packages/captcha/src/helpers.ts")) &&
existsSync(join(root, "packages/captcha/components/CaptchaField.wrn")),
);
check(
"database repository helpers exist",
has("packages/db/src/helpers.ts", "createRepository") &&
has("packages/db/src/helpers.ts", "retryTransaction"),
);
check(
"database repositories use dialect-aware placeholders",
has("packages/db/src/helpers.ts", 'dialect === "postgres" ? `$${index}` : "?"') &&
has("packages/db/test/helpers.test.ts", "VALUES ($1)"),
);
check(
"encrypted HTTP envelope is context and replay bound",
has("packages/encryption/src/http.ts", "WRN-ENCRYPTION-HTTP-REPLAY") &&
has("packages/encryption/src/http.ts", "payload.path !== normalizePath"),
);
check(
"encrypted responses are request-id bound and application errors propagate",
has("packages/encryption/src/http.ts", "expectedRequestId: requestId") &&
has("packages/encryption/src/http.ts", "const response = await next();"),
);
check(
"encryption documentation preserves HTTPS boundary",
has("packages/encryption/README.md", /TLS|HTTPS/) &&
has("packages/encryption/README.md", /browser|end user/i),
);
check(
"JWT access, refresh, scope, cookie, and pair helpers exist",
[
"createAccessToken",
"createRefreshToken",
"requireScopes",
"jwtCookie",
"readJwtCookie",
"createTokenPair",
].every((name) => has("packages/jwt/src/helpers.ts", name)),
);
check(
"i18n supports nested locales and quality negotiation",
has("packages/i18n/src/index.ts", "localeFiles") &&
has("packages/i18n/src/index.ts", "parseAcceptLanguage"),
);
check(
"i18n safely resolves namespace collisions and wildcard language ranges",
has("packages/i18n/src/index.ts", 'tag?.trim() === "*"') &&
has("packages/i18n/test/package-kit.test.ts", "primitive namespace collisions"),
);
check(
"i18n runtime data is injected into rendered documents",
has("packages/dev-server/src/runtime.ts", "renderI18nData(deps.i18n, language)") &&
has("packages/dev-server/src/runtime.ts", "deps.i18n.cookie.name"),
);
check(
"image package provides picture, loaders, placeholder, and preload helpers",
["createPicture", "createCdnImageLoader", "createBlurPlaceholder", "imagePreload"].every((name) =>
has("packages/image/src/index.ts", name),
),
);
check(
"image helpers validate finite dimensions and preserve URL fragments",
has("packages/image/src/index.ts", "Image width bounds must be finite") &&
has("packages/image/test/package-kit.test.ts", "URL fragments"),
);
check(
"realtime messages are size, room, type, and payload bounded",
has("packages/realtime/src/messages.ts", "maxBytes") &&
has("packages/realtime/src/messages.ts", "Unsafe realtime payload key"),
);
check(
"auth shell uses statically discoverable Tailwind width classes",
!has("packages/auth/components/AuthShell.wrn", "max-w-{maxWidth}") &&
has("packages/auth/components/AuthShell.wrn", "class:max-w-md"),
);
check(
"uploader package provides UI blocks and helpers",
existsSync(join(root, "packages/uploader/components/UploadDropzone.wrn")) &&
existsSync(join(root, "packages/uploader/src/helpers.ts")),
);
check(
"validation package provides UI blocks and helpers",
existsSync(join(root, "packages/validation/components/ValidationSummary.wrn")) &&
existsSync(join(root, "packages/validation/src/helpers.ts")),
);
check(
"validation schemas infer helper output types",
has("packages/validation/src/index.ts", "export type InferSchema") &&
has("packages/validation/src/helpers.ts", "schema: ObjectSchema<T>") &&
has("packages/validation/test/helpers.test.ts", "const email: string = value.email"),
);
check(
"validation oneOf preserves literal union types",
has("packages/validation/src/index.ts", "class StringSchema<TValue extends string") &&
has("packages/validation/src/index.ts", "TValues extends readonly [string, ...string[]]") &&
has("packages/validation/test/helpers.test.ts", "const schema: ObjectSchema<ContactInput>"),
);
check("0.8 migration exists", has("packages/cli/src/update.ts", 'id: "0.8.0-01-package-kits"'));
check(
"package kit audit exists",
existsSync(join(root, "scripts/audit-package-kits.mjs")) &&
rootManifest.scripts?.["audit:packages"] === "node scripts/audit-package-kits.mjs",
);
check(
"audit validators are read-only and reports use explicit generators",
rootManifest.scripts?.["security:framework"] === "node scripts/security-performance-audit.mjs" &&
rootManifest.scripts?.["generate:security-report"] ===
"node scripts/security-performance-audit.mjs --write" &&
rootManifest.scripts?.["generate:package-audit"] ===
"node scripts/audit-package-kits.mjs --write" &&
has("scripts/security-performance-audit.mjs", 'process.argv.includes("--write")') &&
has("scripts/audit-package-kits.mjs", 'process.argv.includes("--write")'),
);
const publicApi = spawnSync(process.execPath, ["scripts/check-public-api.mjs"], {
cwd: root,
encoding: "utf8",
});
if (publicApi.stdout) process.stdout.write(publicApi.stdout);
if (publicApi.stderr) process.stderr.write(publicApi.stderr);
check(
"public package exports match the reviewed API baseline",
publicApi.status === 0 && existsSync(join(root, "docs/public-api-0.8.json")),
);
const audit = spawnSync(process.execPath, ["scripts/audit-package-kits.mjs"], {
cwd: root,
encoding: "utf8",
});
if (audit.stdout) process.stdout.write(audit.stdout);
if (audit.stderr) process.stderr.write(audit.stderr);
check("all package kits pass the executable audit", audit.status === 0);
const runtimeProbe = spawnSync(
process.execPath,
["--experimental-transform-types", "scripts/test-package-kits.mjs"],
{ cwd: root, encoding: "utf8" },
);
if (runtimeProbe.stdout) process.stdout.write(runtimeProbe.stdout);
if (runtimeProbe.stderr) process.stderr.write(runtimeProbe.stderr);
check("package helper runtime probes pass", runtimeProbe.status === 0);
check(
"package helper APIs have dedicated tests",
[
"packages/encryption/test/http.test.ts",
"packages/jwt/test/helpers.test.ts",
"packages/db/test/helpers.test.ts",
"packages/i18n/test/package-kit.test.ts",
"packages/image/test/package-kit.test.ts",
"packages/captcha/test/helpers.test.ts",
"packages/uploader/test/helpers.test.ts",
"packages/validation/test/helpers.test.ts",
"packages/realtime/test/realtime.test.ts",
"packages/auth/test/package-components.test.ts",
].every((path) => existsSync(join(root, path))),
);
console.log(`\n${passed} passed`);
console.log(`${failed} failed`);
if (failed) {
console.error("\nFailures:");
for (const value of failures) console.error(`- ${value}`);
process.exitCode = 1;
}