Files
govoplan-risk-compliance/src/govoplan_risk_compliance/backend/db/models.py
T

1125 lines
27 KiB
Python

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",
]