| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- """Add immutable device quality policies, runs, results, and evidence."""
- from alembic import op
- revision = "20260729_320"
- down_revision = "20260729_310"
- branch_labels = None
- depends_on = None
- def upgrade() -> None:
- op.execute(
- """
- CREATE TABLE public.device_quality_profiles (
- uid UUID PRIMARY KEY,
- code VARCHAR(120) NOT NULL UNIQUE,
- name VARCHAR(300) NOT NULL,
- created_by VARCHAR(120) NOT NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE TABLE public.device_quality_profile_versions (
- uid UUID PRIMARY KEY,
- profile_uid UUID NOT NULL
- REFERENCES public.device_quality_profiles(uid)
- ON DELETE RESTRICT,
- version INTEGER NOT NULL CHECK (version > 0),
- status VARCHAR(20) NOT NULL DEFAULT 'draft'
- CHECK (status IN ('draft','published','superseded')),
- rules JSONB NOT NULL,
- content_hash CHAR(64) NOT NULL,
- created_by VARCHAR(120) NOT NULL,
- published_by VARCHAR(120),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- published_at TIMESTAMPTZ,
- UNIQUE (profile_uid, version),
- UNIQUE (profile_uid, content_hash)
- );
- CREATE UNIQUE INDEX uq_device_quality_active_profile
- ON public.device_quality_profile_versions(profile_uid)
- WHERE status = 'published';
- CREATE INDEX idx_device_quality_profile_versions
- ON public.device_quality_profile_versions(
- profile_uid, version DESC
- );
- CREATE TABLE public.device_quality_runs (
- uid UUID PRIMARY KEY,
- policy_version_uid UUID NOT NULL
- REFERENCES public.device_quality_profile_versions(uid)
- ON DELETE RESTRICT,
- policy_hash CHAR(64) NOT NULL,
- source_uid UUID
- REFERENCES public.ingestion_sources(uid)
- ON DELETE RESTRICT,
- status VARCHAR(20) NOT NULL
- CHECK (status IN ('success','failed')),
- total_assets INTEGER NOT NULL CHECK (total_assets >= 0),
- total_violations INTEGER NOT NULL CHECK (total_violations >= 0),
- score DOUBLE PRECISION NOT NULL
- CHECK (score >= 0 AND score <= 100),
- created_by VARCHAR(120) NOT NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- CREATE INDEX idx_device_quality_runs_created
- ON public.device_quality_runs(created_at DESC, uid);
- CREATE INDEX idx_device_quality_runs_policy
- ON public.device_quality_runs(policy_version_uid, created_at DESC);
- CREATE TABLE public.device_quality_rule_results (
- uid UUID PRIMARY KEY,
- run_uid UUID NOT NULL
- REFERENCES public.device_quality_runs(uid)
- ON DELETE CASCADE,
- rule_code VARCHAR(120) NOT NULL,
- severity VARCHAR(20) NOT NULL
- CHECK (severity IN ('info','warning','error','critical')),
- weight DOUBLE PRECISION NOT NULL
- CHECK (weight >= 0 AND weight <= 100),
- status VARCHAR(30) NOT NULL
- CHECK (status IN ('passed','violated','not_applicable')),
- evaluated_count INTEGER NOT NULL CHECK (evaluated_count >= 0),
- violation_count INTEGER NOT NULL CHECK (
- violation_count >= 0
- AND violation_count <= evaluated_count
- ),
- sampled_count INTEGER NOT NULL CHECK (
- sampled_count >= 0
- AND sampled_count <= violation_count
- ),
- pass_rate DOUBLE PRECISION NOT NULL
- CHECK (pass_rate >= 0 AND pass_rate <= 1),
- weighted_score DOUBLE PRECISION NOT NULL CHECK (
- weighted_score >= 0 AND weighted_score <= weight
- ),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (run_uid, rule_code)
- );
- CREATE INDEX idx_device_quality_rule_results
- ON public.device_quality_rule_results(
- run_uid, severity, rule_code
- );
- CREATE TABLE public.device_quality_violation_samples (
- uid UUID PRIMARY KEY,
- run_uid UUID NOT NULL
- REFERENCES public.device_quality_runs(uid)
- ON DELETE CASCADE,
- rule_code VARCHAR(120) NOT NULL,
- severity VARCHAR(20) NOT NULL
- CHECK (severity IN ('info','warning','error','critical')),
- asset_uid UUID NOT NULL
- REFERENCES public.device_assets(uid)
- ON DELETE RESTRICT,
- field_name VARCHAR(300) NOT NULL,
- source_uid UUID
- REFERENCES public.ingestion_sources(uid)
- ON DELETE RESTRICT,
- source_mapping_uid UUID
- REFERENCES public.device_asset_source_mappings(uid)
- ON DELETE RESTRICT,
- message VARCHAR(1000) NOT NULL,
- evidence JSONB NOT NULL,
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- expires_at TIMESTAMPTZ NOT NULL,
- UNIQUE (run_uid, rule_code, asset_uid, field_name)
- );
- CREATE INDEX idx_device_quality_violation_run
- ON public.device_quality_violation_samples(
- run_uid, rule_code, asset_uid
- );
- CREATE INDEX idx_device_quality_violation_retention
- ON public.device_quality_violation_samples(expires_at);
- CREATE TABLE public.device_quality_asset_scores (
- uid UUID PRIMARY KEY,
- run_uid UUID NOT NULL
- REFERENCES public.device_quality_runs(uid)
- ON DELETE CASCADE,
- asset_uid UUID NOT NULL
- REFERENCES public.device_assets(uid)
- ON DELETE RESTRICT,
- asset_type VARCHAR(40) NOT NULL,
- status VARCHAR(30) NOT NULL
- CHECK (status IN ('passed','violated','not_applicable')),
- evaluated_rule_count INTEGER NOT NULL
- CHECK (evaluated_rule_count >= 0),
- violation_count INTEGER NOT NULL CHECK (
- violation_count >= 0
- AND violation_count <= evaluated_rule_count
- ),
- score DOUBLE PRECISION NOT NULL
- CHECK (score >= 0 AND score <= 100),
- created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE (run_uid, asset_uid)
- );
- CREATE INDEX idx_device_quality_asset_scores
- ON public.device_quality_asset_scores(
- run_uid, score, asset_uid
- );
- """
- )
- def downgrade() -> None:
- # Quality policies, runs, scores, and violation evidence are retained.
- pass
|