feat(compliance): data classification fields and retention policies job [FASE-3.5]
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
This commit is contained in:
@@ -23,6 +23,7 @@ from app.services.campaign_scheduler_service import check_and_run_recurring_camp
|
||||
from app.jobs.jira_sync_job import sync_all_jira_links
|
||||
from app.services.osint_enrichment_service import enrich_all_techniques
|
||||
from app.services.stale_detection_service import detect_stale_coverage
|
||||
from app.jobs.retention_job import run_retention_job
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -217,10 +218,19 @@ def start_scheduler() -> None:
|
||||
name="Stale coverage detection (daily)",
|
||||
replace_existing=True,
|
||||
)
|
||||
scheduler.add_job(
|
||||
run_retention_job,
|
||||
trigger="interval",
|
||||
hours=24,
|
||||
id="retention_policies",
|
||||
name="Data retention policies (daily)",
|
||||
replace_existing=True,
|
||||
)
|
||||
scheduler.start()
|
||||
logger.info(
|
||||
"Background scheduler started — mitre_sync (24h), intel_scan (7d), "
|
||||
"notification_cleanup (24h), weekly_snapshot (Sundays 00:00), "
|
||||
"recurring_campaigns (daily), jira_sync (1h), "
|
||||
"osint_enrichment (weekly), stale_detection (daily)"
|
||||
"osint_enrichment (weekly), stale_detection (daily), "
|
||||
"retention_policies (daily)"
|
||||
)
|
||||
|
||||
53
backend/app/jobs/retention_job.py
Normal file
53
backend/app/jobs/retention_job.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""Data retention policies — scheduled cleanup of aged records."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.database import SessionLocal
|
||||
from app.models.audit import AuditLog
|
||||
from app.services.notification_service import cleanup_old_notifications
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
AUDIT_LOG_RETENTION_DAYS = 730
|
||||
|
||||
|
||||
def apply_retention_policies(db: Session) -> dict[str, int]:
|
||||
"""Apply retention rules. Commits the session before returning."""
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(days=AUDIT_LOG_RETENTION_DAYS)
|
||||
deleted_audit = (
|
||||
db.query(AuditLog)
|
||||
.filter(AuditLog.timestamp < cutoff)
|
||||
.delete(synchronize_session=False)
|
||||
)
|
||||
if deleted_audit:
|
||||
logger.info(
|
||||
"Retention: deleted %d audit logs older than %d days",
|
||||
deleted_audit,
|
||||
AUDIT_LOG_RETENTION_DAYS,
|
||||
)
|
||||
|
||||
deleted_notifications = cleanup_old_notifications(db, days=90)
|
||||
db.commit()
|
||||
return {
|
||||
"audit_logs_deleted": deleted_audit,
|
||||
"notifications_deleted": deleted_notifications,
|
||||
}
|
||||
|
||||
|
||||
def run_retention_job() -> None:
|
||||
"""Entry point for the daily retention scheduler job."""
|
||||
logger.info("Scheduled retention job starting...")
|
||||
db = SessionLocal()
|
||||
try:
|
||||
summary = apply_retention_policies(db)
|
||||
logger.info("Retention job finished — %s", summary)
|
||||
except Exception:
|
||||
logger.exception("Retention job failed")
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
Reference in New Issue
Block a user