| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- """Add hierarchical, delegated and policy-driven governance responsibility."""
- from alembic import op
- revision = "20260801_420"
- down_revision = "20260731_410"
- branch_labels = None
- depends_on = None
- def upgrade() -> None:
- op.execute(
- """
- ALTER TABLE public.governance_responsibility_scopes
- DROP CONSTRAINT IF EXISTS
- governance_responsibility_scopes_resource_type_check;
- ALTER TABLE public.governance_responsibility_scopes
- ADD CONSTRAINT
- governance_responsibility_scopes_resource_type_check
- CHECK (
- resource_type IN (
- 'business_domain','device_asset','device_ontology',
- 'device_mapping','device_quality','fault_classification',
- 'quality_issue','organization','data_asset','semantic_term',
- 'data_standard','quality_policy','data_product','agent'
- )
- ) NOT VALID;
- ALTER TABLE public.governance_responsibility_scopes
- VALIDATE CONSTRAINT
- governance_responsibility_scopes_resource_type_check;
- ALTER TABLE public.governance_responsibility_assignments
- DROP CONSTRAINT IF EXISTS
- governance_responsibility_assignments_responsibility_role_check;
- ALTER TABLE public.governance_responsibility_assignments
- ADD CONSTRAINT
- governance_responsibility_assignments_responsibility_role_check
- CHECK (
- responsibility_role IN (
- 'organization_owner','domain_owner','data_steward',
- 'data_architect','asset_manager','term_steward',
- 'standard_owner','quality_owner','product_owner','agent_owner'
- )
- ) NOT VALID;
- ALTER TABLE public.governance_responsibility_assignments
- VALIDATE CONSTRAINT
- governance_responsibility_assignments_responsibility_role_check;
- CREATE TABLE public.governance_responsibility_hierarchy (
- uid UUID PRIMARY KEY,
- resource_type VARCHAR(40) NOT NULL,
- resource_uid VARCHAR(120) NOT NULL,
- parent_type VARCHAR(40) NOT NULL,
- parent_uid VARCHAR(120) NOT NULL,
- revision INTEGER NOT NULL DEFAULT 1 CHECK (revision > 0),
- updated_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (resource_type, resource_uid),
- CHECK (
- resource_type IN (
- 'organization','business_domain','data_asset','semantic_term',
- 'data_standard','quality_policy','data_product','agent'
- )
- ),
- CHECK (
- parent_type IN (
- 'organization','business_domain','data_asset','semantic_term',
- 'data_standard','quality_policy','data_product','agent'
- )
- ),
- CHECK (
- resource_type <> parent_type OR resource_uid <> parent_uid
- )
- );
- CREATE INDEX idx_governance_responsibility_hierarchy_parent
- ON public.governance_responsibility_hierarchy(
- parent_type, parent_uid
- );
- CREATE TABLE public.governance_responsibility_delegations (
- uid UUID PRIMARY KEY,
- source_user_uid UUID NOT NULL REFERENCES public.users(id),
- delegate_user_uid UUID NOT NULL REFERENCES public.users(id),
- scope_type VARCHAR(40),
- scope_uid VARCHAR(120),
- responsibility_role VARCHAR(40),
- delegation_type VARCHAR(30) NOT NULL CHECK (
- delegation_type IN ('temporary','departure_transfer')
- ),
- starts_at TIMESTAMPTZ NOT NULL,
- ends_at TIMESTAMPTZ,
- reason VARCHAR(500) NOT NULL,
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('active','revoked','expired')
- ),
- current_version INTEGER NOT NULL DEFAULT 1 CHECK (
- current_version > 0
- ),
- created_by UUID NOT NULL REFERENCES public.users(id),
- updated_by UUID NOT NULL REFERENCES public.users(id),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- CHECK (source_user_uid <> delegate_user_uid),
- CHECK ((scope_type IS NULL) = (scope_uid IS NULL)),
- CHECK (
- scope_type IS NULL OR scope_type IN (
- 'organization','business_domain','data_asset','semantic_term',
- 'data_standard','quality_policy','data_product','agent'
- )
- ),
- CHECK (
- responsibility_role IS NULL OR responsibility_role IN (
- 'organization_owner','domain_owner','data_steward',
- 'data_architect','asset_manager','term_steward',
- 'standard_owner','quality_owner','product_owner','agent_owner'
- )
- ),
- CHECK (
- (delegation_type = 'temporary' AND ends_at > starts_at)
- OR
- (delegation_type = 'departure_transfer' AND ends_at IS NULL)
- )
- );
- CREATE UNIQUE INDEX uq_governance_responsibility_active_delegation
- ON public.governance_responsibility_delegations(
- source_user_uid,
- COALESCE(scope_type, ''), COALESCE(scope_uid, ''),
- COALESCE(responsibility_role, '')
- ) WHERE status = 'active';
- CREATE INDEX idx_governance_responsibility_delegate
- ON public.governance_responsibility_delegations(
- delegate_user_uid, status, ends_at
- );
- CREATE TABLE public.governance_responsibility_policies (
- uid UUID PRIMARY KEY,
- code VARCHAR(120) NOT NULL UNIQUE,
- name VARCHAR(300) NOT NULL,
- policy_type VARCHAR(30) NOT NULL CHECK (
- policy_type IN ('central_policy','joint_review')
- ),
- scope_type VARCHAR(40) NOT NULL CHECK (
- scope_type IN (
- 'organization','business_domain','data_asset','semantic_term',
- 'data_standard','quality_policy','data_product','agent'
- )
- ),
- scope_uid VARCHAR(120) NOT NULL,
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('draft','published','retired')
- ),
- current_version INTEGER NOT NULL DEFAULT 1 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_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE TABLE public.governance_responsibility_policy_versions (
- uid UUID PRIMARY KEY,
- policy_uid UUID NOT NULL
- REFERENCES public.governance_responsibility_policies(uid),
- version INTEGER NOT NULL CHECK (version > 0),
- status VARCHAR(20) NOT NULL CHECK (
- status IN ('draft','published','superseded')
- ),
- definition 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 (policy_uid, version),
- CHECK (jsonb_typeof(definition) = 'object')
- );
- ALTER TABLE public.governance_responsibility_policies
- ADD CONSTRAINT governance_responsibility_active_version_fk
- FOREIGN KEY (active_version_uid)
- REFERENCES public.governance_responsibility_policy_versions(uid);
- CREATE UNIQUE INDEX uq_governance_responsibility_published_version
- ON public.governance_responsibility_policy_versions(policy_uid)
- WHERE status = 'published';
- CREATE INDEX idx_governance_responsibility_policy_scope
- ON public.governance_responsibility_policies(
- scope_type, scope_uid, status
- );
- """
- )
- def downgrade() -> None:
- raise RuntimeError(
- "responsibility delegation and policy evidence is retained; "
- "downgrade requires an approved archival migration"
- )
|