83 lines
2.5 KiB
JavaScript
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");
|