Spaces:
Paused
Paused
| """ | |
| Entity and Relationship Models | |
| Contains Entity, Relationship, and related models for | |
| network analysis and entity mapping. | |
| """ | |
| import json | |
| import uuid | |
| from sqlalchemy import Column, DateTime, Float, ForeignKey, Index, Integer, String | |
| from sqlalchemy.orm import relationship | |
| from .base import Base, EncryptedString, utc_now | |
| class Entity(Base): | |
| __tablename__ = "entities" | |
| id = Column(String, primary_key=True, index=True) | |
| case_id = Column(String, ForeignKey("cases.id"), index=True) | |
| entity_type = Column(String, index=True) # person, company, account, merchant, etc. | |
| name = Column(EncryptedString) | |
| entity_metadata = Column( | |
| EncryptedString, default=lambda: json.dumps({}) | |
| ) # phone, email, address, ip_address, etc. | |
| # Timestamps | |
| created_at = Column(DateTime, default=utc_now, index=True) | |
| updated_at = Column(DateTime, default=utc_now, onupdate=utc_now) | |
| # Relationships | |
| case = relationship("Case", backref="entities") | |
| source_relationships = relationship( | |
| "Relationship", | |
| foreign_keys="Relationship.source_id", | |
| back_populates="source_entity", | |
| ) | |
| target_relationships = relationship( | |
| "Relationship", | |
| foreign_keys="Relationship.target_id", | |
| back_populates="target_entity", | |
| ) | |
| # Composite indexes | |
| __table_args__ = ( | |
| Index("idx_entity_case_type", "case_id", "entity_type"), | |
| Index("idx_entity_name_type", "name", "entity_type"), | |
| ) | |
| class Relationship(Base): | |
| __tablename__ = "relationships" | |
| id = Column(String, primary_key=True, index=True) | |
| case_id = Column(String, ForeignKey("cases.id"), index=True) | |
| source_id = Column(String, ForeignKey("entities.id"), index=True) | |
| target_id = Column(String, ForeignKey("entities.id"), index=True) | |
| relationship_type = Column( | |
| String, index=True | |
| ) # phone, email, address, ip_address, transaction, etc. | |
| confidence = Column(Float, default=0.0, index=True) | |
| relationship_metadata = Column( | |
| EncryptedString, default=lambda: json.dumps({}) | |
| ) # additional relationship data | |
| # Timestamps | |
| created_at = Column(DateTime, default=utc_now, index=True) | |
| updated_at = Column(DateTime, default=utc_now, onupdate=utc_now) | |
| # Relationships | |
| case = relationship("Case", backref="relationships") | |
| source_entity = relationship( | |
| "Entity", foreign_keys=[source_id], back_populates="source_relationships" | |
| ) | |
| target_entity = relationship( | |
| "Entity", foreign_keys=[target_id], back_populates="target_relationships" | |
| ) | |
| # Composite indexes | |
| __table_args__ = ( | |
| Index("idx_relationship_case_type", "case_id", "relationship_type"), | |
| Index("idx_relationship_source_target", "source_id", "target_id"), | |
| Index("idx_relationship_confidence_type", "confidence", "relationship_type"), | |
| ) | |
| class IdentityNode(Base): | |
| __tablename__ = "identity_nodes" | |
| id = Column(String, primary_key=True, index=True) | |
| case_id = Column(String, ForeignKey("cases.id"), index=True) | |
| identity_type = Column(String, index=True) # person, company, address | |
| attributes = Column(EncryptedString) # JSON of identity attributes | |
| risk_score = Column(Float, default=0.0) | |
| validation_status = Column(String, default="pending") # pending, valid, suspicious | |
| created_at = Column(DateTime, default=utc_now, index=True) | |
| class IdentityRelationship(Base): | |
| __tablename__ = "identity_relationships" | |
| id = Column(String, primary_key=True, index=True) | |
| from_node_id = Column(String, ForeignKey("identity_nodes.id"), index=True) | |
| to_node_id = Column(String, ForeignKey("identity_nodes.id"), index=True) | |
| relationship_type = Column(String, index=True) # shared_address, shared_phone, etc. | |
| confidence_score = Column(Float, default=0.0) | |
| created_at = Column(DateTime, default=utc_now, index=True) | |
| class FrozenEntity(Base): | |
| __tablename__ = "frozen_entities" | |
| id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) | |
| entity_id = Column(String, unique=True, index=True, nullable=False) | |
| entity_type = Column(String, index=True, default="account") | |
| frozen_at = Column(DateTime, default=utc_now) | |
| frozen_by = Column(String) | |
| reason = Column(String) | |
| status = Column(String, default="frozen") # frozen, thawed | |
| metadata_json = Column(String, default=dict) | |
| # Graph and visualization models | |
| class GraphSnapshot(Base): | |
| __tablename__ = "graph_snapshots" | |
| id = Column(String, primary_key=True, index=True) | |
| case_id = Column(String, ForeignKey("cases.id"), index=True) | |
| name = Column(EncryptedString, default="Untitled Snapshot") | |
| description = Column(EncryptedString) | |
| # Graph data stored as JSON | |
| nodes = Column(EncryptedString, default=lambda: json.dumps([])) | |
| links = Column(EncryptedString, default=list) | |
| # Metadata | |
| node_count = Column(Integer, default=0) | |
| link_count = Column(Integer, default=0) | |
| snapshot_metadata = Column(EncryptedString, default=lambda: json.dumps({})) | |
| # User info | |
| created_by = Column(String, index=True) | |
| # Timestamps | |
| created_at = Column(DateTime, default=utc_now, index=True) | |
| updated_at = Column(DateTime, default=utc_now, onupdate=utc_now) | |
| # Relationships | |
| case = relationship("Case", backref="graph_snapshots") | |
| __table_args__ = (Index("idx_snapshot_case_created", "case_id", "created_at"),) | |
| __all__ = [ | |
| "Entity", | |
| "Relationship", | |
| "IdentityNode", | |
| "IdentityRelationship", | |
| "FrozenEntity", | |
| "GraphSnapshot", | |
| ] | |