import assert from 'node:assert/strict'; import fs from 'node:fs'; import { EXPECTED_TENANT_FOREIGN_KEY_RELATION_COUNT, EXPECTED_TENANT_FOREIGN_KEY_SCHEMA_SHA256, buildTenantForeignKeyViolationQuery, tenantForeignKeyExceptions, tenantForeignKeySchemaSha256, } from './lib/tenant-foreign-key-audit.js'; import { assertTenantForeignKeyAuditTarget, parseTenantForeignKeyAuditOptions, } from './tenant-foreign-key-audit.js'; const relation = overrides => ({ childTable: 'child_rows', constraintName: 'child_rows_parent_id_fkey', childColumns: ['parent_id'], parentTable: 'parent_rows', parentColumns: ['id'], validated: true, updateAction: 'a', deleteAction: 'a', ...overrides, }); assert.equal(EXPECTED_TENANT_FOREIGN_KEY_RELATION_COUNT, 189); assert.match(EXPECTED_TENANT_FOREIGN_KEY_SCHEMA_SHA256, /^[0-9a-f]{64}$/); assert.equal(tenantForeignKeyExceptions().length, 3); const digestA = tenantForeignKeySchemaSha256([relation({ childTable: 'b' }), relation({ childTable: 'a' })]); const digestB = tenantForeignKeySchemaSha256([relation({ childTable: 'a' }), relation({ childTable: 'b' })]); assert.equal(digestA, digestB, 'schema fingerprint must not depend on catalog row ordering'); const defaultQuery = buildTenantForeignKeyViolationQuery([relation({})]); assert.match(defaultQuery, /child\.tenant_id is distinct from parent\.tenant_id/i); const globalRuleQuery = buildTenantForeignKeyViolationQuery([ relation({ childTable: 'platform_audit_alerts', constraintName: 'platform_audit_alerts_rule_id_fkey', childColumns: ['rule_id'], parentTable: 'platform_audit_alert_rules', }), ]); assert.match(globalRuleQuery, /parent\.tenant_id is not null and child\.tenant_id is distinct from parent\.tenant_id/i); const platformBankQuery = buildTenantForeignKeyViolationQuery([ relation({ childTable: 'tenant_question_bank_adoptions', constraintName: 'tenant_question_bank_adoptions_source_question_bank_id_fkey', childColumns: ['source_question_bank_id'], parentTable: 'question_banks', }), ]); assert.match(platformBankQuery, /parent\.source_scope is distinct from 'platform'/i); assert.throws( () => parseTenantForeignKeyAuditOptions([], {}), /DATABASE_URL is required/, ); assert.throws( () => assertTenantForeignKeyAuditTarget('postgresql://postgres:postgres@127.0.0.1:5432/postgres'), /reserved for tikupro-pg/, ); assert.throws( () => assertTenantForeignKeyAuditTarget('postgresql://postgres:postgres@tikupro-pg:55432/postgres'), /tikupro-pg targets are forbidden/, ); assert.deepEqual( assertTenantForeignKeyAuditTarget('postgresql://postgres:secret@127.0.0.1:55432/postgres'), { host: '127.0.0.1', port: '55432', database: 'postgres', user: 'postgres' }, ); const readiness = fs.readFileSync('scripts/production-readiness-check.js', 'utf8'); assert.match(readiness, /db\.tenant_foreign_keys\.schema/); const launchGate = fs.readFileSync('scripts/production-launch-gate.js', 'utf8'); assert.match(launchGate, /db\.tenant-foreign-key-audit/); console.log('[PASS] tenant foreign key audit contract');