feat(db): hierarchy record class schema + witnesses (contract 1, M4-1a) #1459

Merged
fred merged 10 commits from feat/m4-1a-hierarchy-schema into next 2026-08-28 00:42:36 +00:00
Showing only changes of commit 3dcfb264c5 - Show all commits
+298 -82
View File
@@ -15,11 +15,17 @@
* (`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. 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.
* all propagate symbol identity to the consumer. 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
@@ -27,7 +33,13 @@
* 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 or via namespace). In a raw-capable file
* 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
@@ -43,7 +55,9 @@
* 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; a
* — `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
@@ -543,6 +557,21 @@ function computeSchemaConduits(files: FileFacts[], fileSet: Set<string>): Schema
mine.named.add(m[1]!);
}
}
// The default slot is an export name like any other:
// `export default companies;` / `export default mod.companies;`
for (const m of f.code.matchAll(/export\s+default\s+(\w+)\s*;/g)) {
if (aliases.named.includes(m[1]!)) mine.named.add('default');
if (aliases.namespaces.includes(m[1]!)) mine.ns.add('default');
}
for (const ns of aliases.namespaces) {
if (
new RegExp(
`export\\s+default\\s+${ns}(?:\\s*\\.\\s*\\w+)*\\s*\\.\\s*(?:${CLASS_SYMBOLS.join('|')})\\b`,
).test(f.code)
) {
mine.named.add('default');
}
}
}
if (mine.named.size + mine.ns.size > before) {
conduits.set(f.rel, mine);
@@ -556,6 +585,10 @@ function computeSchemaConduits(files: FileFacts[], fileSet: Set<string>): Schema
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<string>;
}
/**
@@ -605,13 +638,21 @@ function destructureBindings(
function classAliases(f: FileFacts, conduits: SchemaConduits, fileSet: Set<string>): ClassAliases {
const named = new Set<string>();
const namespaces = new Set<string>();
const memberSyms = new Set<string>(CLASS_SYMBOLS);
for (const m of f.code.matchAll(IMPORT_RE)) {
const [, typeOnly, , namedList, nsName, , spec] = m;
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).
@@ -621,6 +662,7 @@ function classAliases(f: FileFacts, conduits: SchemaConduits, fileSet: Set<strin
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);
}
@@ -629,7 +671,7 @@ function classAliases(f: FileFacts, conduits: SchemaConduits, fileSet: Set<strin
// const { schema } = ns; → nested namespace (fail-closed)
// const t = ns.companies; → named alias
// const s2 = ns.schema; → namespace alias
const nsSrc: SchemaExports = { named: new Set(CLASS_SYMBOLS), ns: new Set() };
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(
@@ -643,12 +685,12 @@ function classAliases(f: FileFacts, conduits: SchemaConduits, fileSet: Set<strin
'g',
),
)) {
if (CLASS_SYMBOLS.includes(m[2]!)) named.add(m[1]!);
if (memberSyms.has(m[2]!)) named.add(m[1]!);
else namespaces.add(m[1]!);
}
}
}
return { named: [...named], namespaces: [...namespaces] };
return { named: [...named], namespaces: [...namespaces], memberSyms };
}
/**
@@ -658,27 +700,34 @@ function classAliases(f: FileFacts, conduits: SchemaConduits, fileSet: Set<strin
* 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` — re-exports createDb/createPgliteDb from the db package or
* another factory conduit (via `export … from`, or by exporting a local
* binding of the factory under any name); importing ANYTHING from one
* confers factory capability — the conduit may rename the symbol, so there
* is no consumer-side name gate.
* `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<string>,
): { driver: Set<string>; factory: Set<string> } {
const driver = new Set<string>();
const factory = new Set<string>();
// 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<string, Set<string>>();
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 isFactorySpec = (rel: string, spec: string): boolean => {
if (spec === '@mosaicstack/db') return true;
const factoryNamesOf = (rel: string, spec: string): Set<string> | null => {
if (spec === '@mosaicstack/db') return new Set(DB_FACTORY_SYMBOLS);
const r = resolveSpecifier(rel, spec, fileSet);
return r !== null && factory.has(r);
return r !== null ? (factoryNames.get(r) ?? null) : null;
};
let changed = true;
while (changed) {
@@ -691,71 +740,93 @@ function computeCapabilityConduits(
driver.add(f.rel);
changed = true;
}
if (!factory.has(f.rel) && isFactorySpec(f.rel, spec)) {
const named = m[2];
if (named === undefined || /\b(createDb|createPgliteDb)\b/.test(named)) {
factory.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.
// Export-of-local factory bindings: a module that BINDS the factory
// (named import, namespace member, or tracked dynamic import) and
// exports that binding under any name is a factory conduit even with
// no `export … from` clause (`export const mk = mod.createDb`).
if (!factory.has(f.rel)) {
const locals = new Set<string>();
const nss = new Set<string>();
for (const im of f.code.matchAll(IMPORT_RE)) {
const [, typeOnly, , namedList, nsName, , spec] = im;
if (typeOnly || !isFactorySpec(f.rel, spec!)) continue;
if (nsName) nss.add(nsName);
if (namedList) {
for (const part of namedList.split(',')) {
const am = /^(createDb|createPgliteDb)(?:\s+as\s+(\w+))?$/.exec(part.trim());
if (am) 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;
if (!isFactorySpec(f.rel, spec!)) continue;
if (nsName) nss.add(nsName);
if (pattern) {
for (const part of pattern.split(',')) {
const pm = /^(createDb|createPgliteDb)\s*(?::\s*(\w+))?/.exec(part.trim());
if (pm) locals.add(pm[2] ?? pm[1]!);
}
}
}
for (const ns of nss) {
for (const am of f.code.matchAll(
new RegExp(
`(?:const|let|var)\\s+(\\w+)\\s*=\\s*${ns}\\s*\\.\\s*(?:createDb|createPgliteDb)\\b`,
'g',
),
)) {
locals.add(am[1]!);
}
}
for (const local of locals) {
if (
new RegExp(`export\\s+(?:const|let|var|function)\\s+${local}\\b`).test(f.code) ||
new RegExp(`export\\s*\\{[^}]*\\b${local}\\b[^}]*\\}`).test(f.code)
) {
factory.add(f.rel);
changed = true;
break;
const mine = factoryNames.get(f.rel) ?? new Set<string>();
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<string>();
const nss = new Map<string, Set<string>>();
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+(\\w+)\\s*=\\s*${ns}\\s*\\.\\s*(\\w+)\\b`, 'g'),
)) {
if (src.has(am[2]!)) 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+${local}\\b`).test(f.code)) {
mine.add(local);
}
if (new RegExp(`export\\s+default\\s+${local}\\b`).test(f.code)) {
mine.add('default');
}
}
}
if (mine.size > before) {
factoryNames.set(f.rel, mine);
changed = true;
}
}
}
return { driver, factory };
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). */
@@ -854,6 +925,25 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
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<string>();
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}\\s*\\(`).test(code)) {
violations.push({ file: rel, prong: 'dynamic-import', detail: 'createRequire()' });
@@ -869,7 +959,9 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
// 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`);
const symAlt = CLASS_SYMBOLS.join('|');
// 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) and literal computed access (ns['companies']).
@@ -877,9 +969,10 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
targets.push(`${ns}(?:\\s*\\.\\s*\\w+)*\\s*\\[\\s*['"\`](?:${symAlt})['"\`]\\s*\\]`);
}
if (targets.length > 0) {
// `\(\s*\(*` tolerates argument parenthesization: .insert((companies)).
// The argument prefix tolerates parenthesization, spread, and array
// wrapping: .insert((companies)), .insert(...[companies]).
const writeRe = new RegExp(
`\\.\\s*(insert|update|delete)\\s*\\(\\s*\\(*\\s*(${targets.join('|')})`,
`\\.\\s*(insert|update|delete)\\s*\\(\\s*(?:(?:\\(|\\[|\\.\\.\\.)\\s*)*(${targets.join('|')})`,
'g',
);
for (const m of code.matchAll(writeRe)) {
@@ -924,7 +1017,7 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
// 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)';
'(?: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)+';
const q = `(?:\\\\?["'\`])?`;
const sqlAdjacentRe = new RegExp(
@@ -956,6 +1049,13 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
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
@@ -967,6 +1067,12 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
(aliases.namespaces.length > 0 &&
new RegExp(
`\\b(${aliases.namespaces.join('|')})(?:\\s*\\.\\s*\\w+)*\\s*\\.\\s*(createDb|createPgliteDb)\\b`,
).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' });
@@ -995,8 +1101,10 @@ function analyzeFile(f: FileFacts, ctx: AnalysisCtx): Violation[] {
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(…).
for (const m of code.matchAll(
/\b(?:db|database|client|conn|connection|pool|pg|pglite|tx|trx)\s*\.\s*(execute|query|unsafe)\s*\(/g,
/(?:\b(?:db|database|client|conn|connection|pool|pg|pglite|tx|trx)|\[\s*['"](?:db|database|client|conn|connection|pool|pg|pglite|tx|trx)['"]\s*\])\s*\.\s*(execute|query|unsafe)\s*\(/g,
)) {
violations.push({
file: rel,
@@ -1356,6 +1464,114 @@ describe('hierarchy writer coverage (contract 1 §6.3b)', () => {
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); } }`,
},
];
const CLEAN_CONTROLS: Array<{ name: string; src: string }> = [
{