Initial Commit
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* No-disallowed audit: verify that non-deterministic global APIs
|
||||
* (`Date`, `Math.random`, `crypto.randomUUID`) are only used in the
|
||||
* approved files listed below and never leak into business-logic modules.
|
||||
*
|
||||
* Approved list (files that legitimately need these APIs):
|
||||
* - src/utils/format.ts (generateUuid, generateNanoid, formatDate)
|
||||
* - src/plugins/dynamic/DateTimePlugin.ts (uses Date via clock fallback)
|
||||
* - src/plugins/dynamic/UuidPlugin.ts (delegates to format.ts)
|
||||
* - src/base/suaveplan-error.ts (error timestamp)
|
||||
*/
|
||||
import { readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
|
||||
const SRC_ROOT = join(import.meta.dirname ?? __dirname, "../src");
|
||||
|
||||
const APPROVED = new Set([
|
||||
join(SRC_ROOT, "utils/format.ts"),
|
||||
join(SRC_ROOT, "plugins/dynamic/DateTimePlugin.ts"),
|
||||
join(SRC_ROOT, "plugins/dynamic/UuidPlugin.ts"),
|
||||
join(SRC_ROOT, "otel/templates-otel.ts"),
|
||||
]);
|
||||
|
||||
// Patterns that indicate direct usage of non-deterministic globals
|
||||
const DISALLOWED = [
|
||||
/\bDate\.now\b/,
|
||||
/\bnew Date\(\)/,
|
||||
/\bMath\.random\b/,
|
||||
/\bcrypto\.randomUUID\b/,
|
||||
];
|
||||
|
||||
function collectTs(dir: string): string[] {
|
||||
const results: string[] = [];
|
||||
for (const entry of readdirSync(dir)) {
|
||||
const full = join(dir, entry);
|
||||
const stat = statSync(full);
|
||||
if (stat.isDirectory()) {
|
||||
results.push(...collectTs(full));
|
||||
} else if (
|
||||
entry.endsWith(".ts") &&
|
||||
!entry.endsWith(".test.ts") &&
|
||||
!entry.endsWith(".bench.ts")
|
||||
) {
|
||||
results.push(full);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
describe("no-disallowed globals in non-approved files", () => {
|
||||
const files = collectTs(SRC_ROOT).filter((f) => !APPROVED.has(f));
|
||||
|
||||
for (const file of files) {
|
||||
it(`${file.replace(SRC_ROOT, "src")} has no direct Date/Math.random usage`, {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const src = readFileSync(file, "utf-8");
|
||||
for (const pattern of DISALLOWED) {
|
||||
expect(
|
||||
pattern.test(src),
|
||||
`Found disallowed pattern ${pattern} in ${file}`
|
||||
).toBe(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user