20260811_482_trusted_delivery_lifecycle.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. """Persist P3-WP06 B1 policy, provision, hold-release, and reclaim lifecycle."""
  2. from alembic import op
  3. revision = "20260811_482"
  4. down_revision = "20260811_481"
  5. branch_labels = None
  6. depends_on = None
  7. def upgrade() -> None:
  8. op.execute(
  9. """
  10. CREATE TABLE public.trusted_delivery_policy_transitions (
  11. uid UUID PRIMARY KEY, policy_uid UUID NOT NULL REFERENCES public.trusted_delivery_policy_versions(uid),
  12. operation VARCHAR(20) NOT NULL CHECK(operation IN ('activate','rollback')),
  13. idempotency_key VARCHAR(160) NOT NULL UNIQUE,
  14. request_digest CHAR(64) NOT NULL CHECK(request_digest ~ '^[0-9a-f]{64}$'),
  15. approval_ref VARCHAR(200) NOT NULL, approval_digest CHAR(64) NOT NULL CHECK(approval_digest ~ '^[0-9a-f]{64}$'),
  16. actor_uid UUID NOT NULL REFERENCES public.users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp()
  17. );
  18. ALTER TABLE public.trusted_delivery_grants
  19. ADD COLUMN approval_ref VARCHAR(200),
  20. ADD COLUMN approval_digest CHAR(64),
  21. ADD COLUMN purpose VARCHAR(100),
  22. ADD COLUMN environment VARCHAR(30),
  23. ADD COLUMN target_capability JSONB;
  24. ALTER TABLE public.trusted_delivery_grants
  25. ADD CONSTRAINT trusted_delivery_grants_approval_projection_check CHECK (
  26. (approval_ref IS NULL AND approval_digest IS NULL AND purpose IS NULL AND environment IS NULL AND target_capability IS NULL)
  27. OR (approval_ref IS NOT NULL AND approval_digest ~ '^[0-9a-f]{64}$' AND purpose IS NOT NULL
  28. AND environment IN ('development','test','production') AND jsonb_typeof(target_capability)='object')
  29. );
  30. ALTER TABLE public.trusted_delivery_grants DROP CONSTRAINT trusted_delivery_grants_status_check;
  31. ALTER TABLE public.trusted_delivery_grants ADD CONSTRAINT trusted_delivery_grants_status_check
  32. CHECK(status IN ('active','revoked','failed','held','reclaimed'));
  33. ALTER TABLE public.trusted_delivery_deliveries ADD COLUMN operation VARCHAR(20) NOT NULL DEFAULT 'provision'
  34. CHECK(operation IN ('provision','revoke'));
  35. ALTER TABLE public.trusted_delivery_deliveries DROP CONSTRAINT trusted_delivery_deliveries_status_check;
  36. ALTER TABLE public.trusted_delivery_deliveries ADD CONSTRAINT trusted_delivery_deliveries_status_check
  37. CHECK(status IN ('pending','processing','applied','dead_letter','reclaimed'));
  38. ALTER TABLE public.trusted_delivery_receipts DROP CONSTRAINT trusted_delivery_receipts_status_check;
  39. ALTER TABLE public.trusted_delivery_receipts ADD CONSTRAINT trusted_delivery_receipts_status_check
  40. CHECK(status IN ('applied','failed','reclaimed'));
  41. CREATE TABLE public.trusted_delivery_hold_releases (
  42. uid UUID PRIMARY KEY, hold_uid UUID NOT NULL REFERENCES public.trusted_delivery_legal_holds(uid),
  43. idempotency_key VARCHAR(160) NOT NULL UNIQUE,
  44. request_digest CHAR(64) NOT NULL CHECK(request_digest ~ '^[0-9a-f]{64}$'),
  45. approval_ref VARCHAR(200) NOT NULL, approval_digest CHAR(64) NOT NULL CHECK(approval_digest ~ '^[0-9a-f]{64}$'),
  46. actor_uid UUID NOT NULL REFERENCES public.users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp()
  47. );
  48. CREATE UNIQUE INDEX uq_trusted_delivery_hold_release ON public.trusted_delivery_hold_releases(hold_uid);
  49. """
  50. )
  51. def downgrade() -> None:
  52. op.execute(
  53. """DO $$ BEGIN
  54. IF EXISTS(SELECT 1 FROM public.trusted_delivery_policy_transitions)
  55. OR EXISTS(SELECT 1 FROM public.trusted_delivery_hold_releases)
  56. OR EXISTS(SELECT 1 FROM public.trusted_delivery_grants WHERE approval_ref IS NOT NULL)
  57. OR EXISTS(SELECT 1 FROM public.trusted_delivery_deliveries WHERE operation <> 'provision')
  58. OR EXISTS(SELECT 1 FROM public.trusted_delivery_receipts WHERE status='reclaimed') THEN
  59. RAISE EXCEPTION 'downgrade requires approved lifecycle archival migration';
  60. END IF;
  61. END $$;
  62. DROP TABLE public.trusted_delivery_hold_releases;
  63. ALTER TABLE public.trusted_delivery_receipts DROP CONSTRAINT trusted_delivery_receipts_status_check;
  64. ALTER TABLE public.trusted_delivery_receipts ADD CONSTRAINT trusted_delivery_receipts_status_check CHECK(status IN ('applied','failed'));
  65. ALTER TABLE public.trusted_delivery_deliveries DROP CONSTRAINT trusted_delivery_deliveries_status_check;
  66. ALTER TABLE public.trusted_delivery_deliveries ADD CONSTRAINT trusted_delivery_deliveries_status_check
  67. CHECK(status IN ('pending','processing','applied','dead_letter'));
  68. ALTER TABLE public.trusted_delivery_deliveries DROP COLUMN operation;
  69. ALTER TABLE public.trusted_delivery_grants DROP CONSTRAINT trusted_delivery_grants_status_check;
  70. ALTER TABLE public.trusted_delivery_grants ADD CONSTRAINT trusted_delivery_grants_status_check CHECK(status IN ('active','revoked','failed','held'));
  71. ALTER TABLE public.trusted_delivery_grants DROP CONSTRAINT trusted_delivery_grants_approval_projection_check;
  72. ALTER TABLE public.trusted_delivery_grants DROP COLUMN target_capability, DROP COLUMN environment, DROP COLUMN purpose,
  73. DROP COLUMN approval_digest, DROP COLUMN approval_ref;
  74. DROP TABLE public.trusted_delivery_policy_transitions;"""
  75. )