"""NEW tables (explicit follow-up to Ch10's flagged scope gap): bounded per-IP traffic breakdown so the IP investigation panel reflects TRUE full traffic, not just bot_hits/suspicious_events activity. CARDINALITY NOTE: unlike the other Method-A tables, this one's row count scales with distinct IPs per day, which is unbounded for a probed site. Two mitigations: ip_path_stats_daily keeps only the top N paths per IP per day (not every ip x path pair); both tables use log_entries' ~30-day retention (Ch06), enforced by `flask cleanup` (Chapter 12). """ from __future__ import annotations from app.extensions import db class IpPathStatsDaily(db.Model): __tablename__ = "ip_path_stats_daily" date = db.Column(db.Date, primary_key=True) ip: str = db.Column(db.String(45), primary_key=True) path: str = db.Column(db.String(2048), primary_key=True) count: int = db.Column(db.Integer, nullable=False, default=0) __table_args__ = (db.Index("ix_ip_path_stats_ip", "ip"),) class IpStatusStatsDaily(db.Model): __tablename__ = "ip_status_stats_daily" date = db.Column(db.Date, primary_key=True) ip: str = db.Column(db.String(45), primary_key=True) status_bucket: str = db.Column(db.String(8), primary_key=True) # 2xx|3xx|4xx|5xx count: int = db.Column(db.Integer, nullable=False, default=0) __table_args__ = (db.Index("ix_ip_status_stats_ip", "ip"),)