| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- """Add governed data products, applications, contracts and certificates."""
- from alembic import op
- revision = "20260802_440"
- down_revision = "20260802_430"
- branch_labels = None
- depends_on = None
- def upgrade() -> None:
- op.execute(
- """
- CREATE TABLE public.governed_data_products (
- uid UUID PRIMARY KEY,
- legacy_product_id INTEGER NOT NULL UNIQUE
- REFERENCES public.data_products(id) ON DELETE RESTRICT,
- product_code VARCHAR(120) NOT NULL UNIQUE,
- name VARCHAR(300) NOT NULL,
- product_type VARCHAR(30) NOT NULL CHECK (
- product_type IN ('database','api','file','data_product')
- ),
- owner_uid UUID NOT NULL REFERENCES public.users(id),
- business_domain_uid UUID NOT NULL,
- description VARCHAR(2000) NOT NULL,
- quality_target NUMERIC(6,2) NOT NULL CHECK (
- quality_target >= 0 AND quality_target <= 100
- ),
- sla JSONB NOT NULL,
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('draft','in_review','active','suspended','retired')
- ),
- current_version INTEGER NOT NULL DEFAULT 1 CHECK (current_version > 0),
- created_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_by UUID NOT NULL REFERENCES public.users(id),
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- retired_at TIMESTAMPTZ,
- CHECK (jsonb_typeof(sla) = 'object')
- );
- CREATE INDEX idx_governed_product_domain_status
- ON public.governed_data_products(
- business_domain_uid, status, updated_at DESC
- );
- CREATE INDEX idx_governed_product_owner_status
- ON public.governed_data_products(owner_uid, status, updated_at DESC);
- CREATE TABLE public.data_product_governance_events (
- uid UUID PRIMARY KEY,
- product_uid UUID NOT NULL
- REFERENCES public.governed_data_products(uid) ON DELETE CASCADE,
- product_version INTEGER NOT NULL CHECK (product_version > 0),
- action VARCHAR(50) NOT NULL,
- actor_uid UUID NOT NULL REFERENCES public.users(id),
- payload JSONB NOT NULL DEFAULT '{}'::jsonb,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- CHECK (jsonb_typeof(payload) = 'object')
- );
- CREATE INDEX idx_product_governance_timeline
- ON public.data_product_governance_events(product_uid, created_at, uid);
- CREATE TABLE public.data_product_applications (
- uid UUID PRIMARY KEY,
- application_code VARCHAR(40) NOT NULL UNIQUE,
- title VARCHAR(300) NOT NULL,
- source_type VARCHAR(30) NOT NULL CHECK (
- source_type IN ('database','api','file','data_product')
- ),
- source_ref JSONB NOT NULL,
- business_domain_uid UUID NOT NULL,
- purpose VARCHAR(1000) NOT NULL,
- requested_fields JSONB NOT NULL,
- status VARCHAR(30) NOT NULL CHECK (
- status IN (
- 'draft','pending_approval','approved','rejected',
- 'fulfilled','cancelled'
- )
- ),
- approval_task_uid UUID REFERENCES public.governance_tasks(uid),
- product_uid UUID REFERENCES public.governed_data_products(uid),
- current_version INTEGER NOT NULL DEFAULT 1 CHECK (current_version > 0),
- created_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_by UUID NOT NULL REFERENCES public.users(id),
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- CHECK (jsonb_typeof(source_ref) = 'object'),
- CHECK (jsonb_typeof(requested_fields) = 'array')
- );
- CREATE INDEX idx_product_application_worklist
- ON public.data_product_applications(
- created_by, status, updated_at DESC
- );
- CREATE INDEX idx_product_application_domain
- ON public.data_product_applications(
- business_domain_uid, status, updated_at DESC
- );
- CREATE TABLE public.data_product_application_events (
- uid UUID PRIMARY KEY,
- application_uid UUID NOT NULL
- REFERENCES public.data_product_applications(uid) ON DELETE CASCADE,
- application_version INTEGER NOT NULL CHECK (application_version > 0),
- action VARCHAR(50) NOT NULL,
- actor_uid UUID NOT NULL REFERENCES public.users(id),
- payload JSONB NOT NULL DEFAULT '{}'::jsonb,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- CHECK (jsonb_typeof(payload) = 'object')
- );
- CREATE INDEX idx_product_application_timeline
- ON public.data_product_application_events(
- application_uid, created_at, uid
- );
- CREATE TABLE public.data_product_contracts (
- uid UUID PRIMARY KEY,
- product_uid UUID NOT NULL UNIQUE
- REFERENCES public.governed_data_products(uid) ON DELETE RESTRICT,
- contract_code VARCHAR(180) NOT NULL UNIQUE,
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('draft','active','terminated')
- ),
- current_version INTEGER NOT NULL CHECK (current_version > 0),
- active_version_uid UUID,
- created_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_by UUID NOT NULL REFERENCES public.users(id),
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- terminated_at TIMESTAMPTZ,
- termination_reason VARCHAR(1000)
- );
- CREATE TABLE public.data_product_contract_versions (
- uid UUID PRIMARY KEY,
- contract_uid UUID NOT NULL
- REFERENCES public.data_product_contracts(uid) ON DELETE RESTRICT,
- version INTEGER NOT NULL CHECK (version > 0),
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('draft','published','superseded')
- ),
- definition JSONB NOT NULL,
- content_hash CHAR(64) NOT NULL,
- compatibility JSONB NOT NULL,
- created_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- published_by UUID REFERENCES public.users(id),
- published_at TIMESTAMPTZ,
- UNIQUE (contract_uid, version),
- UNIQUE (contract_uid, content_hash),
- CHECK (jsonb_typeof(definition) = 'object'),
- CHECK (jsonb_typeof(compatibility) = 'object')
- );
- ALTER TABLE public.data_product_contracts
- ADD CONSTRAINT data_product_contract_active_version_fk
- FOREIGN KEY (active_version_uid)
- REFERENCES public.data_product_contract_versions(uid);
- CREATE UNIQUE INDEX uq_data_product_contract_published_version
- ON public.data_product_contract_versions(contract_uid)
- WHERE status = 'published';
- CREATE TABLE public.data_product_certificates (
- uid UUID PRIMARY KEY,
- certificate_code VARCHAR(50) NOT NULL UNIQUE,
- product_uid UUID NOT NULL
- REFERENCES public.governed_data_products(uid) ON DELETE RESTRICT,
- contract_uid UUID NOT NULL
- REFERENCES public.data_product_contracts(uid) ON DELETE RESTRICT,
- contract_version INTEGER NOT NULL CHECK (contract_version > 0),
- approval_task_uid UUID NOT NULL REFERENCES public.governance_tasks(uid),
- evidence_snapshot JSONB NOT NULL,
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('qualified','unqualified')
- ),
- content_hash CHAR(64) NOT NULL,
- issued_by UUID NOT NULL REFERENCES public.users(id),
- issued_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (product_uid, content_hash),
- CHECK (jsonb_typeof(evidence_snapshot) = 'object')
- );
- CREATE INDEX idx_product_certificate_latest
- ON public.data_product_certificates(product_uid, issued_at DESC);
- CREATE TABLE public.data_product_feedback (
- uid UUID PRIMARY KEY,
- product_uid UUID NOT NULL
- REFERENCES public.governed_data_products(uid) ON DELETE CASCADE,
- category VARCHAR(30) NOT NULL CHECK (
- category IN (
- 'quality','freshness','usability',
- 'documentation','service'
- )
- ),
- rating INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 5),
- summary VARCHAR(300) NOT NULL,
- details VARCHAR(2000) NOT NULL,
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('open','triaged','in_progress','resolved','closed')
- ),
- assignee_uid UUID REFERENCES public.users(id),
- resolution VARCHAR(2000),
- evidence_refs JSONB NOT NULL DEFAULT '[]'::jsonb,
- current_version INTEGER NOT NULL DEFAULT 1 CHECK (current_version > 0),
- created_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_by UUID NOT NULL REFERENCES public.users(id),
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- closed_at TIMESTAMPTZ,
- CHECK (jsonb_typeof(evidence_refs) = 'array')
- );
- CREATE INDEX idx_product_feedback_worklist
- ON public.data_product_feedback(
- product_uid, status, updated_at DESC
- );
- CREATE INDEX idx_product_feedback_assignee
- ON public.data_product_feedback(
- assignee_uid, status, updated_at DESC
- );
- """
- )
- def downgrade() -> None:
- raise RuntimeError(
- "governed product contracts, certificates and feedback are retained; "
- "downgrade requires an approved archival migration"
- )
|