Files
orion/app/modules/prospecting/models/security_audit.py
Samir Boulahtit 972ee1e5d0 feat(prospecting): add ProspectSecurityAudit model (Phase 1 foundation)
- New model: ProspectSecurityAudit with score, grade, findings_json,
  severity counts, has_https, has_valid_ssl, missing_headers, exposed
  files, technologies, scan_error
- Add last_security_audit_at timestamp to Prospect model
- Add security_audit 1:1 relationship on Prospect

Part of Phase 1: Security Audit in Enrichment Pipeline. Service,
constants, migration, endpoints, and frontend to follow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:23:38 +02:00

60 lines
2.3 KiB
Python

# app/modules/prospecting/models/security_audit.py
"""
Security audit results for a prospect's website.
Stores findings from passive security checks (HTTPS, headers, exposed files,
cookies, server info, technology detection). Follows the same 1:1 pattern as
ProspectTechProfile and ProspectPerformanceProfile.
"""
from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.orm import relationship
from app.core.database import Base
from models.database.base import TimestampMixin
class ProspectSecurityAudit(Base, TimestampMixin):
"""Security audit results for a prospect's website."""
__tablename__ = "prospect_security_audits"
id = Column(Integer, primary_key=True, index=True)
prospect_id = Column(
Integer,
ForeignKey("prospects.id", ondelete="CASCADE"),
nullable=False,
unique=True,
)
# Overall score and grade
score = Column(Integer, nullable=False, default=0) # 0-100
grade = Column(String(2), nullable=False, default="F") # A+, A, B, C, D, F
# Detected language for bilingual reports
detected_language = Column(String(5), nullable=True, default="en")
# Findings stored as JSON (variable structure per check)
findings_json = Column(Text, nullable=True) # JSON list of finding dicts
# Denormalized severity counts (for dashboard queries without JSON parsing)
findings_count_critical = Column(Integer, nullable=False, default=0)
findings_count_high = Column(Integer, nullable=False, default=0)
findings_count_medium = Column(Integer, nullable=False, default=0)
findings_count_low = Column(Integer, nullable=False, default=0)
findings_count_info = Column(Integer, nullable=False, default=0)
# Key results (denormalized for quick access)
has_https = Column(Boolean, nullable=True)
has_valid_ssl = Column(Boolean, nullable=True)
ssl_expires_at = Column(DateTime, nullable=True)
missing_headers_json = Column(Text, nullable=True) # JSON list of header names
exposed_files_json = Column(Text, nullable=True) # JSON list of exposed paths
technologies_json = Column(Text, nullable=True) # JSON list of detected techs
# Scan metadata
scan_error = Column(Text, nullable=True)
# Relationships
prospect = relationship("Prospect", back_populates="security_audit")