from __future__ import annotations from datetime import date, datetime from typing import Any import uuid from sqlalchemy import ( Date, DateTime, ForeignKey, Index, Integer, JSON, String, Text, UniqueConstraint, ) from sqlalchemy.orm import Mapped, mapped_column, relationship from govoplan_core.db.base import Base, TimestampMixin def new_uuid() -> str: return str(uuid.uuid4()) class RiskSanctionsListSnapshot(Base, TimestampMixin): __tablename__ = "risk_sanctions_list_snapshots" __table_args__ = ( UniqueConstraint( "tenant_id", "connector_snapshot_ref", name="uq_risk_sanctions_connector_snapshot", ), Index( "ix_risk_sanctions_snapshot_current", "tenant_id", "provider_id", "status", "acquired_at", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str | None] = mapped_column( String(36), nullable=True, index=True, ) visibility: Mapped[str] = mapped_column( String(20), default="tenant", nullable=False, index=True, ) connector_snapshot_ref: Mapped[str] = mapped_column( String(300), nullable=False, ) provider_id: Mapped[str] = mapped_column( String(100), nullable=False, index=True, ) publisher: Mapped[str] = mapped_column( String(300), nullable=False, ) jurisdiction: Mapped[str] = mapped_column( String(100), nullable=False, index=True, ) list_type: Mapped[str] = mapped_column( String(100), nullable=False, index=True, ) source_id: Mapped[str] = mapped_column( String(200), nullable=False, index=True, ) source_version: Mapped[str] = mapped_column( String(255), nullable=False, index=True, ) publication_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) effective_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) acquired_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) sha256: Mapped[str] = mapped_column( String(64), nullable=False, index=True, ) connector_run_id: Mapped[str] = mapped_column( String(36), nullable=False, ) raw_evidence_ref: Mapped[str] = mapped_column( String(300), nullable=False, ) source_parser_version: Mapped[str] = mapped_column( String(100), nullable=False, ) normalization_version: Mapped[str] = mapped_column( String(100), nullable=False, ) signature_evidence: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) entry_count: Mapped[int] = mapped_column( Integer, default=0, nullable=False, ) status: Mapped[str] = mapped_column( String(30), default="active", nullable=False, index=True, ) imported_by: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True, ) imported_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, ) entries: Mapped[list["RiskSanctionsEntry"]] = relationship( back_populates="snapshot", cascade="all, delete-orphan", ) class RiskSanctionsEntry(Base, TimestampMixin): __tablename__ = "risk_sanctions_entries" __table_args__ = ( UniqueConstraint( "snapshot_id", "source_entry_id", name="uq_risk_sanctions_entry_source", ), Index( "ix_risk_sanctions_entry_name", "snapshot_id", "normalized_name", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) snapshot_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_list_snapshots.id", ondelete="CASCADE", ), nullable=False, index=True, ) source_entry_id: Mapped[str] = mapped_column( String(255), nullable=False, index=True, ) subject_type: Mapped[str] = mapped_column( String(30), nullable=False, index=True, ) primary_name: Mapped[str] = mapped_column( String(1000), nullable=False, ) normalized_name: Mapped[str] = mapped_column( String(1000), nullable=False, index=True, ) original_script_name: Mapped[str | None] = mapped_column( String(1000), nullable=True, ) reference_number: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True, ) listed_on: Mapped[date | None] = mapped_column( Date, nullable=True, ) programmes: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) measures: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) raw_evidence_locator: Mapped[str] = mapped_column( String(500), nullable=False, ) details: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) snapshot: Mapped[RiskSanctionsListSnapshot] = relationship( back_populates="entries" ) aliases: Mapped[list["RiskSanctionsAlias"]] = relationship( back_populates="entry", cascade="all, delete-orphan", ) identifiers: Mapped[list["RiskSanctionsIdentifier"]] = relationship( back_populates="entry", cascade="all, delete-orphan", ) dates: Mapped[list["RiskSanctionsDate"]] = relationship( back_populates="entry", cascade="all, delete-orphan", ) addresses: Mapped[list["RiskSanctionsAddress"]] = relationship( back_populates="entry", cascade="all, delete-orphan", ) class RiskSanctionsAlias(Base): __tablename__ = "risk_sanctions_aliases" __table_args__ = ( Index( "ix_risk_sanctions_alias_name", "entry_id", "normalized_name", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) entry_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_entries.id", ondelete="CASCADE", ), nullable=False, index=True, ) name: Mapped[str] = mapped_column( String(1000), nullable=False, ) normalized_name: Mapped[str] = mapped_column( String(1000), nullable=False, index=True, ) quality: Mapped[str | None] = mapped_column( String(100), nullable=True, ) alias_type: Mapped[str] = mapped_column( String(50), default="aka", nullable=False, ) entry: Mapped[RiskSanctionsEntry] = relationship( back_populates="aliases" ) class RiskSanctionsIdentifier(Base): __tablename__ = "risk_sanctions_identifiers" __table_args__ = ( Index( "ix_risk_sanctions_identifier_value", "entry_id", "normalized_value", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) entry_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_entries.id", ondelete="CASCADE", ), nullable=False, index=True, ) identifier_type: Mapped[str] = mapped_column( String(100), nullable=False, ) value: Mapped[str] = mapped_column( String(1000), nullable=False, ) normalized_value: Mapped[str] = mapped_column( String(1000), nullable=False, index=True, ) issuing_country: Mapped[str | None] = mapped_column( String(255), nullable=True, ) note: Mapped[str | None] = mapped_column( Text, nullable=True, ) entry: Mapped[RiskSanctionsEntry] = relationship( back_populates="identifiers" ) class RiskSanctionsDate(Base): __tablename__ = "risk_sanctions_dates" id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) entry_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_entries.id", ondelete="CASCADE", ), nullable=False, index=True, ) date_type: Mapped[str] = mapped_column( String(50), nullable=False, ) value: Mapped[str] = mapped_column( String(100), nullable=False, ) precision: Mapped[str] = mapped_column( String(30), default="unknown", nullable=False, ) entry: Mapped[RiskSanctionsEntry] = relationship( back_populates="dates" ) class RiskSanctionsAddress(Base): __tablename__ = "risk_sanctions_addresses" id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) entry_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_entries.id", ondelete="CASCADE", ), nullable=False, index=True, ) street: Mapped[str | None] = mapped_column( String(1000), nullable=True, ) city: Mapped[str | None] = mapped_column( String(500), nullable=True, ) region: Mapped[str | None] = mapped_column( String(500), nullable=True, ) postal_code: Mapped[str | None] = mapped_column( String(100), nullable=True, ) country: Mapped[str | None] = mapped_column( String(255), nullable=True, ) note: Mapped[str | None] = mapped_column( Text, nullable=True, ) entry: Mapped[RiskSanctionsEntry] = relationship( back_populates="addresses" ) class RiskScreeningSubjectSnapshot(Base, TimestampMixin): __tablename__ = "risk_screening_subject_snapshots" id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) subject_ref: Mapped[str | None] = mapped_column( String(500), nullable=True, index=True, ) subject_type: Mapped[str] = mapped_column( String(30), nullable=False, ) primary_name: Mapped[str | None] = mapped_column( String(1000), nullable=True, ) normalized_name: Mapped[str | None] = mapped_column( String(1000), nullable=True, index=True, ) aliases: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) identifiers: Mapped[list[dict[str, str]]] = mapped_column( JSON, default=list, nullable=False, ) dates: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) addresses: Mapped[list[dict[str, str]]] = mapped_column( JSON, default=list, nullable=False, ) fingerprint: Mapped[str] = mapped_column( String(64), nullable=False, index=True, ) submitted_by: Mapped[str | None] = mapped_column( String(255), nullable=True, ) class RiskScreeningRun(Base, TimestampMixin): __tablename__ = "risk_screening_runs" __table_args__ = ( UniqueConstraint( "tenant_id", "idempotency_key", name="uq_risk_screening_run_idempotency", ), Index( "ix_risk_screening_run_status", "tenant_id", "outcome", "created_at", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) subject_snapshot_id: Mapped[str] = mapped_column( ForeignKey( "risk_screening_subject_snapshots.id", ondelete="RESTRICT", ), nullable=False, index=True, ) list_snapshot_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_list_snapshots.id", ondelete="RESTRICT", ), nullable=False, index=True, ) idempotency_key: Mapped[str] = mapped_column( String(255), nullable=False, ) request_hash: Mapped[str] = mapped_column( String(64), nullable=False, ) matcher_version: Mapped[str] = mapped_column( String(100), nullable=False, ) normalization_version: Mapped[str] = mapped_column( String(100), nullable=False, ) policy_version: Mapped[str] = mapped_column( String(100), nullable=False, ) policy_snapshot: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) status: Mapped[str] = mapped_column( String(30), nullable=False, index=True, ) outcome: Mapped[str] = mapped_column( String(30), nullable=False, index=True, ) candidate_count: Mapped[int] = mapped_column( Integer, default=0, nullable=False, ) started_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, ) completed_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) created_by: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True, ) subject_snapshot: Mapped[RiskScreeningSubjectSnapshot] = relationship() list_snapshot: Mapped[RiskSanctionsListSnapshot] = relationship() candidates: Mapped[list["RiskScreeningCandidate"]] = relationship( back_populates="run", cascade="all, delete-orphan", ) class RiskScreeningCandidate(Base, TimestampMixin): __tablename__ = "risk_screening_candidates" __table_args__ = ( UniqueConstraint( "run_id", "entry_id", name="uq_risk_screening_candidate_entry", ), Index( "ix_risk_screening_candidate_queue", "tenant_id", "review_status", "score", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) run_id: Mapped[str] = mapped_column( ForeignKey( "risk_screening_runs.id", ondelete="CASCADE", ), nullable=False, index=True, ) entry_id: Mapped[str] = mapped_column( ForeignKey( "risk_sanctions_entries.id", ondelete="RESTRICT", ), nullable=False, index=True, ) score: Mapped[int] = mapped_column( Integer, nullable=False, index=True, ) match_kind: Mapped[str] = mapped_column( String(50), nullable=False, index=True, ) evidence: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False, ) review_status: Mapped[str] = mapped_column( String(30), default="pending", nullable=False, index=True, ) current_disposition_id: Mapped[str | None] = mapped_column( String(36), nullable=True, ) run: Mapped[RiskScreeningRun] = relationship( back_populates="candidates" ) entry: Mapped[RiskSanctionsEntry] = relationship() class RiskScreeningDisposition(Base): __tablename__ = "risk_screening_dispositions" id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) candidate_id: Mapped[str] = mapped_column( ForeignKey( "risk_screening_candidates.id", ondelete="RESTRICT", ), nullable=False, index=True, ) decision: Mapped[str] = mapped_column( String(30), nullable=False, index=True, ) reason: Mapped[str] = mapped_column( Text, nullable=False, ) evidence_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) scope: Mapped[str] = mapped_column( String(30), default="candidate", nullable=False, ) expires_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) review_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) actor_account_id: Mapped[str | None] = mapped_column( String(36), nullable=True, index=True, ) actor_membership_id: Mapped[str | None] = mapped_column( String(36), nullable=True, ) actor_authority: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) separation_status: Mapped[str] = mapped_column( String(30), nullable=False, ) override_reason: Mapped[str | None] = mapped_column( Text, nullable=True, ) supersedes_id: Mapped[str | None] = mapped_column( ForeignKey( "risk_screening_dispositions.id", ondelete="RESTRICT", ), nullable=True, ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) class RiskScreeningException(Base, TimestampMixin): __tablename__ = "risk_screening_exceptions" __table_args__ = ( Index( "ix_risk_screening_exception_active", "tenant_id", "subject_fingerprint", "source_entry_ref", "status", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) subject_fingerprint: Mapped[str] = mapped_column( String(64), nullable=False, index=True, ) source_entry_ref: Mapped[str] = mapped_column( String(500), nullable=False, index=True, ) scope: Mapped[str] = mapped_column( String(30), nullable=False, ) status: Mapped[str] = mapped_column( String(30), default="active", nullable=False, index=True, ) reason: Mapped[str] = mapped_column( Text, nullable=False, ) evidence_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) starts_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, ) expires_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) review_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) originating_disposition_id: Mapped[str] = mapped_column( ForeignKey( "risk_screening_dispositions.id", ondelete="RESTRICT", ), nullable=False, ) created_by: Mapped[str | None] = mapped_column( String(36), nullable=True, ) class RiskAssuranceNode(Base, TimestampMixin): __tablename__ = "risk_assurance_nodes" __table_args__ = ( UniqueConstraint( "tenant_id", "stable_id", "revision", name="uq_risk_assurance_node_revision", ), Index( "ix_risk_assurance_node_current", "tenant_id", "kind", "state", "superseded_at", ), Index( "ix_risk_assurance_node_governed_object", "tenant_id", "governed_object_ref", "superseded_at", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) stable_id: Mapped[str] = mapped_column( String(255), nullable=False, index=True, ) kind: Mapped[str] = mapped_column( String(40), nullable=False, index=True, ) revision: Mapped[int] = mapped_column( Integer, nullable=False, ) previous_revision_id: Mapped[str | None] = mapped_column( ForeignKey( "risk_assurance_nodes.id", ondelete="RESTRICT", ), nullable=True, ) label: Mapped[str] = mapped_column( String(500), nullable=False, ) description: Mapped[str | None] = mapped_column( Text, nullable=True, ) state: Mapped[str] = mapped_column( String(40), nullable=False, index=True, ) owner_ref: Mapped[str] = mapped_column( String(500), nullable=False, index=True, ) scope_ref: Mapped[str | None] = mapped_column( String(500), nullable=True, index=True, ) governed_object_ref: Mapped[str | None] = mapped_column( String(1000), nullable=True, index=True, ) valid_from: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) valid_to: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True, ) recorded_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) superseded_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True, ) provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) legal_basis_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) policy_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) evidence_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) classification: Mapped[str] = mapped_column( String(50), default="internal", nullable=False, index=True, ) created_by: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True, ) class RiskAssuranceEdge(Base, TimestampMixin): __tablename__ = "risk_assurance_edges" __table_args__ = ( UniqueConstraint( "tenant_id", "stable_id", "revision", name="uq_risk_assurance_edge_revision", ), Index( "ix_risk_assurance_edge_source", "tenant_id", "source_node_ref", "state", "superseded_at", ), Index( "ix_risk_assurance_edge_target", "tenant_id", "target_node_ref", "state", "superseded_at", ), ) id: Mapped[str] = mapped_column( String(36), primary_key=True, default=new_uuid, ) tenant_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True, ) stable_id: Mapped[str] = mapped_column( String(255), nullable=False, index=True, ) revision: Mapped[int] = mapped_column( Integer, nullable=False, ) previous_revision_id: Mapped[str | None] = mapped_column( ForeignKey( "risk_assurance_edges.id", ondelete="RESTRICT", ), nullable=True, ) source_node_ref: Mapped[str] = mapped_column( String(255), nullable=False, index=True, ) target_node_ref: Mapped[str] = mapped_column( String(255), nullable=False, index=True, ) relation: Mapped[str] = mapped_column( String(50), nullable=False, index=True, ) state: Mapped[str] = mapped_column( String(30), default="active", nullable=False, index=True, ) owner_ref: Mapped[str] = mapped_column( String(500), nullable=False, index=True, ) scope_ref: Mapped[str | None] = mapped_column( String(500), nullable=True, index=True, ) valid_from: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) valid_to: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True, ) recorded_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True, ) superseded_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True, ) provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False, ) legal_basis_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) policy_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) evidence_refs: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False, ) created_by: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True, ) __all__ = [ "RiskAssuranceEdge", "RiskAssuranceNode", "RiskSanctionsAddress", "RiskSanctionsAlias", "RiskSanctionsDate", "RiskSanctionsEntry", "RiskSanctionsIdentifier", "RiskSanctionsListSnapshot", "RiskScreeningCandidate", "RiskScreeningDisposition", "RiskScreeningException", "RiskScreeningRun", "RiskScreeningSubjectSnapshot", "new_uuid", ]