import { readFileSync } from 'node:fs'; import { describe, expect, it } from 'vitest'; describe('tenant isolation migration', () => { const sql = readFileSync('migrations/0001_infrastructure.up.sql', 'utf8'); const tables = ['staff_outbox', 'staff_inbox', 'staff_idempotency_keys', 'staff_audit_log']; it.each(tables)('%s is tenant scoped and protected by RLS', (table) => { const create = sql.slice( sql.indexOf(`CREATE TABLE IF NOT EXISTS ${table}`), sql.indexOf(';', sql.indexOf(`CREATE TABLE IF NOT EXISTS ${table}`)), ); expect(create).toContain('tenant_id VARCHAR(26) NOT NULL'); expect(sql).toContain(`ALTER TABLE ${table} ENABLE ROW LEVEL SECURITY`); expect(sql).toContain(`ALTER TABLE ${table} FORCE ROW LEVEL SECURITY`); expect(sql).toMatch(new RegExp(`CREATE POLICY [a-z_]+ ON ${table} `)); }); it('sets tenant and actor locally inside each transaction', () => { const source = readFileSync('src/infrastructure/database.ts', 'utf8'); expect(source).toContain("set_config('app.tenant_id', $1, true)"); expect(source).toContain("set_config('app.user_id', $2, true)"); }); }); describe('attendance portal migrations', () => { const sql = readFileSync('migrations/0005_attendance_portal.up.sql', 'utf8'); const tables = ['staff_employees', 'staff_attendance_events', 'staff_timesheet_entries']; it.each(tables)('%s is tenant scoped and forces RLS', (table) => { expect(sql).toContain(`ALTER TABLE ${table} ENABLE ROW LEVEL SECURITY`); expect(sql).toContain(`ALTER TABLE ${table} FORCE ROW LEVEL SECURITY`); expect(sql).toMatch(new RegExp(`CREATE POLICY ${table}_[a-z_]+ ON ${table}`)); }); it('keeps raw attendance immutable for the runtime role', () => { expect(sql).toContain('GRANT SELECT, INSERT ON staff_attendance_events TO krona_staff_app'); expect(sql).toContain( 'REVOKE UPDATE, DELETE, TRUNCATE ON staff_attendance_events FROM krona_staff_app', ); }); }); describe('payroll foundation migration', () => { const sql = readFileSync('migrations/0006_payroll_foundation.up.sql', 'utf8'); const tables = [ 'staff_org_units', 'staff_org_unit_terms', 'staff_metric_definitions', 'staff_daily_metrics', 'staff_work_items', 'staff_pay_rules', 'staff_pay_assignments', 'staff_work_sessions', 'staff_payroll_runs', 'staff_payroll_lines', 'staff_payouts', ]; it.each(tables)('%s is tenant scoped and included in the RLS setup', (table) => { expect(sql).toContain(`CREATE TABLE ${table}`); expect(sql).toContain(`'${table}'`); }); it('enables and forces RLS with a tenant policy for every listed payroll table', () => { expect(sql).toContain("EXECUTE format('ALTER TABLE %I ENABLE ROW LEVEL SECURITY', target_table)"); expect(sql).toContain("EXECUTE format('ALTER TABLE %I FORCE ROW LEVEL SECURITY', target_table)"); expect(sql).toContain("target_table || '_tenant_isolation', target_table"); }); it('uses tenant-scoped foreign keys for payroll ownership', () => { expect(sql).toContain( 'FOREIGN KEY (tenant_id, employee_id) REFERENCES staff_employees (tenant_id, id)', ); expect(sql).toContain( 'FOREIGN KEY (tenant_id, org_unit_id) REFERENCES staff_org_units (tenant_id, id)', ); expect(sql).toContain( 'FOREIGN KEY (tenant_id, pay_rule_id) REFERENCES staff_pay_rules (tenant_id, id)', ); }); it('keeps the money ledger append-only for the runtime role', () => { expect(sql).toContain('CREATE TABLE staff_payroll_ledger'); expect(sql).toContain('ALTER TABLE staff_payroll_ledger ENABLE ROW LEVEL SECURITY'); expect(sql).toContain('ALTER TABLE staff_payroll_ledger FORCE ROW LEVEL SECURITY'); expect(sql).toContain('GRANT SELECT, INSERT ON staff_payroll_ledger TO krona_staff_app'); expect(sql).toContain( 'REVOKE UPDATE, DELETE, TRUNCATE ON staff_payroll_ledger FROM krona_staff_app', ); }); });