Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Tasks 8.1-8.5: Models (8.1): - DetectionAsset: SIEM/EDR/Sigma rule assets with auto-hash - DetectionTechniqueMapping: N:M asset ↔ technique coverage - DetectionValidation: immutable validation records with expiry - TechniqueConfidenceScore: computed multi-factor confidence - InfrastructureChangeLog: infra changes that invalidate detections - DecayPolicy: configurable freshness thresholds per platform/tactic Services (8.2, 8.3): - detection_asset_service: CRUD + SHA-256 rule hashing + auto- invalidation on rule/infra changes - decay_engine_service: daily decay engine — expires stale validations, recalculates confidence (recency/coverage/health/diversity factors), processes infrastructure change propagation Router (8.4): 15 endpoints under /api/v1/detection-lifecycle: assets CRUD, technique mappings, validations, confidence scores, infrastructure changes, decay trigger, executive dashboard Scheduler (8.3): decay engine runs daily at 02:00 Seed (8.5): default policy (90/180/365d) + strict initial-access policy Migration: b034dlm (6 tables, 11 indexes) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
33 lines
1.6 KiB
Python
33 lines
1.6 KiB
Python
"""Decay Policy model — configurable detection validity rules."""
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from sqlalchemy import Column, String, Integer, Float, Boolean, DateTime, Text
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from app.database import Base
|
|
|
|
|
|
class DecayPolicy(Base):
|
|
__tablename__ = "decay_policies"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
name = Column(String(200), nullable=False)
|
|
description = Column(Text)
|
|
applies_to_platform = Column(String(100))
|
|
applies_to_asset_type = Column(String(50))
|
|
applies_to_tactic = Column(String(100))
|
|
fresh_days = Column(Integer, default=90, server_default='90')
|
|
aging_days = Column(Integer, default=180, server_default='180')
|
|
stale_days = Column(Integer, default=365, server_default='365')
|
|
default_validity_days = Column(Integer, default=180, server_default='180')
|
|
silent_threshold_days = Column(Integer, default=30, server_default='30')
|
|
noisy_threshold_daily = Column(Integer, default=100, server_default='100')
|
|
recency_weight = Column(Float, default=0.3, server_default='0.3')
|
|
coverage_weight = Column(Float, default=0.3, server_default='0.3')
|
|
health_weight = Column(Float, default=0.25, server_default='0.25')
|
|
diversity_weight = Column(Float, default=0.15, server_default='0.15')
|
|
is_default = Column(Boolean, default=False, server_default='false')
|
|
is_active = Column(Boolean, default=True, server_default='true')
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.utcnow)
|