20260818_557_plugin_final_downgrade_fence.py 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. """Fence the first WP13 downgrade against every durable plugin fact."""
  2. from alembic import op
  3. revision = "20260818_557"
  4. down_revision = "20260818_556"
  5. branch_labels = None
  6. depends_on = None
  7. _FACT_TABLES = (
  8. # Registry rows carry the persisted review actor and incident link.
  9. "plugin_registry_versions",
  10. "plugin_approvals",
  11. "plugin_runtime_leases",
  12. "plugin_runs",
  13. "plugin_dead_letters",
  14. "plugin_audit_outbox",
  15. "plugin_request_claims",
  16. "plugin_runtime_breakers",
  17. "plugin_recovery_claims",
  18. )
  19. def upgrade() -> None:
  20. # This revision intentionally changes no successful runtime behaviour. It
  21. # owns the first downgrade step so later revisions cannot expose 556's
  22. # narrower downgrade checks while any durable WP13 evidence still exists.
  23. op.get_bind().exec_driver_sql("SELECT 1")
  24. def downgrade() -> None:
  25. bind = op.get_bind()
  26. checks = " OR ".join(
  27. f"EXISTS(SELECT 1 FROM public.{table} LIMIT 1)" for table in _FACT_TABLES
  28. )
  29. if bind.exec_driver_sql(f"SELECT {checks}").scalar():
  30. raise RuntimeError("downgrade refused: durable WP13 plugin facts are nonempty")