#!/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( /]*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(/]*\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("= 1600 && height >= 900, `Render is too small: ${name} ${width}x${height}`); console.log(`${name}: ${width}x${height}`); } console.log("HMM OCI architecture validation: PASS");