/** * Hierarchy writer-coverage assertion — contract 1 * (docs/requirements/hierarchy-schema.md) §6.3(b). * * A static CI assertion over all production sources (apps/, packages/, * plugins/) with three prongs, each bound to a closed, explicitly enumerated * allowlist: * * (i) Symbol prong — write references (insert/update/delete) to the * class-table schema symbols occur only in allowlisted modules. * Schema symbols are tracked through named imports (aliased or not), * namespace imports, and re-export conduits. Conduits carry an * EXPORT MAP (per-module named exports and namespace exports), * computed to a fixpoint, so a rename at the export site * (`export { companies as c } from`), an export of a locally bound * alias (`import { companies }; export { companies as co }`), and a * binding derived from a namespace (`export const co = ns.companies`) * all propagate symbol identity to the consumer. Declaration exports * tolerate a type annotation and prior declarators * (`export const co: typeof companies = companies`, * `export const dummy = 0, co = companies`). The DEFAULT-export * slot is an export name like any other (`export { companies as * default } from`, `export default companies`), so a bare default * import of a conduit resolves against the map too; namespace-member * write targets match the source's EXPORTED names — renames included * (`M.co` after `export { companies as co } from`) — not just the * original class symbols. Destructuring a NON-class property from a * schema namespace over-approximates: the binding is treated as a * schema namespace itself (fail-closed), and single-alias derivation * from a namespace (`const t = ns.companies`) is folded in to a * fixed depth. * (ii) Literal prong — a class-table name inside a string or template * span that also carries SQL context fails outside the allowlist. * Spans are produced by a real lexer, so comments cannot hide code * and strings cannot hide comments. Schema definitions and generated * migrations are excluded from this prong only (per contract). * (iii) Raw-execution prong — content-independent. A file is RAW-CAPABLE * when it imports a database driver or the createDb/createPgliteDb * factories — directly, via namespace, by destructuring a factory * symbol out of a schema namespace, or from a capability CONDUIT. * Conduits carry their own exported-name maps computed to a * fixpoint, so a factory renamed at any hop (`export { createDb as * mk } from`, `export default createDb`) still marks every module * down the chain, and a tracked dynamic import of a conduit is an * import edge like a static one. In a raw-capable file * outside the allowlist and register, EVERY `.execute(`, `.query(`, * and `.unsafe(` call fails, on any receiver, with any argument — * there is no tagged-template exemption (§6.3(b): "regardless of what * the SQL string contains or how it is constructed"). In files * without detected capability (the DI residual), a conventional * receiver backstop still fires on db/client-shaped receivers. * `sql.raw` is tracked through import aliasing and namespaces. * * Runtime code-construction primitives (eval, new Function — spelled * directly or as a literal computed member like `globalThis['eval']`) fail * anywhere — allowlist and register included: constructed code defeats every * static prong, so there is no enumerated disposition path for it. * Unanalyzable import routes fail everywhere except their own enumerated * disposition registers below: a dynamic import whose specifier is not a * single string literal, and createRequire (tracked through import aliasing * — `createRequire as x` — and destructuring from the module namespace, * whether that namespace came from a static `import * as` or a tracked * dynamic import; a * route that hides the NAME entirely, e.g. re-exporting createRequire from a * helper, falls under the value-flow residual). A LITERAL dynamic import is * an import edge like any static import (contract rev 9): its bindings * (destructured or namespace) feed prong (i) exactly as static import * bindings do — and to keep that claim sound, a literal dynamic import of a * schema/factory/driver source OUTSIDE the tracked * `const X = await import('…')` binding shape (`.then` chains, deferred * awaits, Promise.all) is itself a violation: bindings the analyzer cannot * track are not allowed to exist for capability-bearing modules. * * KNOWN RESIDUALS (deliberate, reviewed trade-offs — not claims of closure): * - In a file with NO detected raw capability (no driver/factory import on * any tracked route), prong (iii) falls back to a conventional-receiver * backstop (db/client/pool/tx/…). A dependency-injected handle bound to * an unconventional name in such a file is an OPEN evasion path. The * counterfactual was measured: any-receiver flagging in capability-free * files false-positives on real non-SQL .execute()/.query() sites * (runtime-provider-registry, connector-lease, the log CLI), so the * residual is accepted and reviews of DI provider modules carry it. * - Computed member access with a NON-literal name (obj[verb]()) is not * statically resolvable; literal computed access (obj['insert']()) is * flagged, and the statically-resolvable DISGUISES of a literal key fail * closed — access or call, in any position: a text-only template-literal * key (obj[`insert`](), ns[`companies`] — template text never reaches * the lexer's code output), a quoted OR template key carrying expression * dressing (`ns['companies' as const]`, `ns['companies'!]`, * `ns[`companies` as const]` — the dressed rule's key class includes the * backtick, so the lexed empty backtick pair matches), and a quoted key * built from string escapes (`\u`/`\x`/octal). (A template key WITH * interpolation is a non-literal computed member, above.) Invoking a * write/exec verb via `.apply`/`.call`/`.bind` fails closed the same * way, and ANY appearance of the `Reflect` identifier fails closed * outright — verb detection through Reflect is not boundable (argument * windows stop at newlines and nested parens, the method can be * bracket-spelled, the object aliased), and the tree has zero * occurrences outside test files. These * code-shape rules match ordinary syntax over ordinary method names, so * they carry their own enumerated disposition (CODE_SHAPE_REGISTER, * empty today): a reviewed legitimate hit is registered, never resolved * by weakening the shape. Constructing the member at runtime is adjacent * to eval and is expected to be caught in review. * - The DB_FACTORY_IMPORTERS enumeration counts the import edges * hasSymbolImportEdge can see (named import, literal dynamic package * import with symbol use, namespace member use). Destructuring a factory * out of a schema namespace (`const { createDb } = dbns`) confers * capability for prong (iii) but is NOT visible to the enumeration, so a * file on that route joins the importer set only via review; prong (iii) * still flags any execution in it. The enumeration is a measured set, * not a soundness claim. * - General VALUE FLOW is not modeled. The analyzer tracks import edges, * re-export chains, and single-step alias/destructure derivations from a * namespace binding (to depth 2) — not arbitrary assignment chains, * function returns, or method extraction. Demonstrated escapes in this * class: `const u = this.client.unsafe; u.call(this.client, s)` (the * verb never appears as a member call), an alias chain three or more * steps deep, a helper function that returns a schema symbol, and an * export whose expression COMPUTES the value (a ternary, a call result) * rather than naming a binding or member. * Closing it requires data-flow analysis (a type-checker-backed rewrite, * tracked for M4-1b consideration); the counterfactual — flagging every * bare identifier call — false-positives on essentially all callback * code. Reviews of modules touching db handles carry this residual. * - The scan perimeter is the full / tree for the three roots * (build output, tool caches, and dot-directories excluded), so * production TS outside src/ — package configs, e2e helpers, * packages/mosaic/framework/** — is scanned and conduit-visible * (widened from src/-only in M4-1b-i; the widened set was measured free * of every trigger token at the time). Files excluded from the scan — * test files — are still invisible as import-graph CONDUITS: test files * are emitted to dist, so a production module could launder a symbol or * capability through a re-export in one. Importing a test module from * production code is anomalous and review-visible; that blind spot is * accepted as a residual, not closed. * * The writer allowlist names hierarchy command/repository modules ONLY. It is * empty today: the hierarchy command family (M4-1b-ii) has not landed, so no * production module may write the class tables. The infrastructure register * holds legitimate non-hierarchy raw execution; registered modules are exempt * from prong (iii) only — prongs (i) and (ii) apply to them with no * exemption, and no registered module may appear on the writer allowlist. * * Register modules whose exports let a CALLER reach SQL execution carry their * own closed importer enumerations (the laundering path §6.3(b) closes): * the migration runner, migrate-tier, and the createDb/createPgliteDb * factories. The remaining registered modules execute only fixed statements * or collection-CRUD over the storage `(id, data)` shape — which cannot * address class-table columns — and export no caller-supplied-SQL surface; * that composition property is review-enforced (§5.1) on any change to them. * * A false positive is resolved in the same PR by adding the module to the one * enumerated list its role permits — never by weakening the assertion. * * Test files (*.spec.*, *.test.*, __tests__/) are not scanned: they are not * production mutation paths, and the contract's own §6 witnesses must write * class tables directly to witness database constraints. The known evasion * forms from the M4-1a review are kept below as permanent controls: the * analyzer must flag every one of them, so a regression that reopens an * escape fails this suite. */ import { readdirSync, readFileSync, statSync, existsSync } from 'node:fs'; import { dirname, join, relative, resolve, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vitest'; const REPO_ROOT = resolve(fileURLToPath(new URL('.', import.meta.url)), '..', '..', '..'); /** Drizzle schema symbols of the five class tables (packages/db/src/schema.ts). */ const CLASS_SYMBOLS = ['companies', 'estates', 'platformProjects', 'workspaces', 'hierarchyGrants']; /** SQL table names of the five class tables. */ const CLASS_TABLES = [ 'companies', 'estates', 'platform_projects', 'workspaces', 'hierarchy_grants', ]; /** * Writer allowlist (§6.3b): hierarchy command/repository modules only. * EMPTY until the hierarchy command family lands (M4-1b-ii; M4-1b-i ships * only the audit/outbox machinery, which writes no class table). Adding a module * here is a contract-conformance decision reviewed under §5.1 — the module * must be part of the Gateway hierarchy command path, and it must not export * a function that executes caller-supplied SQL. */ const WRITER_ALLOWLIST: string[] = []; /** * Infrastructure register: closed enumeration of legitimate non-hierarchy raw * execution. Exempt from prong (iii) ONLY; prongs (i)/(ii) still apply, and * none of these may ever join the writer allowlist. */ const INFRA_REGISTER: string[] = [ 'packages/db/src/client.ts', // connection factory (imports postgres driver) 'packages/db/src/client-pglite.ts', // PGlite factory (imports the pglite driver) 'packages/db/src/migrate.ts', // migration runner (hash-ledger DDL execution) 'packages/db/src/backlog.ts', // backlog domain module: parameterized sql`` over backlog tables only 'packages/memory/src/insights.ts', // analytics raw query over memory tables 'packages/storage/src/tier-detection.ts', // driver import for tier probing (fixed statements) 'packages/storage/src/adapters/pglite.ts', // storage adapter (collection CRUD over (id, data)) 'packages/storage/src/adapters/postgres.ts', // storage adapter (extension bootstrap) 'packages/storage/src/migrate-tier.ts', // storage tier migration 'packages/storage/src/cli.ts', // storage CLI health probe 'apps/gateway/src/admin/admin-health.controller.ts', // SELECT 1 health probe ]; /** * Closed importer enumerations for registered modules whose exports execute * SQL or hand out an executing handle. An import edge is a static value * import naming the symbol (from the module path or the package barrel), or * a literal dynamic import of the package in a file using the symbol. * `import type` is erased and is not an edge; parameter injection (the * gateway schema-check module) has no edge. Being enumerated confers nothing * else: importers stay subject to every prong and gain no writer standing. */ const MIGRATION_RUNNER_SYMBOLS = ['runMigrations', 'runPgliteMigrations', 'getMigrationStatus']; const MIGRATION_RUNNER_IMPORTERS: string[] = [ 'apps/gateway/src/database/database.module.ts', 'packages/storage/src/adapters/postgres.ts', 'packages/mosaic/src/commands/fleet-backlog.ts', 'packages/mosaic/src/commands/gateway/verify.ts', ]; const MIGRATE_TIER_SYMBOLS = [ 'runMigrateTier', 'checkTargetPreconditions', 'PostgresMigrationTarget', 'DrizzleMigrationSource', ]; const MIGRATE_TIER_IMPORTERS: string[] = [ 'packages/storage/src/cli.ts', // storage CLI command surface 'packages/storage/src/index.ts', // package barrel re-export (public API) ]; /** * Enumerated disposition for non-literal dynamic imports (§6.3b review F8): * files here may use a computed import specifier; every other prong still * applies to them in full. Each entry needs a justification. */ const DYNAMIC_IMPORT_REGISTER: string[] = [ 'plugins/macp/src/index.ts', // loads the ACP runtime SDK from a configured sdkRoot; no db access ]; /** * Enumerated disposition for createRequire (an unanalyzable CJS import * route). Every entry uses it for package.json version reads or module * resolution only (measured); every other prong still applies in full. */ const CREATE_REQUIRE_REGISTER: string[] = [ 'packages/mosaic/src/cli.ts', // package.json version read 'packages/mosaic/src/commands/gateway/daemon.ts', // module path resolution 'packages/mosaic/src/commands/launch.ts', // package.json version read + resolution 'packages/mosaic/src/commands/lease-activation-probe.ts', // injectable module resolver default 'plugins/macp/src/index.ts', // OpenCode SDK resolution ]; /** Importers of the db-handle factories (measured set; a new importer must be reviewed in). */ const DB_FACTORY_SYMBOLS = ['createDb', 'createPgliteDb']; const DB_FACTORY_IMPORTERS: string[] = [ 'apps/gateway/src/database/database.module.ts', 'packages/brain/src/cli.ts', 'packages/log/src/cli.ts', 'packages/memory/src/adapters/pgvector.ts', 'packages/memory/src/cli.ts', 'packages/mosaic/src/commands/fleet-backlog.ts', 'packages/storage/src/adapters/postgres.ts', 'packages/storage/src/cli.ts', 'packages/storage/src/migrate-tier.ts', ]; /** * Enumerated disposition for the fail-closed CODE-SHAPE rules (text-only * template keys, dressed/escape-built quoted keys, verb * `.apply`/`.call`/`.bind`, `Reflect.*` verb indirection). Those shapes use * ordinary syntax over ordinary method names (`query`, `delete`), so a * legitimate hit is possible — e.g. a non-SQL `.query.bind(this)` on a * log-shaped service. Such a hit is registered here with a justification, * reviewed under §5.1, and is never resolved by weakening the shape. Empty * today: the production tree has zero occurrences of any of these shapes * (calibrated by the full-tree test). Exemption covers the shape rules ONLY — * every prong still applies in full. eval/new Function stays unconditional: * constructed code has no disposition path. */ const CODE_SHAPE_REGISTER: string[] = []; const SCAN_ROOTS = ['apps', 'packages', 'plugins']; const EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']); const DRIVER_SPECIFIERS = ['postgres', 'pg', '@electric-sql/pglite']; function isTestPath(rel: string): boolean { return ( /\.(spec|test)\.[cm]?tsx?$/.test(rel) || rel.split(sep).includes('__tests__') || rel.endsWith('.d.ts') ); } /** Directory names excluded from the walk: build output and tool caches only. */ const EXCLUDED_DIRS = new Set(['node_modules', 'dist', 'build', 'coverage', 'test-results']); function collectSources(): string[] { const files: string[] = []; for (const root of SCAN_ROOTS) { const rootDir = join(REPO_ROOT, root); if (!existsSync(rootDir)) continue; for (const pkg of readdirSync(rootDir)) { const pkgDir = join(rootDir, pkg); if (!statSync(pkgDir).isDirectory()) continue; const walk = (dir: string): void => { for (const entry of readdirSync(dir)) { const full = join(dir, entry); const st = statSync(full); if (st.isDirectory()) { if (EXCLUDED_DIRS.has(entry) || entry.startsWith('.')) continue; walk(full); } else if (EXTENSIONS.has(full.slice(full.lastIndexOf('.')))) { const rel = relative(REPO_ROOT, full).split(sep).join('/'); if (!isTestPath(rel)) files.push(rel); } } }; walk(pkgDir); } } return files.sort(); } // --------------------------------------------------------------------------- // Lexer: single pass producing (a) comment-free source with strings intact // (for import/export and call-site regexes) and (b) the string/template text // spans (for the literal prong). String-aware, so `//` inside a string is not // a comment and a quote inside a comment does not open a string. Template // expressions re-enter code mode (nesting supported); regex literals are // recognized with the standard prev-token heuristic so their contents cannot // open a phantom string. // --------------------------------------------------------------------------- interface Lexed { code: string; spans: string[]; } function lexSource(src: string): Lexed { let code = ''; const spans: string[] = []; let i = 0; const n = src.length; // Template nesting: each entry is the accumulated text of one template. const tplStack: string[] = []; // Brace depth inside the current ${ } expression, one entry per nesting level. const exprDepth: number[] = []; let lastSig = ''; // last significant code char (regex-vs-division heuristic) let lastWord = ''; // last identifier/keyword emitted to code const emit = (ch: string): void => { code += ch; if (!/\s/.test(ch)) { lastSig = ch; if (/[A-Za-z0-9_$]/.test(ch)) lastWord += ch; else lastWord = ''; } }; const regexCanStart = (): boolean => { if (lastSig === '' || '([{,;=:!&|?+-*%^<>~'.includes(lastSig)) return true; return ['return', 'typeof', 'case', 'in', 'of', 'new', 'delete', 'void', 'do', 'else'].includes( lastWord, ); }; while (i < n) { const ch = src[i]!; const next = i + 1 < n ? src[i + 1]! : ''; if (tplStack.length > 0 && exprDepth.length < tplStack.length) { // Inside template literal text. const top = tplStack.length - 1; if (ch === '\\') { tplStack[top] += src.slice(i, i + 2); i += 2; continue; } if (ch === '`') { spans.push(tplStack.pop()!); emit('`'); i += 1; continue; } if (ch === '$' && next === '{') { exprDepth.push(0); emit('$'); emit('{'); i += 2; continue; } tplStack[top] += ch; i += 1; continue; } // Code mode (possibly inside a ${ } expression). if (ch === '/' && next === '/') { while (i < n && src[i] !== '\n') i += 1; continue; } if (ch === '/' && next === '*') { i += 2; while (i < n && !(src[i] === '*' && src[i + 1] === '/')) i += 1; i += 2; emit(' '); continue; } if (ch === "'" || ch === '"') { let span = ''; i += 1; while (i < n && src[i] !== ch) { if (src[i] === '\\') { span += src.slice(i, i + 2); i += 2; } else { span += src[i]; i += 1; } } i += 1; spans.push(span); // Keep quoted strings in code output so import specifiers stay parseable. emit(ch); code += span; emit(ch); continue; } if (ch === '`') { tplStack.push(''); emit('`'); i += 1; continue; } if (ch === '/' && regexCanStart()) { // Regex literal: consume without interpreting quotes/backticks inside. i += 1; let inClass = false; while (i < n) { const rc = src[i]!; if (rc === '\\') { i += 2; continue; } if (rc === '[') inClass = true; else if (rc === ']') inClass = false; else if (rc === '/' && !inClass) break; else if (rc === '\n') break; // not a regex after all; bail safely i += 1; } i += 1; while (i < n && /[a-z]/.test(src[i]!)) i += 1; // flags emit('/'); continue; } if (exprDepth.length > 0) { const top = exprDepth.length - 1; if (ch === '{') exprDepth[top] = exprDepth[top]! + 1; if (ch === '}') { if (exprDepth[top] === 0) { exprDepth.pop(); emit('}'); i += 1; continue; } exprDepth[top] = exprDepth[top]! - 1; } } emit(ch); i += 1; } while (tplStack.length > 0) spans.push(tplStack.pop()!); return { code, spans }; } // --------------------------------------------------------------------------- // Import graph helpers // --------------------------------------------------------------------------- function resolveSpecifier(fromRel: string, spec: string, fileSet: Set): string | null { if (!spec.startsWith('.')) return null; const base = join(dirname(fromRel), spec).split(sep).join('/'); const noJs = base.replace(/\.(js|mjs|cjs)$/, ''); for (const cand of [ base, noJs, `${noJs}.ts`, `${noJs}.tsx`, `${noJs}.mts`, `${noJs}.cts`, `${noJs}/index.ts`, ]) { if (fileSet.has(cand)) return cand; } return null; } const IMPORT_RE = /import\s*(type\s+)?(?:(\w+)\s*,\s*)?(?:\{([^}]*)\}|\*\s*as\s+(\w+)|(\w+))?\s*from\s*['"]([^'"]+)['"]/g; const EXPORT_FROM_RE = /export\s*(type\s+)?(?:\{([^}]*)\}|\*(?:\s*as\s+\w+)?)\s*from\s*['"]([^'"]+)['"]/g; // Member-access shapes, tolerant of optional chaining and non-null // assertions (ns?.companies, ns!.companies, ns?.['companies']) — a `?.` or // `!` between receiver and member must not break a match. const DOT = `\\s*(?:\\?\\.|!\\s*\\.|\\.)\\s*`; const BRACKET_OPEN = `\\s*(?:\\?\\.|!)?\\s*\\[`; const MEMBER_SEG = `(?:${DOT}\\w+|${BRACKET_OPEN}\\s*['"\`]\\w+['"\`]\\s*\\])`; /** Terminal member access matching one of `alt`'s names, dot or bracket form. */ const memberTail = (alt: string): string => `(?:${DOT}(?:${alt})\\b|${BRACKET_OPEN}\\s*['"\`](?:${alt})['"\`]\\s*\\])`; /** * Reduce an exported expression to its core: strip parenthesization, * trailing type assertions (`as …`, `satisfies …`), and trailing non-null * assertions (`(companies)`, `companies as unknown as object`, * `companies satisfies object`, `companies!`, `(companies as any)!`) so * `export default ` passes see the binding under the dressing. */ function stripExprDressing(raw: string): string { let expr = raw.trim(); for (let prev = ''; prev !== expr; ) { prev = expr; expr = expr .replace(/^\(\s*/, '') .replace(/\s*\)$/, '') .replace(/\s+as\s+[^()]+$/, '') .replace(/\s+satisfies\s+[^()]+$/, '') .replace(/\s*!+$/, '') .trim(); } return expr; } /** Call-open shape tolerant of the optional-call form: `f(…)` or `f?.(…)`. */ const CALL_OPEN = `\\s*(?:\\?\\.)?\\s*\\(`; /** * Declaration-head shapes: a declarator's initializer may sit behind a type * annotation (`export const co: typeof companies = companies`) or behind * prior declarators (`export const dummy = 0, co = companies`). TYPE_ANN * admits `=>` inside the type text but stops at a bare `=` (the * initializer); DECL_LIST skips prior declarators whose initializers are * comma-free. Both are approximations of the declarator grammar — exotic * prior initializers (an array or call containing a comma) fall to the * value-flow residual. Both are also SINGLE-LINE shapes: a multiline type * annotation (prettier keeps one only past the print width) falls to the * value-flow residual too. */ const TYPE_ANN = `(?:\\s*:\\s*(?:[^=;\\n]|=>)*?)?`; const DECL_LIST = `(?:[\\w$]+${TYPE_ANN}\\s*=\\s*[^,;\\n]*,\\s*)*`; interface FileFacts { rel: string; code: string; spans: string[]; } interface Violation { file: string; prong: string; detail: string; } /** * Schema exports of one module in the conduit graph: `named` are exported * identifiers bound to a class-table symbol (under WHATEVER exported name — * renames propagate); `ns` are exported identifiers that are themselves * namespaces over a schema source (`export * as x from …`). */ interface SchemaExports { named: Set; ns: Set; } type SchemaConduits = Map; /** Exported class-symbol names reachable through `spec` from `rel` (null = not a schema source). */ function schemaExportsOf( rel: string, spec: string, conduits: SchemaConduits, fileSet: Set, ): SchemaExports | null { if (spec === '@mosaicstack/db') return { named: new Set(CLASS_SYMBOLS), ns: new Set() }; const r = resolveSpecifier(rel, spec, fileSet); return r !== null ? (conduits.get(r) ?? null) : null; } /** * Compute the fixpoint map of "schema sources": module → the exported names * under which a class-table symbol (or a schema namespace) is reachable from * it. Seeds: the schema module and the db package barrel (the bare * '@mosaicstack/db' specifier is handled in schemaExportsOf). Renames are * propagated: `export { companies as c } from …` exports `c`, an * `export { x as y }` of a local class binding exports `y`, and * `export const y = ns.companies` over a schema namespace exports `y`. */ function computeSchemaConduits(files: FileFacts[], fileSet: Set): SchemaConduits { const conduits: SchemaConduits = new Map([ ['packages/db/src/schema.ts', { named: new Set(CLASS_SYMBOLS), ns: new Set() }], ['packages/db/src/index.ts', { named: new Set(CLASS_SYMBOLS), ns: new Set() }], ]); let changed = true; while (changed) { changed = false; for (const f of files) { const mine: SchemaExports = conduits.get(f.rel) ?? { named: new Set(), ns: new Set(), }; const before = mine.named.size + mine.ns.size; for (const m of f.code.matchAll(EXPORT_FROM_RE)) { if (m[1]) continue; // export type — erased const src = schemaExportsOf(f.rel, m[3]!, conduits, fileSet); if (src === null || (src.named.size === 0 && src.ns.size === 0)) continue; const starAs = /export\s*\*\s*as\s+(\w+)/.exec(m[0]); if (starAs) { mine.ns.add(starAs[1]!); // export * as x from schema source } else if (m[2] === undefined) { for (const n of src.named) mine.named.add(n); // export * from … for (const n of src.ns) mine.ns.add(n); } else { for (const part of m[2].split(',')) { const seg = part.trim(); if (!seg || seg.startsWith('type ')) continue; const asMatch = /^(\w+)\s+as\s+(\w+)$/.exec(seg); const original = asMatch ? asMatch[1]! : seg; const exported = asMatch ? asMatch[2]! : seg; if (src.named.has(original)) mine.named.add(exported); if (src.ns.has(original)) mine.ns.add(exported); } } } // Exports of local bindings: `export { x as y }` where x is a local // class alias (or namespace), and `export const y = ns.`. const aliases = classAliases(f, conduits, fileSet); if (aliases.named.length > 0 || aliases.namespaces.length > 0) { for (const m of f.code.matchAll(/export\s*\{([^}]*)\}(?!\s*from)/g)) { for (const part of m[1]!.split(',')) { const seg = part.trim(); if (!seg || seg.startsWith('type ')) continue; const asMatch = /^(\w+)\s+as\s+(\w+)$/.exec(seg); const local = asMatch ? asMatch[1]! : seg; const exported = asMatch ? asMatch[2]! : seg; if (aliases.named.includes(local)) mine.named.add(exported); if (aliases.namespaces.includes(local)) mine.ns.add(exported); } } for (const ns of aliases.namespaces) { for (const m of f.code.matchAll( new RegExp( `export\\s+(?:const|let|var)\\s+${DECL_LIST}(\\w+)${TYPE_ANN}\\s*=\\s*\\(*\\s*${ns}${MEMBER_SEG}*${memberTail(CLASS_SYMBOLS.join('|'))}`, 'g', ), )) { mine.named.add(m[1]!); } } for (const local of aliases.named) { for (const m of f.code.matchAll( new RegExp( `export\\s+(?:const|let|var)\\s+${DECL_LIST}(\\w+)${TYPE_ANN}\\s*=\\s*\\(*\\s*${local}\\b`, 'g', ), )) { mine.named.add(m[1]!); } } // The default slot is an export name like any other, whatever the // expression dressing: bare local, parenthesized, type-asserted // (`as`/`satisfies`), non-null-asserted (`companies!`), or a // namespace member chain in dot or bracket form, semicolon or not. for (const m of f.code.matchAll(/export\s+default\s+([^;\n]+)/g)) { const expr = stripExprDressing(m[1]!); if (/^\w+$/.test(expr)) { if (aliases.named.includes(expr)) mine.named.add('default'); if (aliases.namespaces.includes(expr)) mine.ns.add('default'); } else { for (const ns of aliases.namespaces) { if ( new RegExp(`^${ns}${MEMBER_SEG}*${memberTail(CLASS_SYMBOLS.join('|'))}$`).test(expr) ) { mine.named.add('default'); break; } } } } } if (mine.named.size + mine.ns.size > before) { conduits.set(f.rel, mine); changed = true; } } } return conduits; } interface ClassAliases { named: string[]; // local identifiers bound to class-table symbols namespaces: string[]; // namespace identifiers over a schema source // Member names under which a class symbol is reachable on SOME imported // schema source (class symbols plus every renamed conduit export the file // imports) — the alternation for namespace-member write targets. memberSyms: Set; } /** * Parse an import named-binding list ("a, b as c") against the SOURCE's * schema exports, adding locals bound to class symbols / schema namespaces. */ function importBindings( namedList: string, src: SchemaExports, named: Set, namespaces: Set, ): void { for (const part of namedList.split(',')) { const seg = part.trim(); if (!seg || seg.startsWith('type ')) continue; const asMatch = /^(\w+)\s+as\s+(\w+)$/.exec(seg); const original = asMatch ? asMatch[1]! : seg; const local = asMatch ? asMatch[2]! : seg; if (src.named.has(original)) named.add(local); if (src.ns.has(original)) namespaces.add(local); } } /** * Parse a destructuring pattern ("a, b: c, d = x") over a schema source. * A class-symbol property binds a named alias; ANY other destructured * property is over-approximated as a schema namespace (it may be a nested * namespace such as `const { schema } = ns` — fail-closed). */ function destructureBindings( pattern: string, src: SchemaExports, named: Set, namespaces: Set, ): void { for (const part of pattern.split(',')) { const seg = part.trim(); if (!seg) continue; const m = /^(\w+)\s*(?::\s*(\w+))?\s*(?:=[\s\S]*)?$/.exec(seg); if (!m) continue; const local = m[2] ?? m[1]!; if (src.named.has(m[1]!)) named.add(local); else namespaces.add(local); } } function classAliases(f: FileFacts, conduits: SchemaConduits, fileSet: Set): ClassAliases { const named = new Set(); const namespaces = new Set(); const memberSyms = new Set(CLASS_SYMBOLS); for (const m of f.code.matchAll(IMPORT_RE)) { const [, typeOnly, defaultWith, namedList, nsName, defaultBare, spec] = m; if (typeOnly) continue; const src = schemaExportsOf(f.rel, spec!, conduits, fileSet); if (src === null || (src.named.size === 0 && src.ns.size === 0)) continue; for (const n of src.named) memberSyms.add(n); if (nsName) namespaces.add(nsName); if (namedList) importBindings(namedList, src, named, namespaces); // A default import binds whatever the source exports as `default`. const dflt = defaultWith ?? defaultBare; if (dflt) { if (src.named.has('default')) named.add(dflt); if (src.ns.has('default')) namespaces.add(dflt); } } // Literal dynamic imports of a schema source are import edges like any // other (contract rev 9): both binding shapes feed prong (i). for (const m of f.code.matchAll( /(?:const|let|var)\s*(?:\{([^}]*)\}|(\w+))\s*=\s*await\s+import\s*\(\s*(['"])([^'"]+)\3\s*\)/g, )) { const [, pattern, nsName, , spec] = m; const src = schemaExportsOf(f.rel, spec!, conduits, fileSet); if (src === null || (src.named.size === 0 && src.ns.size === 0)) continue; for (const n of src.named) memberSyms.add(n); if (nsName) namespaces.add(nsName); if (pattern) destructureBindings(pattern, src, named, namespaces); } // Aliases derived FROM a schema namespace, to a bounded depth (2 passes): // const { companies } = ns; → named alias // const { schema } = ns; → nested namespace (fail-closed) // const t = ns.companies; → named alias // const s2 = ns.schema; → namespace alias const nsSrc: SchemaExports = { named: memberSyms, ns: new Set() }; for (let pass = 0; pass < 2; pass += 1) { for (const ns of [...namespaces]) { for (const m of f.code.matchAll( new RegExp(`(?:const|let|var)\\s*\\{([^}]*)\\}\\s*=\\s*(?:await\\s+)?${ns}\\b`, 'g'), )) { destructureBindings(m[1]!, nsSrc, named, namespaces); } for (const m of f.code.matchAll( new RegExp( `(?:const|let|var)\\s+${DECL_LIST}(\\w+)${TYPE_ANN}\\s*=\\s*\\(*\\s*${ns}${MEMBER_SEG}*(?:${DOT}(\\w+)\\b|${BRACKET_OPEN}\\s*['"\`](\\w+)['"\`]\\s*\\])`, 'g', ), )) { if (memberSyms.has((m[2] ?? m[3])!)) named.add(m[1]!); else namespaces.add(m[1]!); } } } return { named: [...named], namespaces: [...namespaces], memberSyms }; } /** * Capability conduits: modules that re-export raw-execution capability, so a * consumer can obtain it without a literal driver/factory specifier. * `driver` — re-exports (star, named, or default) from a driver package or * another driver conduit; importing ANYTHING from one confers driver * capability (the conduit module itself is additionally flagged by prong * (iii)'s literal check, so these routes fail at both ends). * `factory` — carries a NAME MAP (module → the exported names under which a * factory is reachable), computed to a fixpoint: `export … from` propagates * the SOURCE's exported factory names through renames (star and star-as * copy them all), and a local binding of a factory (named import, namespace * member extraction, or tracked dynamic-import destructure) exported under * any name — braces, declaration, or `export default` — adds that name. * Importing ANYTHING from a factory conduit (statically or via a tracked * dynamic import) confers factory capability — the conduit may rename the * symbol at any hop, so there is no consumer-side name gate. */ function computeCapabilityConduits( files: FileFacts[], fileSet: Set, ): { driver: Set; factory: Set } { const driver = new Set(); // Factory conduits carry a NAME MAP (module → exported names under which a // factory is reachable) so renames propagate hop by hop, exactly like the // schema export map — a literal-name gate at any hop would launder. const factoryNames = new Map>(); const isDriverSpec = (rel: string, spec: string): boolean => { if (DRIVER_SPECIFIERS.includes(spec)) return true; const r = resolveSpecifier(rel, spec, fileSet); return r !== null && driver.has(r); }; const factoryNamesOf = (rel: string, spec: string): Set | null => { if (spec === '@mosaicstack/db') return new Set(DB_FACTORY_SYMBOLS); const r = resolveSpecifier(rel, spec, fileSet); return r !== null ? (factoryNames.get(r) ?? null) : null; }; let changed = true; while (changed) { changed = false; for (const f of files) { for (const m of f.code.matchAll(EXPORT_FROM_RE)) { if (m[1]) continue; // export type — erased const spec = m[3]!; if (!driver.has(f.rel) && isDriverSpec(f.rel, spec)) { driver.add(f.rel); changed = true; } } // `export { default as x } from 'postgres'` matches EXPORT_FROM_RE's // named branch above; `export x from` is not valid syntax — covered. const mine = factoryNames.get(f.rel) ?? new Set(); const before = mine.size; for (const m of f.code.matchAll(EXPORT_FROM_RE)) { if (m[1]) continue; const src = factoryNamesOf(f.rel, m[3]!); if (src === null || src.size === 0) continue; if (m[2] === undefined) { // `export *` / `export * as x` — over-approximated to the source's // names (membership is what confers capability on consumers). for (const n of src) mine.add(n); } else { for (const part of m[2].split(',')) { const seg = part.trim(); if (!seg || seg.startsWith('type ')) continue; const am = /^(\w+)\s+as\s+(\w+)$/.exec(seg); if (src.has(am ? am[1]! : seg)) mine.add(am ? am[2]! : seg); } } } // Locals bound to a factory (named import — aliased or not — namespace // member extraction, or tracked dynamic-import destructure), then // exported under ANY name and by ANY form, braces or default included // (`export const mk = mod.createDb`, `export default createDb`). const locals = new Set(); const nss = new Map>(); for (const im of f.code.matchAll(IMPORT_RE)) { const [, typeOnly, , namedList, nsName, , spec] = im; if (typeOnly) continue; const src = factoryNamesOf(f.rel, spec!); if (src === null || src.size === 0) continue; if (nsName) nss.set(nsName, src); if (namedList) { for (const part of namedList.split(',')) { const am = /^(\w+)(?:\s+as\s+(\w+))?$/.exec(part.trim()); if (am && src.has(am[1]!)) locals.add(am[2] ?? am[1]!); } } } for (const dm of f.code.matchAll( /(?:const|let|var)\s*(?:\{([^}]*)\}|(\w+))\s*=\s*await\s+import\s*\(\s*(['"])([^'"]+)\3\s*\)/g, )) { const [, pattern, nsName, , spec] = dm; const src = factoryNamesOf(f.rel, spec!); if (src === null || src.size === 0) continue; if (nsName) nss.set(nsName, src); if (pattern) { for (const part of pattern.split(',')) { const pm = /^(\w+)\s*(?::\s*(\w+))?/.exec(part.trim()); if (pm && src.has(pm[1]!)) locals.add(pm[2] ?? pm[1]!); } } } for (const [ns, src] of nss) { for (const am of f.code.matchAll( new RegExp( `(?:const|let|var)\\s+${DECL_LIST}(\\w+)${TYPE_ANN}\\s*=\\s*\\(*\\s*${ns}(?:${DOT}(\\w+)\\b|${BRACKET_OPEN}\\s*['"\`](\\w+)['"\`]\\s*\\])`, 'g', ), )) { if (src.has((am[2] ?? am[3])!)) locals.add(am[1]!); } } if (locals.size > 0) { for (const m of f.code.matchAll(/export\s*\{([^}]*)\}(?!\s*from)/g)) { for (const part of m[1]!.split(',')) { const seg = part.trim(); if (!seg || seg.startsWith('type ')) continue; const am = /^(\w+)(?:\s+as\s+(\w+))?$/.exec(seg); if (am && locals.has(am[1]!)) mine.add(am[2] ?? am[1]!); } } for (const local of locals) { if ( new RegExp(`export\\s+(?:const|let|var|function)\\s+${DECL_LIST}${local}\\b`).test( f.code, ) ) { mine.add(local); } // A derived binding exported under a NEW name re-exports the // capability under that name: `export const mk2 = (mk);` for (const dm of f.code.matchAll( new RegExp( `export\\s+(?:const|let|var)\\s+${DECL_LIST}(\\w+)${TYPE_ANN}\\s*=\\s*\\(*\\s*${local}\\b`, 'g', ), )) { mine.add(dm[1]!); } } } // The default slot, under any expression dressing — a local factory // binding (`export default (createDb)`) or a namespace factory member // (`export default mod.createDb`, `export default mod['createDb']`) — // mirrors the schema side's default-export pass. for (const m of f.code.matchAll(/export\s+default\s+([^;\n]+)/g)) { const expr = stripExprDressing(m[1]!); if (/^\w+$/.test(expr)) { if (locals.has(expr)) mine.add('default'); } else { for (const [ns, src] of nss) { const t = new RegExp( `^${ns}(?:${DOT}(\\w+)\\b|${BRACKET_OPEN}\\s*['"\`](\\w+)['"\`]\\s*\\])$`, ).exec(expr); if (t && src.has((t[1] ?? t[2])!)) { mine.add('default'); break; } } } } if (mine.size > before) { factoryNames.set(f.rel, mine); changed = true; } } } return { driver, factory: new Set(factoryNames.keys()) }; } /** Value-import edge naming one of `symbols` (named import from anywhere, or literal dynamic package import while using the symbol). */ function hasSymbolImportEdge(code: string, symbols: string[], packageName: string): boolean { const pkg = packageName.replace('/', '\\/'); const staticEdge = new RegExp( `import\\s*(?!type\\b)(?:\\w+\\s*,\\s*)?\\{[^}]*\\b(${symbols.join('|')})\\b[^}]*\\}\\s*from\\s*['"][^'"]+['"]`, ).test(code); const usesSymbol = new RegExp(`\\b(${symbols.join('|')})\\b`).test(code); const dynamicEdge = usesSymbol && new RegExp(`import\\s*\\(\\s*['"]${pkg}['"]\\s*\\)`).test(code); // Namespace form: `import * as ns from ''` + `ns.` usage // (dot or bracket member, optional-chain/non-null tolerant). let nsEdge = false; for (const m of code.matchAll( new RegExp(`import\\s*\\*\\s*as\\s+(\\w+)\\s*from\\s*['"]${pkg}['"]`, 'g'), )) { if (new RegExp(`\\b${m[1]}${memberTail(symbols.join('|'))}`).test(code)) nsEdge = true; } return staticEdge || dynamicEdge || nsEdge; } // --------------------------------------------------------------------------- // The analyzer — pure over (rel, source) so the evasion controls below can // feed synthetic files through the exact production logic. // --------------------------------------------------------------------------- interface AnalysisCtx { fileSet: Set; conduits: SchemaConduits; // schema-symbol sources with exported names (prong i) driverConduits: Set; // driver-capability re-exporters (prong iii) factoryConduits: Set; // factory-capability re-exporters (prong iii) } function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] { const { fileSet, conduits, driverConduits, factoryConduits } = ctx; const violations: Violation[] = []; const rel = f.rel; const code = f.code; const inAllowlist = WRITER_ALLOWLIST.includes(rel); const inRegister = INFRA_REGISTER.includes(rel); const isSchemaDefinition = rel === 'packages/db/src/schema.ts'; // Runtime code construction: fails anywhere. Covers direct calls // (optional-call form included), and literal computed access // (window['eval'], globalThis['Function']). if ( new RegExp( `\\beval${CALL_OPEN}|\\bnew\\s+Function\\s*\\(|\\[\\s*['"](eval|Function)['"]\\s*\\]`, ).test(code) ) { violations.push({ file: rel, prong: 'code-construction', detail: 'eval/new Function' }); } // Fail-closed CODE-SHAPE rules: statically-resolvable disguises of a // literal member key or verb invocation. They match ordinary syntax, so a // reviewed legitimate hit is dispositioned through CODE_SHAPE_REGISTER — // the shapes themselves are never weakened. if (!CODE_SHAPE_REGISTER.includes(rel)) { // A computed member — access or call — whose key is a text-only template // literal is invisible to every member and verb matcher (the lexer routes // template text to spans, so the key survives in code as two ADJACENT // backticks — the discriminator against backticks inside quoted-string // prose, whose text stays in code, and against interpolated keys, whose // `${…}` expression stays in code between the backticks). Runtime code // construction's sibling: fail-closed in any position (write target, // export expression, receiver, call). A template key WITH interpolation // is a non-literal computed member (documented residual above). if (new RegExp(`\\[\\s*\`\`\\s*\\]`).test(code)) { violations.push({ file: rel, prong: 'code-construction', detail: 'template-literal computed member', }); } // A quoted OR template computed key carrying expression dressing // (`ns['companies' as const]`, `ns['companies' satisfies 'companies']`, // `ns['companies'!]`, and the template forms `ns[\`companies\` as // const]`, `ns[\`companies\`!]`) keeps its static value while breaking // every `['name']` matcher — the bracket alternatives require the // closing quote to touch the `]`, and a dressed TEMPLATE key also breaks // the template rule above (dressing intervenes before the `]`). // Tolerance inside the matchers cannot span the class (the dressing's // type text may itself contain a `]`, e.g. `as Foo['x']`), so the SHAPE // fails closed: a quote-close followed by `!`/`as`/`satisfies` inside a // bracket. The key class includes the backtick: a dressed template key // survives in lexed code as the empty adjacent-backtick pair, which the // empty-key case of this regex matches (an interpolated key keeps its // `\${…}` between the backticks and stays clean unless dressed — a // dressed interpolated key fires too, an over-match dispositioned like // any other shape hit). The `!(?!=)` guard keeps ordinary comparisons // (`o['k'] !== x` — dressing AFTER the bracket) clean. if ( new RegExp(`\\[\\s*(['"\`])(?:(?!\\1)[^\\n])*\\1\\s*(?:!(?!=)|as\\s|satisfies\\s)`).test(code) ) { violations.push({ file: rel, prong: 'code-construction', detail: 'dressed computed-member key', }); } // A quoted key built from string escapes (a `\` + `u`/`x`/octal-digit // sequence whose decoded text is a plain identifier, e.g. a key spelling // `companies` with its first letter unicode-escaped) stays invisible to // every `\w+`-keyed matcher. The key IS statically // resolvable, so it is not under the non-literal residual: any bracketed // quoted key containing an identifier-capable escape fails closed. if (new RegExp(`\\[\\s*(['"])[^'"\\n]*\\\\[ux0-7][^'"\\n]*\\1\\s*\\]`).test(code)) { violations.push({ file: rel, prong: 'code-construction', detail: 'escape-built computed-member key', }); } // Invoking a write/exec verb through Function.prototype indirection // (`db.insert.apply(db, [companies])`, `d.execute.call(d, s)`, // `db.insert.bind(db)`) hides the argument shape from every verb matcher // while both member names stay statically visible — unlike the // method-EXTRACTION residual, where the verb never appears as a member. if ( new RegExp( `(?:${DOT}(?:insert|update|delete|execute|query|unsafe|raw)\\b|` + `\\[\\s*['"](?:insert|update|delete|execute|query|unsafe|raw)['"]\\s*\\])` + `${DOT}(?:apply|call|bind)${CALL_OPEN}`, ).test(code) ) { violations.push({ file: rel, prong: 'code-construction', detail: 'verb apply/call/bind indirection', }); } // `Reflect` reaches the same members without member syntax: // `Reflect.apply(db.insert, db, [companies])`, `Reflect.get(db, // 'insert')`, `Reflect.getOwnPropertyDescriptor(db, 'execute')`. Verb // detection through Reflect is not boundable: any argument window stops // at a newline (prettier breaks a >100-col call one-arg-per-line, moving // the verb past it) or at the first `)` (a nested-paren first argument // closes it early), the method can be bracket-spelled // (`Reflect['apply']`), and the object can be aliased // (`const R = Reflect`). So the IDENTIFIER is the shape: any `Reflect` // token in lexed code fails closed — member access, aliasing, or // argument passing alike. The tree has zero occurrences outside test // files (measured); a reviewed legitimate use is register-dispositioned. // (`\b` keeps compound identifiers like `ReflectHelper` clean.) if (new RegExp(`\\bReflect\\b`).test(code)) { violations.push({ file: rel, prong: 'code-construction', detail: 'Reflect indirection', }); } } // Dynamic import whose specifier is not a single string literal: the // import graph becomes unanalyzable. Checked per call site, so a literal // first fragment ('x' + y) does not slip past. A LITERAL import of a // schema/factory source must additionally sit in the tracked binding shape // (const X = await import(…)) — any other consumption of its promise // (.then, deferred await, array wrapping) hides the binding from prong (i), // so it fails closed here. if (!DYNAMIC_IMPORT_REGISTER.includes(rel)) { for (const m of code.matchAll(/\bimport\s*\(/g)) { const idx = m.index ?? 0; const tail = code.slice(idx + m[0].length); const lit = /^\s*(['"])((?:[^'"\\]|\\.)*?)\1\s*[,)]/.exec(tail); if (!lit) { violations.push({ file: rel, prong: 'dynamic-import', detail: 'non-literal import()' }); continue; } const spec = lit[2]!; const schemaSrc = schemaExportsOf(rel, spec, conduits, fileSet); const factoryLike = spec === '@mosaicstack/db' || (() => { const r = resolveSpecifier(rel, spec, fileSet); return r !== null && (factoryConduits.has(r) || driverConduits.has(r)); })() || DRIVER_SPECIFIERS.includes(spec); if (schemaSrc !== null || factoryLike) { const before = code.slice(Math.max(0, idx - 200), idx); if (!/(?:const|let|var)\s*(?:\{[^}]*\}|\w+)\s*=\s*await\s*$/.test(before)) { violations.push({ file: rel, prong: 'dynamic-import', detail: `literal import('${spec}') outside the tracked binding shape`, }); } } } } // createRequire: an unanalyzable CJS import route. Tracked by name AND // through import aliases (import { createRequire as x } / destructured // from a dynamic module import). if (!CREATE_REQUIRE_REGISTER.includes(rel)) { const crNames = new Set(); if (new RegExp(`\\bcreateRequire${CALL_OPEN}`).test(code)) crNames.add('createRequire'); for (const m of code.matchAll(/import\s*\{([^}]*)\}\s*from\s*['"](?:node:)?module['"]/g)) { const alias = /\bcreateRequire\s+as\s+(\w+)/.exec(m[1]!); if (alias) crNames.add(alias[1]!); } for (const m of code.matchAll( /(?:const|let|var)\s*\{([^}]*)\}\s*=\s*await\s+import\s*\(\s*['"](?:node:)?module['"]\s*\)/g, )) { const alias = /\bcreateRequire\s*:\s*(\w+)/.exec(m[1]!); if (alias) crNames.add(alias[1]!); } // Destructuring from a STATIC or dynamically-bound module namespace: // import * as M from 'node:module'; const { createRequire: x } = M; const modNs = new Set(); for (const m of code.matchAll(/import\s*\*\s*as\s+(\w+)\s*from\s*['"](?:node:)?module['"]/g)) { modNs.add(m[1]!); } for (const m of code.matchAll( /(?:const|let|var)\s+(\w+)\s*=\s*await\s+import\s*\(\s*['"](?:node:)?module['"]\s*\)/g, )) { modNs.add(m[1]!); } for (const ns of modNs) { for (const m of code.matchAll( new RegExp(`(?:const|let|var)\\s*\\{([^}]*)\\}\\s*=\\s*${ns}\\b`, 'g'), )) { const alias = /\bcreateRequire\s*(?::\s*(\w+))?/.exec(m[1]!); if (alias) crNames.add(alias[1] ?? 'createRequire'); } } for (const n of crNames) { if (n === 'createRequire' || new RegExp(`\\b${n}${CALL_OPEN}`).test(code)) { violations.push({ file: rel, prong: 'dynamic-import', detail: 'createRequire()' }); break; } } } const aliases = classAliases(f, conduits, fileSet); // Prong (i): schema-symbol writes — alias-, namespace-, and conduit-aware. if (!inAllowlist) { // Word boundaries live inside each alternative: the bracket form ends in // `]` (non-word), where a trailing `\b` could never match. const targets: string[] = [...aliases.named].map((a) => `${a}\\b`); // Namespace members match the source's EXPORTED names (renames included), // not just the original class symbols. const symAlt = [...aliases.memberSyms].join('|'); for (const ns of aliases.namespaces) { // Allow intermediate property segments (ns.schema.companies — nested // namespace re-exports), literal computed access (ns['companies']), // and optional-chain/non-null markers (ns?.companies, ns!.companies). targets.push(`${ns}${MEMBER_SEG}*${memberTail(symAlt)}`); } if (targets.length > 0) { // The argument prefix tolerates parenthesization, spread, and array // wrapping: .insert((companies)), .insert(...[companies]). const writeRe = new RegExp( `\\.\\s*(insert|update|delete)${CALL_OPEN}\\s*(?:(?:\\(|\\[|\\.\\.\\.)\\s*)*(${targets.join('|')})`, 'g', ); for (const m of code.matchAll(writeRe)) { violations.push({ file: rel, prong: 'i-symbol', detail: `.${m[1]}(${m[2]}) outside the writer allowlist`, }); } } } // Computed member access with a literal verb name (obj['insert'](…)) // bypasses dot-based call detection; the tree has no legitimate use of the // form (measured), so it fails outright. Write verbs fail outside the // allowlist; execution verbs fail outside allowlist ∪ register. if (!inAllowlist) { const writeBracket = new RegExp( `\\[\\s*['"](insert|update|delete)['"]\\s*\\]${CALL_OPEN}`, 'g', ); for (const m of code.matchAll(writeBracket)) { violations.push({ file: rel, prong: 'i-symbol', detail: `['${m[1]}']() computed-member write call`, }); } if (!inRegister) { for (const m of code.matchAll( new RegExp(`\\[\\s*['"](execute|query|unsafe)['"]\\s*\\]${CALL_OPEN}`, 'g'), )) { violations.push({ file: rel, prong: 'iii-raw-execution', detail: `['${m[1]}']() computed-member execution call`, }); } } } // Prong (ii): class-table names in string/template spans with SQL context. // The SQL keyword must be ADJACENT to the table name — co-residence // anywhere in one span over-matches prose ("pnpm workspaces" plus an // unrelated "from" in an embedded doc string is not SQL). Adjacency // tolerates schema qualification (public.hierarchy_grants), bare // qualifier words (TABLE, ONLY, IF EXISTS), interposed block comments, // and quoting (including escaped quotes in span text). if (!inAllowlist && !isSchemaDefinition) { const kw = '(?:insert\\s+into|update|delete\\s+from|from|join|truncate(?:\\s+table)?|alter\\s+table|drop\\s+table|references|into|copy|on|lock(?:\\s+table)?)'; const gap = '(?:\\s|/\\*[\\s\\S]*?\\*/|--[^\\n]*\\n)+'; // Bare qualifier words may sit between keyword and table name: // GRANT … ON TABLE t, DELETE FROM ONLY t, DROP TABLE IF EXISTS t. const qual = `(?:(?:table|only|if\\s+exists)${gap})*`; const q = `(?:\\\\?["'\`])?`; const sqlAdjacentRe = new RegExp( `\\b${kw}${gap}${qual}${q}(?:${q}\\w+${q}\\s*\\.\\s*)?${q}(${CLASS_TABLES.join('|')})\\b`, 'i', ); for (const span of f.spans) { if (sqlAdjacentRe.test(span)) { violations.push({ file: rel, prong: 'ii-literal', detail: `class-table name in SQL context: ${span.slice(0, 80)}`, }); } } } // Prong (iii): content-independent raw execution. if (!inAllowlist && !inRegister) { const literalDriver = new RegExp( `(from\\s*|import\\s*\\(\\s*)['"](${DRIVER_SPECIFIERS.map((s) => s.replace('/', '\\/')).join('|')})['"]`, ).test(code); // Any value import from a driver conduit confers driver capability. let conduitDriver = false; let factoryConduitImport = false; for (const m of f.code.matchAll(IMPORT_RE)) { if (m[1]) continue; // import type — erased const r = resolveSpecifier(rel, m[6]!, fileSet); if (r !== null && driverConduits.has(r)) conduitDriver = true; if (r !== null && factoryConduits.has(r)) factoryConduitImport = true; } // A TRACKED dynamic import of a conduit is an import edge like any // static one (contract rev 9) — for capability too, not just prong (i). for (const m of f.code.matchAll(/=\s*await\s+import\s*\(\s*(['"])([^'"]+)\1\s*\)/g)) { const r = resolveSpecifier(rel, m[2]!, fileSet); if (r !== null && driverConduits.has(r)) conduitDriver = true; if (r !== null && factoryConduits.has(r)) factoryConduitImport = true; } const driverImport = literalDriver || conduitDriver; // Factory capability: a named/namespace edge to the factory symbols, OR // ANY value import from a factory conduit — the conduit may re-export // the factory under a different name (export { createDb as default }), // so the consumer-side name gate is dropped for conduit imports. const factoryImport = factoryConduitImport || hasSymbolImportEdge(code, DB_FACTORY_SYMBOLS, '@mosaicstack/db') || (aliases.namespaces.length > 0 && new RegExp( `\\b(?:${aliases.namespaces.join('|')})${MEMBER_SEG}*${memberTail('createDb|createPgliteDb')}`, ).test(code)) || // Destructuring a factory symbol OUT of a schema namespace confers // capability whatever the local rename: const { createDb: mk } = dbns. (aliases.namespaces.length > 0 && new RegExp( `(?:const|let|var)\\s*\\{[^}]*\\b(?:createDb|createPgliteDb)\\b[^}]*\\}\\s*=\\s*(?:await\\s+)?(?:${aliases.namespaces.join('|')})\\b`, ).test(code)); if (driverImport) { violations.push({ file: rel, prong: 'iii-raw-execution', detail: 'direct driver import' }); // A driver client exposes query/execute/unsafe as raw primitives: // flag them all on any receiver, any argument, spaced, optional-call // (`?.(`) or not. for (const m of code.matchAll(new RegExp(`\\.\\s*(execute|query|unsafe)${CALL_OPEN}`, 'g'))) { violations.push({ file: rel, prong: 'iii-raw-execution', detail: `.${m[1]}() in a driver-importing module`, }); } } else if (factoryImport) { // A drizzle handle's raw primitive is .execute (its .query namespace is // the relational builder, and unrelated .query() methods are common), // so factory capability flags execute/unsafe on any receiver and query // only on the db/client-shaped receiver backstop below. for (const m of code.matchAll(new RegExp(`\\.\\s*(execute|unsafe)${CALL_OPEN}`, 'g'))) { violations.push({ file: rel, prong: 'iii-raw-execution', detail: `.${m[1]}() in a factory-importing module`, }); } } if (!driverImport) { // DI residual backstop: db/client-shaped receivers fire regardless of // detected capability (a handle can arrive by injection). // The receiver may be a dotted name OR a literal bracketed member with // a conventional name — this['db'].query(…) — and the final member // access tolerates ?. and ! markers (this.db?.query(…)). for (const m of code.matchAll( new RegExp( `(?:\\b(?:db|database|client|conn|connection|pool|pg|pglite|tx|trx)|\\[\\s*['"](?:db|database|client|conn|connection|pool|pg|pglite|tx|trx)['"]\\s*\\])${DOT}(execute|query|unsafe)${CALL_OPEN}`, 'g', ), )) { violations.push({ file: rel, prong: 'iii-raw-execution', detail: `.${m[1]}() on a db-shaped receiver`, }); } } // sql.raw through aliases and namespaces (drizzle-orm and the db barrel). const sqlAliases = new Set(); for (const m of code.matchAll(IMPORT_RE)) { const [, typeOnly, , namedList, nsName, , spec] = m; if (typeOnly) continue; if (!/^drizzle-orm|^@mosaicstack\/db$/.test(spec!)) continue; if (namedList) { for (const part of namedList.split(',')) { const seg = part.trim(); const asMatch = /^sql\s+as\s+(\w+)$/.exec(seg); if (seg === 'sql') sqlAliases.add('sql'); else if (asMatch) sqlAliases.add(asMatch[1]!); } } if (nsName) sqlAliases.add(`${nsName}\\s*\\.\\s*sql`); } if (sqlAliases.size > 0) { const rawRe = new RegExp(`\\b(${[...sqlAliases].join('|')})\\s*\\.\\s*raw${CALL_OPEN}`); if (rawRe.test(code)) { violations.push({ file: rel, prong: 'iii-raw-execution', detail: 'sql.raw()' }); } } } return violations; } // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- describe('hierarchy writer coverage (contract 1 §6.3b)', () => { const sourceRels = collectSources(); const fileSet = new Set(sourceRels); const files: FileFacts[] = sourceRels.map((rel) => { const { code, spans } = lexSource(readFileSync(join(REPO_ROOT, rel), 'utf8')); return { rel, code, spans }; }); const conduits = computeSchemaConduits(files, fileSet); const capConduits = computeCapabilityConduits(files, fileSet); const ctx: AnalysisCtx = { fileSet, conduits, driverConduits: capConduits.driver, factoryConduits: capConduits.factory, }; it('scans a non-empty production source set including plugins', () => { expect(files.length).toBeGreaterThan(100); expect(sourceRels.some((r) => r.startsWith('plugins/'))).toBe(true); }); it('enumerated modules exist on disk (no stale allowlist/register entries)', () => { for (const p of [ ...WRITER_ALLOWLIST, ...INFRA_REGISTER, ...MIGRATION_RUNNER_IMPORTERS, ...MIGRATE_TIER_IMPORTERS, ...DB_FACTORY_IMPORTERS, ...DYNAMIC_IMPORT_REGISTER, ...CREATE_REQUIRE_REGISTER, ]) { expect(existsSync(join(REPO_ROOT, p)), `enumerated module missing: ${p}`).toBe(true); } }); it('no registered module appears on the writer allowlist', () => { for (const p of INFRA_REGISTER) { expect(WRITER_ALLOWLIST, `register/allowlist overlap: ${p}`).not.toContain(p); } }); it('three-prong writer coverage holds over the production tree', () => { const violations = files.flatMap((f) => analyzeFile(f, ctx)); expect( violations, violations.map((v) => `[prong ${v.prong}] ${v.file}: ${v.detail}`).join('\n'), ).toEqual([]); }); it('migration-runner import edges are exactly the closed importer enumeration', () => { const offenders: string[] = []; for (const f of files) { if (f.rel.startsWith('packages/db/src/')) continue; // the runner's own package if (!new RegExp(`\\b(${MIGRATION_RUNNER_SYMBOLS.join('|')})\\b`).test(f.code)) continue; if ( hasSymbolImportEdge(f.code, MIGRATION_RUNNER_SYMBOLS, '@mosaicstack/db') && !MIGRATION_RUNNER_IMPORTERS.includes(f.rel) ) { offenders.push(f.rel); } } expect(offenders, `unenumerated migration-runner importers:\n${offenders.join('\n')}`).toEqual( [], ); }); it('migrate-tier import edges are exactly the closed importer enumeration', () => { const offenders: string[] = []; for (const f of files) { if (f.rel === 'packages/storage/src/migrate-tier.ts') continue; const pathEdge = /from\s*['"][^'"]*migrate-tier(\.js)?['"]/.test(f.code) || /import\s*\(\s*['"][^'"]*migrate-tier(\.js)?['"]\s*\)/.test(f.code); const symbolEdge = new RegExp(`\\b(${MIGRATE_TIER_SYMBOLS.join('|')})\\b`).test(f.code) && hasSymbolImportEdge(f.code, MIGRATE_TIER_SYMBOLS, '@mosaicstack/storage'); if ((pathEdge || symbolEdge) && !MIGRATE_TIER_IMPORTERS.includes(f.rel)) { offenders.push(f.rel); } } expect(offenders, `unenumerated migrate-tier importers:\n${offenders.join('\n')}`).toEqual([]); }); it('db-factory (createDb/createPgliteDb) import edges are exactly the closed importer enumeration', () => { const offenders: string[] = []; for (const f of files) { if (f.rel.startsWith('packages/db/src/')) continue; // the factories' own package if (!new RegExp(`\\b(${DB_FACTORY_SYMBOLS.join('|')})\\b`).test(f.code)) continue; if ( hasSymbolImportEdge(f.code, DB_FACTORY_SYMBOLS, '@mosaicstack/db') && !DB_FACTORY_IMPORTERS.includes(f.rel) ) { offenders.push(f.rel); } } expect(offenders, `unenumerated db-factory importers:\n${offenders.join('\n')}`).toEqual([]); }); // ------------------------------------------------------------------------- // Permanent evasion controls: every known escape from the M4-1a review must // be flagged by the analyzer, and the two legitimate controls must pass. // Synthetic files run through the exact production analyzer. // ------------------------------------------------------------------------- const EVASIONS: Array<{ name: string; src: string; extras?: Array<{ rel: string; src: string }>; }> = [ { name: 'E1 namespace import write', src: `import * as dbSchema from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(dbSchema.companies).values({}); }`, }, { name: 'E2 re-export laundering (conduit consumer)', src: `import { companies } from './evasion-barrel.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(companies).values({}); }`, }, { name: 'E3 renamed createDb handle', src: `import { createDb } from '@mosaicstack/db';\nexport async function f(t: string) { const d = createDb('u'); await d.execute('DELETE FROM ' + t); }`, }, { name: 'E4 aliased sql.raw', src: `import { sql as q } from 'drizzle-orm';\nimport { db } from './x.js';\nexport async function f(t: string) { await db.execute(q.raw('TRUNCATE ' + t)); }`, }, { name: 'E5 interpolated tagged template on db receiver', src: `import { sql } from 'drizzle-orm';\nimport { db } from './x.js';\nexport async function f() { const tbl = 'hierarchy_grants'; await db.execute(sql\`DELETE FROM \${tbl}\`); }`, }, { name: 'E6 driver client via import', src: `import postgres from 'postgres';\nexport async function f(t: string) { const c = postgres('u'); await c.unsafe('TRUNCATE ' + t); }`, }, { name: 'E7 DI-shaped driver client query', src: `export class R { constructor(private client: { query(s: string): Promise }) {}\n async f(t: string) { await this.client.query('TRUNCATE ' + t); } }`, }, { name: 'E8 string containing // does not hide code', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { const x = 'oops//'; await db.insert(companies).values({}); }`, }, { name: 'C-literal SQL string with class table', src: `export const q = 'DELETE FROM hierarchy_grants WHERE role = $1';`, }, { name: 'C-eval', src: `export function f(s: string) { return eval(s); }`, }, // --- round-2 review shapes (R1–R5) --- { name: 'E9 namespace destructuring', src: `import * as dbSchema from '@mosaicstack/db';\nimport { db } from './x.js';\nconst { companies } = dbSchema;\nexport async function f() { await db.insert(companies).values({}); }`, }, { name: 'E10 nested namespace re-export', src: `import * as ns from './evasion-mid.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns.schema.companies).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid.ts', src: `export * as schema from '@mosaicstack/db';`, }, ], }, { name: 'E11 literal dynamic import, destructured binding', src: `import { db } from './x.js';\nexport async function f() { const { companies } = await import('@mosaicstack/db'); await db.insert(companies).values({}); }`, }, { name: 'E12 literal dynamic import, namespace binding', src: `import { db } from './x.js';\nexport async function f() { const m = await import('@mosaicstack/db'); await db.insert(m.companies).values({}); }`, }, { name: 'E13 createRequire outside its register', src: `import { createRequire } from 'node:module';\nconst require = createRequire(import.meta.url);\nexport const pg = require('postgres');`, }, { name: 'E14 factory capability laundered through re-export', src: `import * as dbns from './evasion-mid2.js';\nexport async function f(t: string) { await dbns.createDb('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid2.ts', src: `export { createDb } from '@mosaicstack/db';`, }, ], }, { name: 'E15 driver default laundered through re-export', src: `import pg from './evasion-mid3.js';\nexport async function f(t: string) { const c = pg('u'); await c.unsafe('TRUNCATE ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid3.ts', src: `export { default } from 'postgres';`, }, ], }, { name: 'E16 concatenated dynamic-import specifier', src: `export async function f() { const m = await import('@mosaicstack/' + 'db'); return m; }`, }, { name: 'E17 computed-member write call', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db['insert'](companies).values({}); }`, }, { name: 'E18 spaced member access write', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db . insert (companies).values({}); }`, }, { name: 'E19 computed-member execution call', src: `export class R { constructor(private client: { query(s: string): Promise }) {}\n async f(t: string) { await this.client['query']('TRUNCATE ' + t); } }`, }, { name: 'E20 schema-qualified table in SQL span', src: `export const q = 'DELETE FROM public.hierarchy_grants WHERE role = $1';`, }, { name: 'E21 comment interposed in SQL span', src: `export const q = 'DELETE FROM /* audit */ hierarchy_grants WHERE role = $1';`, }, { name: 'E22 COPY statement in SQL span', src: `export const q = 'COPY hierarchy_grants FROM STDIN';`, }, { name: 'E23 escaped-backtick-quoted table in SQL span', src: 'export const q = `DELETE FROM \\`hierarchy_grants\\` WHERE role = 1`;', }, // --- round-3 review shapes (G1–G6) --- { name: 'E24 export-site rename through conduit', src: `import { c } from './evasion-mid4.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid4.ts', src: `export { companies as c } from '@mosaicstack/db';`, }, ], }, { name: 'E25 export of locally bound alias, renamed', src: `import { co } from './evasion-mid5.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid5.ts', src: `import { companies } from '@mosaicstack/db';\nexport { companies as co };`, }, ], }, { name: 'E26 alias-export helper over dynamic namespace', src: `import { co } from './evasion-mid6.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid6.ts', src: `const mod = await import('@mosaicstack/db');\nexport const co = mod.companies;`, }, ], }, { name: 'E27 single-const alias from namespace', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nconst t = ns.companies;\nexport async function f() { await db.insert(t).values({}); }`, }, { name: 'E28 non-class destructure from namespace (fail-closed)', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nconst { schema } = ns;\nexport async function f() { await db.insert(schema.companies).values({}); }`, }, { name: 'E29 destructure with default value', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nconst { companies: co = null } = ns;\nexport async function f() { await db.insert(co).values({}); }`, }, { name: 'E30 factory renamed to default through conduit', src: `import createDbNow from './evasion-mid7.js';\nexport async function f(t: string) { await createDbNow('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid7.ts', src: `export { createDb as default } from '@mosaicstack/db';`, }, ], }, { name: 'E31 factory alias-export helper over dynamic namespace', src: `import { mk } from './evasion-mid8.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid8.ts', src: `const mod = await import('@mosaicstack/db');\nexport const mk = mod.createDb;`, }, ], }, { name: 'E32 createRequire import alias', src: `import { createRequire as mkReq } from 'node:module';\nconst req = mkReq(import.meta.url);\nexport const pg = req('postgres');`, }, { name: 'E33 then-form dynamic schema import', src: `import { db } from './x.js';\nexport function f() { return import('@mosaicstack/db').then((m) => db.insert(m.companies).values({})); }`, }, { name: 'E34 quoted schema qualifier in SQL span', src: `export const q = 'DELETE FROM "public".hierarchy_grants WHERE role = $1';`, }, { name: 'E35 SQL line comment interposed in SQL span', src: 'export const q = `DELETE FROM -- audit\nhierarchy_grants`;', }, { name: 'E36 spaced member access on conventional receiver', src: `export class R { constructor(private db: { query(s: string): Promise }) {}\n async f(t: string) { await this.db . query ('TRUNCATE ' + t); } }`, }, { name: 'E37 bracket-form schema argument', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns['companies']).values({}); }`, }, { name: 'E38 parenthesized schema argument', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert((companies)).values({}); }`, }, { name: 'E39 computed-member eval', src: `export function f(s: string) { return (globalThis as never)['eval'](s); }`, }, { name: 'E40 schema symbol renamed to default through conduit', src: `import c from './evasion-mid9.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid9.ts', src: `export { companies as default } from '@mosaicstack/db';`, }, ], }, { name: 'E41 export default of locally bound schema symbol', src: `import c from './evasion-mid10.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid10.ts', src: `import { companies } from '@mosaicstack/db';\nexport default companies;`, }, ], }, { name: 'E42 export default of dynamic namespace member', src: `import c from './evasion-mid11.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid11.ts', src: `const mod = await import('@mosaicstack/db');\nexport default mod.companies;`, }, ], }, { name: 'E43 namespace member under renamed export', src: `import * as M from './evasion-mid12.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(M.co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid12.ts', src: `export { companies as co } from '@mosaicstack/db';`, }, ], }, { name: 'E44 dynamic namespace member under renamed export', src: `import { db } from './x.js';\nconst M = await import('./evasion-mid13.js');\nexport async function f() { await db.insert(M.co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid13.ts', src: `export { companies as co } from '@mosaicstack/db';`, }, ], }, { name: 'E45 two-hop factory export-from rename', src: `import { mk } from './evasion-mid15.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid14.ts', src: `export { createDb as mk } from '@mosaicstack/db';`, }, { rel: 'packages/db/src/evasion-mid15.ts', src: `export { mk } from './evasion-mid14.js';`, }, ], }, { name: 'E46 export default of locally bound factory', src: `import mk from './evasion-mid16.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid16.ts', src: `import { createDb } from '@mosaicstack/db';\nexport default createDb;`, }, ], }, { name: 'E47 tracked dynamic import of a factory conduit', src: `const F = await import('./evasion-mid17.js');\nexport async function f(t: string) { await F.mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid17.ts', src: `export { createDb as mk } from '@mosaicstack/db';`, }, ], }, { name: 'E48 factory destructure-rename from schema namespace', src: `import * as dbns from '@mosaicstack/db';\nconst { createDb: mk } = dbns;\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, }, { name: 'E49 createRequire destructured from static module namespace', src: `import * as M from 'node:module';\nconst { createRequire: mkReq } = M;\nconst req = mkReq(import.meta.url);\nexport const pg = req('postgres');`, }, { name: 'E50 spread-argument schema write', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(...[companies]).values({}); }`, }, { name: 'E51 GRANT ON class table in SQL span', src: `export const q = 'GRANT SELECT ON hierarchy_grants TO auditor';`, }, { name: 'E52 LOCK TABLE class table in SQL span', src: `export const q = 'LOCK TABLE hierarchy_grants IN ACCESS EXCLUSIVE MODE';`, }, { name: 'E53 bracketed conventional receiver', src: `export class R { async f(t: string) { await this['db'].query('TRUNCATE ' + t); } }`, }, { name: 'E54 parenthesized default export of schema symbol', src: `import c from './evasion-mid18.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid18.ts', src: `import { companies } from '@mosaicstack/db';\nexport default (companies);`, }, ], }, { name: 'E55 bracket-member default export over dynamic namespace', src: `import c from './evasion-mid19.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid19.ts', src: `const mod = await import('@mosaicstack/db');\nexport default mod['companies'];`, }, ], }, { name: 'E56 type-asserted default export of schema symbol', src: `import c from './evasion-mid20.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid20.ts', src: `import { companies } from '@mosaicstack/db';\nexport default companies as unknown as object;`, }, ], }, { name: 'E57 export-const bracket member of schema namespace', src: `import { co } from './evasion-mid21.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid21.ts', src: `import * as ns from '@mosaicstack/db';\nexport const co = ns['companies'];`, }, ], }, { name: 'E58 default export of dynamic namespace factory member', src: `import mk from './evasion-mid22.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid22.ts', src: `const mod = await import('@mosaicstack/db');\nexport default mod.createDb;`, }, ], }, { name: 'E59 default export of static namespace factory member', src: `import mk from './evasion-mid23.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid23.ts', src: `import * as ns from '@mosaicstack/db';\nexport default ns.createDb;`, }, ], }, { name: 'E60 export-const bracket factory member', src: `import { mk } from './evasion-mid24.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid24.ts', src: `import * as ns from '@mosaicstack/db';\nexport const mk = ns['createDb'];`, }, ], }, { name: 'E61 parenthesized default export of factory local', src: `import mk from './evasion-mid25.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid25.ts', src: `import { createDb } from '@mosaicstack/db';\nexport default (createDb);`, }, ], }, { name: 'E62 GRANT ON TABLE class table in SQL span', src: `export const q = 'GRANT SELECT ON TABLE hierarchy_grants TO auditor';`, }, { name: 'E63 DROP TABLE IF EXISTS class table in SQL span', src: `export const q = 'DROP TABLE IF EXISTS hierarchy_grants';`, }, { name: 'E64 DELETE FROM ONLY class table in SQL span', src: `export const q = 'DELETE FROM ONLY hierarchy_grants WHERE id = $1';`, }, { name: 'E65 optional-chained namespace write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns?.companies).values({}); }`, }, { name: 'E66 non-null-asserted namespace write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns!.companies).values({}); }`, }, { name: 'E67 optional-chained DI receiver', src: `export class R { constructor(private db?: { query(s: string): Promise }) {}\n async f(t: string) { await this.db?.query('TRUNCATE ' + t); } }`, }, { name: 'E68 optional-chained bracketed DI receiver', src: `export class R { async f(t: string) { await this['db']?.query('TRUNCATE ' + t); } }`, }, { name: 'E69 non-null-asserted default export of schema symbol', src: `import c from './evasion-mid26.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid26.ts', src: `import { companies } from '@mosaicstack/db';\nexport default companies!;`, }, ], }, { name: 'E70 satisfies-dressed default export of schema symbol', src: `import c from './evasion-mid27.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid27.ts', src: `import { companies } from '@mosaicstack/db';\nexport default companies satisfies object;`, }, ], }, { name: 'E71 paren-plus-assertion-plus-non-null default export', src: `import c from './evasion-mid28.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid28.ts', src: `import { companies } from '@mosaicstack/db';\nexport default (companies as unknown)!;`, }, ], }, { name: 'E72 non-null-asserted ns-member default export (dynamic ns)', src: `import c from './evasion-mid29.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid29.ts', src: `const mod = await import('@mosaicstack/db');\nexport default mod.companies!;`, }, ], }, { name: 'E73 parenthesized ns-member export-const of schema symbol', src: `import { co } from './evasion-mid30.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid30.ts', src: `import * as ns from '@mosaicstack/db';\nexport const co = (ns.companies);`, }, ], }, { name: 'E74 non-null-asserted default export of factory local', src: `import mk from './evasion-mid31.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid31.ts', src: `import { createDb } from '@mosaicstack/db';\nexport default createDb!;`, }, ], }, { name: 'E75 non-null-asserted ns-member factory default export', src: `import mk from './evasion-mid32.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid32.ts', src: `import * as ns from '@mosaicstack/db';\nexport default ns.createDb!;`, }, ], }, { name: 'E76 satisfies-dressed default export of factory local', src: `import mk from './evasion-mid33.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid33.ts', src: `import { createDb } from '@mosaicstack/db';\nexport default createDb satisfies typeof createDb;`, }, ], }, { name: 'E77 parenthesized ns-member factory derivation re-exported', src: `import mk from './evasion-mid34.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid34.ts', src: `import * as ns from '@mosaicstack/db';\nconst mk = (ns.createDb);\nexport default mk;`, }, ], }, { name: 'E78 optional-call write verb', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert?.(companies).values({}); }`, }, { name: 'E79 optional-call DI receiver chain', src: `export class R { constructor(private pool?: { execute(s: string): Promise }) {}\n async f(t: string) { await this.pool?.execute?.('TRUNCATE ' + t); } }`, }, { name: 'E80 optional-call execution in factory-capable file', src: `import { createDb } from '@mosaicstack/db';\nexport async function f(t: string) { const d = createDb('u'); await d.execute?.('DELETE FROM ' + t); }`, }, { name: 'E81 template-literal computed member call', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db[\`insert\`](companies).values({}); }`, }, { name: 'E82 template-literal computed member as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns[\`companies\`]).values({}); }`, }, { name: 'E83 template-literal computed member in schema default export', src: `import c from './evasion-mid35.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid35.ts', src: `import * as ns from '@mosaicstack/db';\nexport default ns[\`companies\`];`, }, ], }, { name: 'E84 template-literal computed member in factory extraction', src: `import { mk } from './evasion-mid36.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid36.ts', src: `import * as ns from '@mosaicstack/db';\nexport const mk = ns[\`createDb\`];`, }, ], }, { name: 'E85 type-annotated re-export of schema binding', src: `import { co } from './evasion-mid37.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid37.ts', src: `import { companies } from '@mosaicstack/db';\nexport const co: typeof companies = companies;`, }, ], }, { name: 'E86 second-declarator re-export of schema binding', src: `import { co } from './evasion-mid38.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid38.ts', src: `import { companies } from '@mosaicstack/db';\nexport const dummy = 0,\n co = companies;`, }, ], }, { name: 'E87 type-annotated re-export of factory binding', src: `import { mk } from './evasion-mid39.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid39.ts', src: `import { createDb } from '@mosaicstack/db';\nexport const mk: typeof createDb = createDb;`, }, ], }, { name: 'E88 second-declarator re-export of factory binding', src: `import { mk } from './evasion-mid40.js';\nexport async function f(t: string) { await mk('u').execute('DELETE FROM ' + t); }`, extras: [ { rel: 'packages/db/src/evasion-mid40.ts', src: `import { createDb } from '@mosaicstack/db';\nexport const d0 = 0,\n mk = createDb;`, }, ], }, { name: 'E89 apply-invoked write verb', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert.apply(db, [companies]).values({}); }`, }, { name: 'E90 call-invoked write verb', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert.call(db, companies).values({}); }`, }, { name: 'E91 apply-invoked bracket verb in capability-free file', src: `export class R { constructor(private pool: { execute(s: string): Promise }) {}\n async f(t: string) { await this.pool['execute'].apply(this.pool, ['TRUNCATE ' + t]); } }`, }, { name: 'E92 template-keyed receiver verb in capability-free file', src: `export class R { constructor(private pool: { execute(s: string): Promise }) {}\n async f(t: string) { await this.pool[\`execute\`].apply(this.pool, ['TRUNCATE ' + t]); } }`, }, { name: 'E93 as-dressed computed key as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns['companies' as const]).values({}); }`, }, { name: 'E94 satisfies-dressed computed key as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns['companies' satisfies 'companies']).values({}); }`, }, { name: 'E95 non-null-dressed computed key as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns['companies'!]).values({}); }`, }, { name: 'E96 escape-built computed key as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns['\\u0063ompanies']).values({}); }`, }, { name: 'E97 dressed computed key in schema conduit export', src: `import { co } from './evasion-mid41.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid41.ts', src: `import * as ns from '@mosaicstack/db';\nexport const co = ns['companies' as const];`, }, ], }, { name: 'E98 dressed computed key in schema default export', src: `import c from './evasion-mid42.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(c).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid42.ts', src: `import * as ns from '@mosaicstack/db';\nexport default ns['companies' as const];`, }, ], }, { name: 'E99 dressed computed key in single-file factory extraction', src: `import * as ns from '@mosaicstack/db';\nexport async function f(t: string) { const mk = ns['createDb' as const]; const d = mk('u'); await d.execute('DELETE FROM ' + t); }`, }, { name: 'E100 Reflect.apply of a write verb', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await Reflect.apply(db.insert, db, [companies]); }`, }, { name: 'E101 Reflect.apply of an execution verb in capability-free file', src: `export class R { constructor(private pool: { execute(s: string): Promise }) {}\n async f(t: string) { await Reflect.apply(this.pool.execute, this.pool, ['TRUNCATE ' + t]); } }`, }, { name: 'E102 Reflect.get extraction of an execution verb', src: `import { db } from './x.js';\nexport async function f(t: string) { const fn = Reflect.get(db, 'execute') as (s: string) => Promise; await fn.call(db, 'DELETE FROM ' + t); }`, }, { name: 'E103 as-dressed template key as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns[\`companies\` as const]).values({}); }`, }, { name: 'E104 as-dressed template key as verb call', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db[\`insert\` as const](companies).values({}); }`, }, { name: 'E105 non-null-dressed template key as write target', src: `import * as ns from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await db.insert(ns[\`companies\`!]).values({}); }`, }, { name: 'E106 dressed template receiver verb in capability-free file', src: `export class R { constructor(private pool: { query(s: string): Promise }) {}\n async f(t: string) { await this.pool[\`query\` as const]('TRUNCATE ' + t); } }`, }, { name: 'E107 dressed template key in schema conduit export', src: `import { co } from './evasion-mid43.js';\nimport { db } from './x.js';\nexport async function f() { await db.insert(co).values({}); }`, extras: [ { rel: 'packages/db/src/evasion-mid43.ts', src: `import * as ns from '@mosaicstack/db';\nexport const co = ns[\`companies\` as const];`, }, ], }, { name: 'E108 dressed template key in single-file factory extraction', src: `import * as ns from '@mosaicstack/db';\nexport async function f(t: string) { const mk = ns[\`createDb\` as const]; const d = mk('u'); await d.execute('DELETE FROM ' + t); }`, }, { name: 'E109 multiline Reflect.apply in prettier-broken shape', src: `export class R { constructor(private pool: { execute(s: string): Promise }) {}\n async f(t: string) {\n await Reflect.apply(\n this.pool.execute,\n this.pool,\n ['TRUNCATE ' + t],\n );\n } }`, }, { name: 'E110 bracket-spelled Reflect method', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await Reflect['apply'](db.insert, db, [companies]); }`, }, { name: 'E111 Reflect.apply with nested-paren first argument', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { await Reflect.apply((fn: () => unknown) => fn(), db.insert, [db, [companies]]); }`, }, { name: 'E112 aliased Reflect', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { const R = Reflect; await R.apply(db.insert, db, [companies]); }`, }, ]; const CLEAN_CONTROLS: Array<{ name: string; src: string }> = [ { name: 'clean: schema read via select', src: `import { companies } from '@mosaicstack/db';\nimport { db } from './x.js';\nexport async function f() { return db.select().from(companies); }`, }, { name: 'clean: comment mentioning a table is not SQL', src: `// syncs hierarchy_grants downstream\nexport const n = 1;`, }, { name: 'clean: interpolated template key is a non-literal computed member, not a text-only key', src: `export function g(o: Record void>, k: string) { o[\`\${k}\`](); }`, }, { name: 'clean: strict-inequality after a bracket member is not key dressing', src: `export function h(o: Record) { return o['kind'] !== 'x'; }`, }, { name: 'clean: undressed interpolated template key stays a non-literal member under the backtick key class', src: `export function j(o: Record, k: string) { return o[\`\${k}\`]; }`, }, { name: 'clean: compound identifier containing Reflect is not the Reflect object', src: `export class ReflectHelper { reflectStyle = 1; }\n// Reflect in a comment is prose, not code`, }, ]; it('analyzer flags every known evasion form', () => { // A synthetic conduit so E2 exercises the fixpoint through a real re-export. const barrel: FileFacts = { rel: 'packages/db/src/evasion-barrel.ts', ...lexSource(`export { companies } from '@mosaicstack/db';`), }; for (const e of EVASIONS) { const rel = 'packages/db/src/evasion-sample.ts'; const synthetic: FileFacts = { rel, ...lexSource(e.src) }; const extraFacts: FileFacts[] = (e.extras ?? []).map((x) => ({ rel: x.rel, ...lexSource(x.src), })); const synthFiles = [...files, barrel, ...extraFacts, synthetic]; const synthSet = new Set([...fileSet, rel, barrel.rel, ...extraFacts.map((x) => x.rel)]); const synthCap = computeCapabilityConduits(synthFiles, synthSet); const synthCtx: AnalysisCtx = { fileSet: synthSet, conduits: computeSchemaConduits(synthFiles, synthSet), driverConduits: synthCap.driver, factoryConduits: synthCap.factory, }; // An evasion is caught when ANY file in the chain is flagged: some // laundering routes fail closed at the HELPER (origin), not the // consumer — e.g. a template-keyed conduit export — which keeps the // chain out of the tree just as effectively. const v = [synthetic, ...extraFacts].flatMap((ff) => analyzeFile(ff, synthCtx)); expect(v.length, `evasion not caught: ${e.name}`).toBeGreaterThan(0); } }); it('analyzer passes legitimate non-writer code (no false positives on controls)', () => { for (const c of CLEAN_CONTROLS) { const rel = 'packages/db/src/clean-sample.ts'; const synthetic: FileFacts = { rel, ...lexSource(c.src) }; const synthFiles = [...files, synthetic]; const synthSet = new Set([...fileSet, rel]); const synthCap = computeCapabilityConduits(synthFiles, synthSet); const synthCtx: AnalysisCtx = { fileSet: synthSet, conduits: computeSchemaConduits(synthFiles, synthSet), driverConduits: synthCap.driver, factoryConduits: synthCap.factory, }; const v = analyzeFile(synthetic, synthCtx); expect( v, `false positive on ${c.name}: ${v.map((x) => `${x.prong}:${x.detail}`).join('; ')}`, ).toEqual([]); } }); });