20260817_515_tenant_final_downgrade_fence.py 1.3 KB

12345678910111213141516171819202122232425262728293031323334
  1. """Make the current secured head fail closed before any downgrade step."""
  2. from alembic import op
  3. revision = "20260817_515"
  4. down_revision = "20260817_514"
  5. branch_labels = None
  6. depends_on = None
  7. def upgrade() -> None:
  8. # The guard lives on the downgrade edge so it covers every final head
  9. # without changing the already-applied 501--514 history.
  10. return None
  11. def downgrade() -> None:
  12. op.execute("""
  13. DO $$ BEGIN
  14. IF EXISTS (SELECT 1 FROM public.tenants LIMIT 1)
  15. OR EXISTS (SELECT 1 FROM public.tenant_quotas LIMIT 1)
  16. OR EXISTS (SELECT 1 FROM public.tenant_quota_reservations LIMIT 1)
  17. OR EXISTS (SELECT 1 FROM public.tenant_lifecycle_events LIMIT 1)
  18. OR EXISTS (SELECT 1 FROM public.tenant_audit_events LIMIT 1)
  19. OR EXISTS (SELECT 1 FROM public.tenant_resource_manifests LIMIT 1)
  20. OR EXISTS (SELECT 1 FROM public.tenant_control_memberships LIMIT 1)
  21. OR EXISTS (SELECT 1 FROM public.tenant_control_claims LIMIT 1)
  22. OR EXISTS (SELECT 1 FROM public.tenant_legal_holds LIMIT 1)
  23. OR EXISTS (SELECT 1 FROM public.tenant_control_outbox LIMIT 1)
  24. OR EXISTS (SELECT 1 FROM public.tenant_control_outbox_scope_lookup LIMIT 1) THEN
  25. RAISE EXCEPTION 'tenant security downgrade refused while tenant data exists';
  26. END IF;
  27. END $$;
  28. """)