import uuid from datetime import datetime from sqlalchemy import Boolean, Column, DateTime, Integer, String, Text from app.db.database import Base class IntakeSession(Base): __tablename__ = "intake_sessions" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) created_at = Column(DateTime, default=datetime.utcnow, index=True) patient_name = Column(String, nullable=True) # Optional for now # Original Data transcript = Column(Text, nullable=False) detected_language = Column(String, default="en") # Extracted Data chief_complaint = Column(Text, nullable=True) # SOAP Sections soap_subjective = Column(Text, nullable=True) soap_objective = Column(Text, nullable=True) soap_assessment = Column(Text, nullable=True) soap_plan = Column(Text, nullable=True) # Encryption tracking is_encrypted = Column(Boolean, default=False, nullable=False) class User(Base): __tablename__ = "users" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) username = Column(String, unique=True, index=True, nullable=False) full_name = Column(String, nullable=True) role = Column(String, index=True, nullable=False) hashed_password = Column(Text, nullable=False) is_active = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, index=True) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) # Phase 4: MFA totp_secret = Column(Text, nullable=True) mfa_enrolled_at = Column(DateTime, nullable=True) class AuditLog(Base): __tablename__ = "audit_logs" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) timestamp = Column(DateTime, default=datetime.utcnow, index=True) user_id = Column(String, nullable=True, index=True) username = Column(String, nullable=True, index=True) role = Column(String, nullable=True, index=True) action = Column(String, nullable=False) resource = Column(String, nullable=False) resource_id = Column(String, nullable=True) endpoint = Column(String, nullable=False, index=True) http_method = Column(String, nullable=False) status_code = Column(Integer, nullable=False) ip_address = Column(String, nullable=True) user_agent = Column(Text, nullable=True) details = Column(Text, nullable=True) # Enhanced HIPAA fields data_access_type = Column(String, nullable=True, index=True) # read, write, export, delete, purge phi_accessed = Column(Boolean, default=False, nullable=False) correlation_id = Column(String, nullable=True, index=True) class ConversationSession(Base): """Stores AI Voice Assistant conversation sessions.""" __tablename__ = "conversation_sessions" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) created_at = Column(DateTime, default=datetime.utcnow, index=True) ended_at = Column(DateTime, nullable=True) intake_session_id = Column(String, nullable=True, index=True) mode = Column(String, nullable=False, default="patient") # "patient" or "clinician" state = Column(String, default="greeting") turns_json = Column(Text, nullable=True) # JSON array of conversation turns accumulated_transcript = Column(Text, nullable=True) entities_json = Column(Text, nullable=True) # JSON of extracted entities is_encrypted = Column(Boolean, default=False, nullable=False) class RefreshToken(Base): """Stores hashed refresh tokens for JWT auth.""" __tablename__ = "refresh_tokens" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) user_id = Column(String, nullable=False, index=True) token_hash = Column(String, nullable=False, unique=True, index=True) expires_at = Column(DateTime, nullable=False) revoked = Column(Boolean, default=False, nullable=False) created_at = Column(DateTime, default=datetime.utcnow) ip_address = Column(String, nullable=True) user_agent = Column(Text, nullable=True) class ConsentRecord(Base): """Records patient verbal/written consent before intake processing.""" __tablename__ = "consent_records" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) session_id = Column(String, nullable=False, index=True) patient_identifier = Column(String, nullable=True) consent_type = Column(String, nullable=False, default="verbal") # verbal, written, electronic consented_at = Column(DateTime, default=datetime.utcnow) recorded_by_user_id = Column(String, nullable=True) recorded_by_username = Column(String, nullable=True) details = Column(Text, nullable=True) revoked = Column(Boolean, default=False, nullable=False) revoked_at = Column(DateTime, nullable=True) class DataExportLog(Base): """Tracks all data exports for HIPAA compliance — who exported what, when, and where.""" __tablename__ = "data_export_logs" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) timestamp = Column(DateTime, default=datetime.utcnow, index=True) user_id = Column(String, nullable=True, index=True) username = Column(String, nullable=True, index=True) export_type = Column(String, nullable=False) # fhir, csv, json, pdf resource_type = Column(String, nullable=False) # session, audit_log, report resource_ids = Column(Text, nullable=True) # JSON list of exported resource IDs record_count = Column(Integer, default=0) destination = Column(String, nullable=True) # e.g., "ehr_endpoint", "download", "api" ip_address = Column(String, nullable=True) status = Column(String, default="success") # success, failed, partial details = Column(Text, nullable=True) # ===================================================================== # Phase 2: Document Versioning & Collaborative Annotations # ===================================================================== class DocumentVersion(Base): """Versioned SOAP document with diff tracking. Each edit to a SOAP note creates a new version, preserving full history for audit compliance and collaborative editing. """ __tablename__ = "document_versions" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) session_id = Column(String, nullable=False, index=True) version_number = Column(Integer, nullable=False, default=1) created_at = Column(DateTime, default=datetime.utcnow, index=True) # Author author_id = Column(String, nullable=True, index=True) author_username = Column(String, nullable=True) author_role = Column(String, nullable=True) # clinician, system, ai # SOAP content (JSON blob with all sections) content_json = Column(Text, nullable=False) # Change tracking diff_json = Column(Text, nullable=True) # JSON diff from previous version change_summary = Column(Text, nullable=True) # Human-readable summary change_type = Column(String, nullable=False, default="edit") # initial, edit, ai_generated, review, correction # Metadata confidence_json = Column(Text, nullable=True) # Confidence scores per section is_encrypted = Column(Boolean, default=False, nullable=False) class DocumentAnnotation(Base): """Inline annotation on a specific field of a SOAP document version. Supports corrections, additions, questions, and approval markers from collaborating clinicians. """ __tablename__ = "document_annotations" id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) document_version_id = Column(String, nullable=False, index=True) session_id = Column(String, nullable=False, index=True) created_at = Column(DateTime, default=datetime.utcnow, index=True) # Author author_id = Column(String, nullable=True, index=True) author_username = Column(String, nullable=True) # Location within the SOAP note soap_section = Column(String, nullable=False) # subjective, objective, assessment, plan field_path = Column(String, nullable=True) # e.g., "symptom_details.onset" text_offset_start = Column(Integer, nullable=True) # Character offset in section text text_offset_end = Column(Integer, nullable=True) # Annotation content annotation_type = Column(String, nullable=False) # correction, addition, question, approval, flag content = Column(Text, nullable=False) suggested_replacement = Column(Text, nullable=True) # For corrections # Status status = Column(String, default="open") # open, resolved, rejected resolved_by_id = Column(String, nullable=True) resolved_at = Column(DateTime, nullable=True)