import type { EnrichedKnowledgeGraph, EnrichedNode, KnowledgeGraph, SecurityMetadata } from '../index.js'; const AUTH_PATTERNS = [/auth/i, /login/i, /jwt/i, /session/i, /token/i, /password/i, /oauth/i, /credential/i]; const USER_INPUT_PATTERNS = [/request/i, /input/i, /form/i, /query/i, /upload/i, /param/i, /body/i]; const EXTERNAL_CALL_PATTERNS = [/fetch/i, /http/i, /request/i, /api/i, /client/i, /webhook/i, /external/i]; const DATABASE_PATTERNS = [/db/i, /database/i, /model/i, /repository/i, /query/i, /orm/i, /prisma/i, /mongo/i]; const CRYPTO_PATTERNS = [/crypt/i, /hash/i, /sign/i, /encrypt/i, /decrypt/i, /cipher/i, /hmac/i]; /** * Adds heuristic security metadata to each knowledge-graph node. */ export function enrichWithSecurityMetadata(graph: KnowledgeGraph): EnrichedKnowledgeGraph { const nodes: EnrichedNode[] = graph.nodes.map((node) => ({ ...node, security: inferSecurityMetadata(node.name, node.summary, node.path, node.layer), })); return { nodes, edges: graph.edges, }; } function inferSecurityMetadata( name: string, summary: string | undefined, path: string | undefined, layer: string | undefined, ): SecurityMetadata { const haystack = `${name} ${summary ?? ''} ${path ?? ''}`; return { handles_auth: matchesAny(haystack, AUTH_PATTERNS), handles_user_input: matchesAny(haystack, USER_INPUT_PATTERNS), makes_external_calls: matchesAny(haystack, EXTERNAL_CALL_PATTERNS), accesses_database: matchesAny(haystack, DATABASE_PATTERNS), has_crypto: matchesAny(haystack, CRYPTO_PATTERNS), trust_boundary: inferTrustBoundary(layer), }; } function inferTrustBoundary(layer: string | undefined): 'public' | 'internal' | 'privileged' { if (layer === 'api' || layer === 'ui') { return 'public'; } if (layer === 'data') { return 'privileged'; } return 'internal'; } function matchesAny(text: string, patterns: RegExp[]): boolean { for (const pattern of patterns) { if (pattern.test(text)) { return true; } } return false; }