test_wp12_metering_showback_migration_contract.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. """Static security and delivery contract for the WP12 database revision."""
  2. from __future__ import annotations
  3. from pathlib import Path
  4. ROOT = Path(__file__).resolve().parents[1]
  5. MIGRATION = ROOT / "migrations/versions/20260818_546_metering_showback.py"
  6. DEPLOYMENT_MIGRATION = ROOT / "deployment/migrations/versions/20260818_546_metering_showback.py"
  7. CONTROL_MIGRATION = ROOT / "migrations/versions/20260818_547_metering_allocation_budget_gateway.py"
  8. DEPLOYMENT_CONTROL_MIGRATION = ROOT / "deployment/migrations/versions/20260818_547_metering_allocation_budget_gateway.py"
  9. REPLAY_MIGRATION = ROOT / "migrations/versions/20260818_548_metering_allocation_replay.py"
  10. DEPLOYMENT_REPLAY_MIGRATION = ROOT / "deployment/migrations/versions/20260818_548_metering_allocation_replay.py"
  11. INTEGRITY_MIGRATION = ROOT / "migrations/versions/20260818_549_metering_showback_integrity.py"
  12. DEPLOYMENT_INTEGRITY_MIGRATION = ROOT / "deployment/migrations/versions/20260818_549_metering_showback_integrity.py"
  13. UNIFIED_REPLAY_MIGRATION = ROOT / "migrations/versions/20260818_550_metering_unified_replay_acl.py"
  14. DEPLOYMENT_UNIFIED_REPLAY_MIGRATION = ROOT / "deployment/migrations/versions/20260818_550_metering_unified_replay_acl.py"
  15. ATOMIC_ALLOCATION_MIGRATION = ROOT / "migrations/versions/20260818_551_metering_allocation_atomicity.py"
  16. DEPLOYMENT_ATOMIC_ALLOCATION_MIGRATION = ROOT / "deployment/migrations/versions/20260818_551_metering_allocation_atomicity.py"
  17. OWNER_FENCE_MIGRATION = ROOT / "migrations/versions/20260818_552_metering_definer_owner_fence.py"
  18. DEPLOYMENT_OWNER_FENCE_MIGRATION = ROOT / "deployment/migrations/versions/20260818_552_metering_definer_owner_fence.py"
  19. def test_wp12_migration_is_child_of_545_and_has_closed_runtime_gateway():
  20. source = MIGRATION.read_text(encoding="utf-8")
  21. assert 'revision = "20260818_546"' in source
  22. assert 'down_revision = "20260818_545"' in source
  23. assert "SECURITY DEFINER SET search_path=pg_catalog,public" in source
  24. assert "metering_showback_runtime_write" in source
  25. assert "metering_showback_runtime_read" in source
  26. assert "chargeback_disabled" in source
  27. assert "REVOKE ALL ON TABLE public.metering_events FROM PUBLIC,dataops_app,dataops_app_runtime" in source
  28. def test_wp12_migration_refuses_nonempty_downgrade_and_source_deployment_mirror():
  29. source = MIGRATION.read_text(encoding="utf-8")
  30. assert "downgrade refused: WP12 metering facts are nonempty" in source
  31. assert DEPLOYMENT_MIGRATION.read_bytes() == MIGRATION.read_bytes()
  32. def test_wp12_control_gateway_is_closed_and_fails_downgrade_with_persisted_facts():
  33. source = CONTROL_MIGRATION.read_text(encoding="utf-8")
  34. assert 'revision = "20260818_547"' in source
  35. assert 'down_revision = "20260818_546"' in source
  36. assert "metering_showback_control_write" in source
  37. assert "SECURITY DEFINER SET search_path=pg_catalog,public" in source
  38. assert "metering_allocation_weight_invalid" in source
  39. assert "provider','disabled" in source
  40. assert "downgrade refused: WP12 allocation or budget facts are nonempty" in source
  41. assert DEPLOYMENT_CONTROL_MIGRATION.read_bytes() == source.encode("utf-8")
  42. def test_wp12_persisted_allocation_replay_is_runtime_gateway_only_and_mirrored():
  43. source = REPLAY_MIGRATION.read_text(encoding="utf-8")
  44. assert 'revision = "20260818_548"' in source and 'down_revision = "20260818_547"' in source
  45. assert "metering_showback_allocation_replay" in source
  46. assert "SECURITY DEFINER SET search_path=pg_catalog,public" in source
  47. assert "metering_allocation_rule_not_found" in source
  48. assert DEPLOYMENT_REPLAY_MIGRATION.read_bytes() == source.encode("utf-8")
  49. def test_wp12_integrity_followup_closes_rollup_correction_and_duplicate_target_gaps():
  50. source = INTEGRITY_MIGRATION.read_text(encoding="utf-8")
  51. assert 'revision = "20260818_549"' in source and 'down_revision = "20260818_548"' in source
  52. assert "metering_showback_rollup" in source
  53. assert "metering_correction_scope_invalid" in source
  54. assert "metering_allocation_target_duplicate" in source
  55. assert "metering_allocation_window_overlap" in source
  56. assert DEPLOYMENT_INTEGRITY_MIGRATION.read_bytes() == source.encode("utf-8")
  57. def test_wp12_unified_replay_fences_legacy_acl_and_preflights_existing_facts():
  58. source = UNIFIED_REPLAY_MIGRATION.read_text(encoding="utf-8")
  59. assert 'revision = "20260818_550"' in source and 'down_revision = "20260818_549"' in source
  60. assert "metering_allocation_replay_coverage_invalid" in source
  61. assert "upgrade refused: WP12 integrity preflight failed" in source
  62. assert "metering_showback_runtime_read_legacy" in source
  63. assert DEPLOYMENT_UNIFIED_REPLAY_MIGRATION.read_bytes() == source.encode("utf-8")
  64. def test_wp12_atomic_allocation_followup_fences_concurrency_and_total_weight():
  65. source = ATOMIC_ALLOCATION_MIGRATION.read_text(encoding="utf-8")
  66. assert 'revision = "20260818_551"' in source and 'down_revision = "20260818_550"' in source
  67. assert "metering_allocation_rules_scope_window_excl" in source
  68. assert "pg_advisory_xact_lock" in source
  69. assert "metering_showback_allocation_total_guard" in source
  70. assert "metering_allocation_conflict" in source
  71. assert DEPLOYMENT_ATOMIC_ALLOCATION_MIGRATION.read_bytes() == source.encode("utf-8")
  72. def test_wp12_definer_owner_followup_uses_nologin_owner_and_revokes_legacy_paths():
  73. source = OWNER_FENCE_MIGRATION.read_text(encoding="utf-8")
  74. assert 'revision = "20260818_552"' in source and 'down_revision = "20260818_551"' in source
  75. assert "rolcanlogin" in source
  76. assert "ALTER FUNCTION" in source and "OWNER TO dataops_tenant_foundation_owner" in source
  77. assert "metering_showback_allocation_total_guard" in source
  78. assert "REVOKE ALL ON FUNCTION" in source
  79. assert DEPLOYMENT_OWNER_FENCE_MIGRATION.read_bytes() == source.encode("utf-8")