| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- """Add governed AI data rules, standards, production lines, and deployments."""
- from alembic import op
- revision = "20260723_110"
- down_revision = "20260722_110"
- branch_labels = None
- depends_on = None
- def upgrade() -> None:
- op.execute(
- """
- CREATE TABLE public.data_rules (
- id UUID PRIMARY KEY,
- rule_uid UUID NOT NULL UNIQUE,
- name VARCHAR(200) NOT NULL,
- category VARCHAR(50) NOT NULL,
- owner_uid UUID REFERENCES public.users(id) ON DELETE SET NULL,
- status VARCHAR(20) NOT NULL DEFAULT 'active'
- CHECK (status IN ('active','deprecated')),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE TABLE public.data_rule_versions (
- id UUID PRIMARY KEY,
- rule_uid UUID NOT NULL REFERENCES public.data_rules(rule_uid)
- ON DELETE RESTRICT,
- version_no INTEGER NOT NULL CHECK (version_no > 0),
- source_text TEXT NOT NULL,
- source_language VARCHAR(20) NOT NULL DEFAULT 'zh-CN',
- rule_spec JSONB NOT NULL,
- spec_hash CHAR(64) NOT NULL,
- generated_kind VARCHAR(30) NOT NULL DEFAULT 'rulespec'
- CHECK (generated_kind IN (
- 'rulespec','cel','sql','polars','generated_python'
- )),
- status VARCHAR(20) NOT NULL DEFAULT 'draft'
- CHECK (status IN (
- 'draft','validated','published','deprecated','rejected'
- )),
- created_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- published_at TIMESTAMPTZ,
- UNIQUE (rule_uid, version_no),
- UNIQUE (rule_uid, spec_hash)
- );
- CREATE INDEX idx_data_rule_versions_status
- ON public.data_rule_versions(rule_uid, status, version_no DESC);
- CREATE TABLE public.rule_generation_runs (
- id UUID PRIMARY KEY,
- rule_version_id UUID REFERENCES public.data_rule_versions(id)
- ON DELETE SET NULL,
- authoring_surface VARCHAR(30) NOT NULL
- CHECK (authoring_surface IN ('data_standard','data_flow')),
- source_text_hash CHAR(64) NOT NULL,
- model_provider VARCHAR(80) NOT NULL,
- model_name VARCHAR(120) NOT NULL,
- prompt_version VARCHAR(80) NOT NULL,
- schema_version VARCHAR(40) NOT NULL,
- context_hash CHAR(64) NOT NULL,
- candidate_hash CHAR(64) NOT NULL,
- confidence NUMERIC(5,4) NOT NULL
- CHECK (confidence >= 0 AND confidence <= 1),
- assumptions JSONB NOT NULL DEFAULT '[]'::jsonb,
- ambiguities JSONB NOT NULL DEFAULT '[]'::jsonb,
- repair_attempts INTEGER NOT NULL DEFAULT 0
- CHECK (repair_attempts >= 0 AND repair_attempts <= 2),
- decision VARCHAR(30) NOT NULL CHECK (decision IN (
- 'ready','clarification_required','rejected','failed'
- )),
- decision_detail JSONB NOT NULL DEFAULT '{}'::jsonb,
- correlation_id UUID NOT NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE INDEX idx_rule_generation_correlation
- ON public.rule_generation_runs(correlation_id, created_at);
- CREATE TABLE public.data_standards (
- id UUID PRIMARY KEY,
- standard_uid UUID NOT NULL UNIQUE,
- name VARCHAR(200) NOT NULL,
- owner_uid UUID REFERENCES public.users(id) ON DELETE SET NULL,
- status VARCHAR(20) NOT NULL DEFAULT 'active'
- CHECK (status IN ('active','deprecated')),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE TABLE public.data_standard_versions (
- id UUID PRIMARY KEY,
- standard_uid UUID NOT NULL
- REFERENCES public.data_standards(standard_uid)
- ON DELETE RESTRICT,
- version_no INTEGER NOT NULL CHECK (version_no > 0),
- source_text TEXT NOT NULL,
- standard_spec JSONB NOT NULL,
- spec_hash CHAR(64) NOT NULL,
- scope JSONB NOT NULL,
- status VARCHAR(20) NOT NULL DEFAULT 'draft'
- CHECK (status IN (
- 'draft','validated','published','deprecated','rejected'
- )),
- created_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- published_at TIMESTAMPTZ,
- UNIQUE (standard_uid, version_no),
- UNIQUE (standard_uid, spec_hash)
- );
- CREATE INDEX idx_data_standard_versions_status
- ON public.data_standard_versions(
- standard_uid, status, version_no DESC
- );
- CREATE TABLE public.standard_rule_bindings (
- id UUID PRIMARY KEY,
- standard_version_id UUID NOT NULL
- REFERENCES public.data_standard_versions(id)
- ON DELETE RESTRICT,
- clause_id VARCHAR(100) NOT NULL,
- rule_version_id UUID NOT NULL
- REFERENCES public.data_rule_versions(id)
- ON DELETE RESTRICT,
- severity VARCHAR(20) NOT NULL CHECK (
- severity IN ('info','warning','error','critical')
- ),
- exception_policy VARCHAR(20) NOT NULL CHECK (
- exception_policy IN ('reject','quarantine','warn','fail')
- ),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (standard_version_id, clause_id)
- );
- CREATE INDEX idx_standard_rule_binding_rule
- ON public.standard_rule_bindings(rule_version_id);
- CREATE TABLE public.dataflow_versions (
- id UUID PRIMARY KEY,
- dataflow_uid UUID NOT NULL,
- version_no INTEGER NOT NULL CHECK (version_no > 0),
- name VARCHAR(200) NOT NULL,
- source_text TEXT,
- dataflow_spec JSONB NOT NULL,
- input_schema_hashes JSONB NOT NULL,
- output_schema_hash CHAR(64) NOT NULL,
- package JSONB,
- package_hash CHAR(64),
- status VARCHAR(20) NOT NULL DEFAULT 'draft'
- CHECK (status IN (
- 'draft','validated','released','deprecated','rejected'
- )),
- created_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- released_at TIMESTAMPTZ,
- UNIQUE (dataflow_uid, version_no)
- );
- CREATE INDEX idx_dataflow_versions_status
- ON public.dataflow_versions(
- dataflow_uid, status, version_no DESC
- );
- CREATE TABLE public.dataflow_component_bindings (
- id UUID PRIMARY KEY,
- dataflow_version_id UUID NOT NULL
- REFERENCES public.dataflow_versions(id)
- ON DELETE RESTRICT,
- component_id VARCHAR(100) NOT NULL,
- component_kind VARCHAR(30) NOT NULL CHECK (
- component_kind IN (
- 'standard.enforce','rule.apply','quality.check'
- )
- ),
- standard_version_id UUID
- REFERENCES public.data_standard_versions(id)
- ON DELETE RESTRICT,
- rule_version_id UUID
- REFERENCES public.data_rule_versions(id)
- ON DELETE RESTRICT,
- stage VARCHAR(30) NOT NULL,
- order_no INTEGER NOT NULL CHECK (order_no >= 0),
- idempotency JSONB,
- provenance JSONB NOT NULL DEFAULT '{}'::jsonb,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (dataflow_version_id, component_id),
- CHECK (
- (
- component_kind = 'standard.enforce'
- AND standard_version_id IS NOT NULL
- AND rule_version_id IS NULL
- )
- OR (
- component_kind IN ('rule.apply','quality.check')
- AND standard_version_id IS NULL
- AND rule_version_id IS NOT NULL
- )
- )
- );
- CREATE INDEX idx_dataflow_component_standard
- ON public.dataflow_component_bindings(standard_version_id)
- WHERE standard_version_id IS NOT NULL;
- CREATE INDEX idx_dataflow_component_rule
- ON public.dataflow_component_bindings(rule_version_id)
- WHERE rule_version_id IS NOT NULL;
- CREATE TABLE public.rule_execution_plans (
- id UUID PRIMARY KEY,
- component_binding_id UUID NOT NULL
- REFERENCES public.dataflow_component_bindings(id)
- ON DELETE RESTRICT,
- backend VARCHAR(30) NOT NULL CHECK (
- backend IN (
- 'sql_pushdown','polars_batch','quality_check',
- 'generated_python','external_adapter'
- )
- ),
- compiler_version VARCHAR(80) NOT NULL,
- plan JSONB NOT NULL,
- plan_hash CHAR(64) NOT NULL,
- schema_hashes JSONB NOT NULL,
- status VARCHAR(20) NOT NULL DEFAULT 'compiled'
- CHECK (status IN ('compiled','published','revoked')),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (component_binding_id, plan_hash)
- );
- CREATE TABLE public.rule_artifacts (
- id UUID PRIMARY KEY,
- rule_version_id UUID NOT NULL
- REFERENCES public.data_rule_versions(id)
- ON DELETE RESTRICT,
- kind VARCHAR(30) NOT NULL CHECK (
- kind IN ('cel','sql','polars','python','test','manifest')
- ),
- uri VARCHAR(1000) NOT NULL,
- artifact_digest CHAR(64) NOT NULL,
- signature VARCHAR(2000),
- runtime_digest CHAR(64),
- dependency_manifest JSONB NOT NULL DEFAULT '{}'::jsonb,
- status VARCHAR(20) NOT NULL DEFAULT 'built'
- CHECK (status IN ('built','signed','published','revoked')),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (rule_version_id, kind, artifact_digest)
- );
- CREATE TABLE public.dataflow_deployments (
- id UUID PRIMARY KEY,
- dataflow_version_id UUID NOT NULL
- REFERENCES public.dataflow_versions(id)
- ON DELETE RESTRICT,
- environment VARCHAR(20) NOT NULL CHECK (
- environment IN ('development','test','production')
- ),
- workflow_version_id UUID
- REFERENCES public.dataflow_workflow_versions(id)
- ON DELETE SET NULL,
- schedule_plan_id UUID
- REFERENCES public.workflow_schedules(id)
- ON DELETE SET NULL,
- deployment_config JSONB NOT NULL DEFAULT '{}'::jsonb,
- status VARCHAR(30) NOT NULL DEFAULT 'draft' CHECK (
- status IN (
- 'draft','disabled','canary','active','superseded',
- 'rolled_back','failed'
- )
- ),
- activated_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
- activated_at TIMESTAMPTZ,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (dataflow_version_id, environment)
- );
- CREATE UNIQUE INDEX uq_dataflow_deployment_active_environment
- ON public.dataflow_deployments(dataflow_version_id, environment)
- WHERE status = 'active';
- CREATE TABLE public.rule_runs (
- id UUID PRIMARY KEY,
- workflow_run_id UUID REFERENCES public.workflow_runs(id)
- ON DELETE SET NULL,
- deployment_id UUID NOT NULL
- REFERENCES public.dataflow_deployments(id)
- ON DELETE RESTRICT,
- component_binding_id UUID NOT NULL
- REFERENCES public.dataflow_component_bindings(id)
- ON DELETE RESTRICT,
- rule_version_id UUID NOT NULL
- REFERENCES public.data_rule_versions(id)
- ON DELETE RESTRICT,
- plan_hash CHAR(64) NOT NULL,
- rows_in BIGINT NOT NULL DEFAULT 0 CHECK (rows_in >= 0),
- rows_out BIGINT NOT NULL DEFAULT 0 CHECK (rows_out >= 0),
- rows_rejected BIGINT NOT NULL DEFAULT 0 CHECK (rows_rejected >= 0),
- rows_quarantined BIGINT NOT NULL DEFAULT 0 CHECK (
- rows_quarantined >= 0
- ),
- status VARCHAR(30) NOT NULL CHECK (
- status IN (
- 'queued','running','success','failed','unknown','cancelled'
- )
- ),
- timings JSONB NOT NULL DEFAULT '{}'::jsonb,
- correlation_id UUID NOT NULL,
- started_at TIMESTAMPTZ,
- finished_at TIMESTAMPTZ,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE INDEX idx_rule_runs_correlation
- ON public.rule_runs(correlation_id, created_at);
- CREATE TABLE public.rule_violation_samples (
- id UUID PRIMARY KEY,
- rule_run_id UUID NOT NULL REFERENCES public.rule_runs(id)
- ON DELETE CASCADE,
- artifact_ref VARCHAR(1000) NOT NULL,
- sample_count INTEGER NOT NULL CHECK (
- sample_count >= 0 AND sample_count <= 1000
- ),
- redaction_policy VARCHAR(100) NOT NULL,
- expires_at TIMESTAMPTZ NOT NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- """
- )
- def downgrade() -> None:
- # Published standards, rules, production lines, deployments, and run evidence
- # are intentionally retained during application rollback.
- pass
|