feat: add governed cross-module reporting
This commit is contained in:
+142
@@ -0,0 +1,142 @@
|
||||
"""Add governed cross-module report executions and export history.
|
||||
|
||||
Revision ID: b7c4e1a9d2f6
|
||||
Revises: e5b2c9d4f7a1
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = "b7c4e1a9d2f6"
|
||||
down_revision = "e5b2c9d4f7a1"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"reporting_provider_executions",
|
||||
sa.Column("id", sa.String(length=36), nullable=False),
|
||||
sa.Column("tenant_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("execution_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("provider_id", sa.String(length=120), nullable=False),
|
||||
sa.Column("report_id", sa.String(length=255), nullable=False),
|
||||
sa.Column("report_revision", sa.String(length=255), nullable=False),
|
||||
sa.Column("contract_version", sa.String(length=30), nullable=False),
|
||||
sa.Column("idempotency_key", sa.String(length=255), nullable=False),
|
||||
sa.Column("request_sha256", sa.String(length=64), nullable=False),
|
||||
sa.Column("purpose", sa.Text(), nullable=False),
|
||||
sa.Column("audience_scope", sa.JSON(), nullable=False),
|
||||
sa.Column("parameters", sa.JSON(), nullable=False),
|
||||
sa.Column("result_schema", sa.JSON(), nullable=False),
|
||||
sa.Column("result_payload", sa.JSON(), nullable=False),
|
||||
sa.Column("source_revisions", sa.JSON(), nullable=False),
|
||||
sa.Column("effective_scope", sa.JSON(), nullable=False),
|
||||
sa.Column("privacy_transforms", sa.JSON(), nullable=False),
|
||||
sa.Column("provenance", sa.JSON(), nullable=False),
|
||||
sa.Column("governance_provenance", sa.JSON(), nullable=False),
|
||||
sa.Column("retention_class", sa.String(length=120), nullable=False),
|
||||
sa.Column("retention_days", sa.Integer(), nullable=True),
|
||||
sa.Column("expires_at", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("retention_redacted_at", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("output_hash", sa.String(length=64), nullable=False),
|
||||
sa.Column("generated_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column("actor_id", sa.String(length=255), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_reporting_provider_executions")),
|
||||
sa.UniqueConstraint(
|
||||
"tenant_id",
|
||||
"execution_id",
|
||||
name="uq_reporting_provider_execution",
|
||||
),
|
||||
sa.UniqueConstraint(
|
||||
"tenant_id",
|
||||
"idempotency_key",
|
||||
name="uq_reporting_provider_execution_idempotency",
|
||||
),
|
||||
)
|
||||
_indexes(
|
||||
"reporting_provider_executions",
|
||||
"tenant_id",
|
||||
"execution_id",
|
||||
"provider_id",
|
||||
"report_id",
|
||||
"expires_at",
|
||||
"retention_redacted_at",
|
||||
"output_hash",
|
||||
"generated_at",
|
||||
"actor_id",
|
||||
)
|
||||
op.create_index(
|
||||
"ix_reporting_provider_execution_history",
|
||||
"reporting_provider_executions",
|
||||
["tenant_id", "provider_id", "report_id", "generated_at"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
"ix_reporting_provider_execution_retention",
|
||||
"reporting_provider_executions",
|
||||
["tenant_id", "expires_at"],
|
||||
unique=False,
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
"reporting_provider_exports",
|
||||
sa.Column("id", sa.String(length=36), nullable=False),
|
||||
sa.Column("tenant_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("export_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("provider_execution_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("execution_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("format", sa.String(length=30), nullable=False),
|
||||
sa.Column("purpose", sa.Text(), nullable=False),
|
||||
sa.Column("audience_scope", sa.JSON(), nullable=False),
|
||||
sa.Column("output_hash", sa.String(length=64), nullable=False),
|
||||
sa.Column("exported_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column("actor_id", sa.String(length=255), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["provider_execution_id"],
|
||||
["reporting_provider_executions.id"],
|
||||
name=op.f(
|
||||
"fk_reporting_provider_exports_provider_execution_id_reporting_provider_executions"
|
||||
),
|
||||
ondelete="RESTRICT",
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_reporting_provider_exports")),
|
||||
sa.UniqueConstraint(
|
||||
"tenant_id",
|
||||
"export_id",
|
||||
name="uq_reporting_provider_export",
|
||||
),
|
||||
)
|
||||
_indexes(
|
||||
"reporting_provider_exports",
|
||||
"tenant_id",
|
||||
"export_id",
|
||||
"provider_execution_id",
|
||||
"execution_id",
|
||||
"output_hash",
|
||||
"exported_at",
|
||||
"actor_id",
|
||||
)
|
||||
op.create_index(
|
||||
"ix_reporting_provider_export_history",
|
||||
"reporting_provider_exports",
|
||||
["tenant_id", "provider_execution_id", "exported_at"],
|
||||
unique=False,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_table("reporting_provider_exports")
|
||||
op.drop_table("reporting_provider_executions")
|
||||
|
||||
|
||||
def _indexes(table: str, *columns: str) -> None:
|
||||
for column in columns:
|
||||
op.create_index(op.f(f"ix_{table}_{column}"), table, [column], unique=False)
|
||||
Reference in New Issue
Block a user