Files
vpd-permission-poc/tools/architecture/validate-hmm-architecture.mjs
2026-08-04 14:37:38 +09:00

83 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
const architectureDir = path.resolve(process.argv[2] || "docs/architecture");
const drawioPath = path.join(
architectureDir,
"hmm-ai-data-access-architecture.drawio",
);
const drawio = fs.readFileSync(drawioPath, "utf8");
const diagrams = [...drawio.matchAll(
/<diagram\b[^>]*name="([^"]+)"[^>]*>([\s\S]*?)<\/diagram>/g,
)];
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
assert(diagrams.length === 2, `Expected 2 pages, found ${diagrams.length}`);
assert(
diagrams.map((match) => match[1]).join("|") ===
"01 · 전체 구성|02 · MCP 요청과 VPD",
"Unexpected Draw.io page names",
);
for (const [name, page] of diagrams.map((match) => [match[1], match[2]])) {
const ids = [...page.matchAll(/<mxCell\b[^>]*\bid="([^"]+)"/g)]
.map((match) => match[1]);
assert(ids.length === new Set(ids).size, `Duplicate mxCell id in ${name}`);
assert(page.includes("shape=stencil("), `OCI stencil missing in ${name}`);
}
const requiredText = [
"Autonomous Database",
"OCI Generative AI",
"Object Storage",
"AWS RDS PostgreSQL",
"BACKOFFICE_MCP_TOOLS",
"USER_AI_AGENT_TOOLS.ENABLED",
"CB_ORDS",
"HMM_ACCESS_CTX",
"HMM_LEAVE_SCOPE_POLICY",
"HMM_RDS_PG_LINK",
"SET_USER_BY_BEARER",
"CLEAR_VPD_CONTEXT",
];
for (const text of requiredText) {
assert(drawio.includes(text), `Required architecture text missing: ${text}`);
}
const forbidden = [
/vpd_live_[A-Za-z0-9_-]{8,}/,
/Bearer\s+[A-Za-z0-9_-]{20,}/,
/BEGIN (?:RSA |OPENSSH )?PRIVATE KEY/,
/Dhfkzmf#/,
];
for (const pattern of forbidden) {
assert(!pattern.test(drawio), `Sensitive value pattern found: ${pattern}`);
}
const renderNames = [
"hmm-ai-data-access-architecture-overview",
"hmm-ai-data-access-architecture-security-flow",
];
for (const name of renderNames) {
const svg = fs.readFileSync(path.join(architectureDir, `${name}.svg`), "utf8");
assert(svg.includes("<svg"), `Invalid SVG render: ${name}`);
const png = fs.readFileSync(path.join(architectureDir, `${name}.png`));
assert(
png.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])),
`Invalid PNG render: ${name}`,
);
const width = png.readUInt32BE(16);
const height = png.readUInt32BE(20);
assert(width >= 1600 && height >= 900, `Render is too small: ${name} ${width}x${height}`);
console.log(`${name}: ${width}x${height}`);
}
console.log("HMM OCI architecture validation: PASS");