# Findings Ledger RLS Migration Guide > **Task:** DEVOPS-LEDGER-TEN-48-001-REL > **Contract:** [CONTRACT-FINDINGS-LEDGER-RLS-011](../../contracts/findings-ledger-rls.md) > **Applies to:** PostgreSQL 16+ with Findings Ledger schema ## Overview Migration `007_enable_rls.sql` enables Row-Level Security (RLS) on all Findings Ledger tables, implementing tenant isolation at the database level. This document covers deployment procedures for release pipelines and air-gapped environments. ## Prerequisites - PostgreSQL 16 or later - All prior migrations applied (001–006) - Service accounts configured with appropriate roles ## Migration Files | File | Purpose | SHA256 | |------|---------|--------| | `007_enable_rls.sql` | Apply RLS policies | (generated at build time) | | `007_enable_rls_rollback.sql` | Revert RLS policies | (generated at build time) | | `007_enable_rls.manifest.json` | Metadata for offline-kit | (generated at build time) | ## Protected Tables The migration enables RLS and creates tenant isolation policies on: 1. `ledger_events` 2. `ledger_merkle_roots` 3. `findings_projection` 4. `finding_history` 5. `triage_actions` 6. `ledger_attestations` 7. `orchestrator_exports` 8. `airgap_imports` ## Deployment Procedures ### Standard Pipeline Deployment The CI workflow at `.gitea/workflows/findings-ledger-ci.yml` handles migration validation automatically: 1. Applies prerequisites (001–006) 2. Applies RLS migration (007) 3. Validates RLS configuration 4. Tests rollback capability 5. Verifies idempotency ### Manual Deployment ```bash # 1. Connect to database psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE # 2. Apply migration \i migrations/007_enable_rls.sql # 3. Validate SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public' AND tablename IN ( 'ledger_events', 'ledger_merkle_roots', 'findings_projection', 'finding_history', 'triage_actions', 'ledger_attestations', 'orchestrator_exports', 'airgap_imports' ); -- All should show rowsecurity = true ``` ### Air-Gapped Deployment 1. **Export migration bundle** ```bash # After CI passes, download the migration artifact gh run download -n findings-ledger-migrations ``` 2. **Transfer to air-gapped environment** - Copy `out/findings-ledger/offline-kit/` to target host - Verify SHA256 checksums match manifest 3. **Apply migration** ```bash cd /path/to/offline-kit/migrations # Verify checksums sha256sum -c 007_enable_rls.manifest.json # Apply psql -f 007_enable_rls.sql ``` 4. **Validate using RlsValidationService** ```bash dotnet run --project tools/LedgerReplayHarness \ -- --connection "$LEDGER_DB" --validate-rls-only ``` ## Rollback Procedure If issues are encountered, rollback is safe and non-destructive: ```bash psql -f migrations/007_enable_rls_rollback.sql ``` The rollback: - Disables RLS on all 8 tables - Drops tenant isolation policies - Removes the `findings_ledger_app` schema and tenant function - Does NOT drop the `findings_ledger_admin` role (preserves other grants) ## Validation Checklist After applying the migration, verify: - [ ] All 8 tables have `relrowsecurity = true` in `pg_class` - [ ] All 8 tenant isolation policies exist in `pg_policies` - [ ] Function `findings_ledger_app.require_current_tenant()` exists - [ ] Application can connect and query with tenant context - [ ] `RlsValidationService.ValidateAsync()` returns `IsCompliant = true` ## Tenant Context Requirements After RLS is enabled, all queries must set tenant context: ```sql -- Set tenant before querying SELECT set_config('app.current_tenant', 'tenant-123', false); -- Now queries are tenant-scoped SELECT * FROM ledger_events; -- Only returns tenant-123 data ``` The `LedgerDataSource.OpenConnectionAsync(tenantId, ...)` handles this automatically for application code. ## Admin Bypass For migrations and cross-tenant admin operations, use the `findings_ledger_admin` role: ```sql SET ROLE findings_ledger_admin; -- Queries now bypass RLS ``` ## Metrics & Observability After migration, monitor: - `ledger_connection_opened_total{role="tenant"}` - Connection count with tenant context - `ledger_connection_opened_total{role="system"}` - Admin/migration connections - RLS violation errors in application logs ## CI Workflow Integration The migration is validated in every CI run via: ```yaml # .gitea/workflows/findings-ledger-ci.yml jobs: migration-validation: # Tests apply → validate → rollback → re-apply cycle ``` ## Related Documents - [Tenant Isolation & Redaction](../tenant-isolation-redaction.md) - [Findings Ledger Deployment](../deployment.md) - [Offline Kit Operations](../../../24_OFFLINE_KIT.md) --- *Created 2025-12-06 for DEVOPS-LEDGER-TEN-48-001-REL*