feat(phase-31): add campaign scheduling and recurring automation (T-233 to T-234)

This commit is contained in:
2026-02-10 08:38:00 +01:00
parent 4d124b42dd
commit 02034d60f0
7 changed files with 654 additions and 2 deletions

View File

@@ -8,7 +8,7 @@ import uuid
from datetime import datetime
from sqlalchemy import (
Column, String, Text, Integer, DateTime,
Column, String, Text, Integer, Boolean, DateTime,
ForeignKey, Index,
)
from sqlalchemy.dialects.postgresql import UUID, JSONB
@@ -56,6 +56,17 @@ class Campaign(Base):
tags = Column(JSONB, nullable=True, default=[])
created_at = Column(DateTime, default=datetime.utcnow)
# Recurring scheduling fields
is_recurring = Column(Boolean, default=False)
recurrence_pattern = Column(String, nullable=True) # weekly, monthly, quarterly
next_run_at = Column(DateTime, nullable=True)
last_run_at = Column(DateTime, nullable=True)
parent_campaign_id = Column(
UUID(as_uuid=True),
ForeignKey("campaigns.id", ondelete="SET NULL"),
nullable=True,
)
# Relationships
threat_actor = relationship("ThreatActor")
creator = relationship("User", foreign_keys=[created_by])
@@ -65,12 +76,23 @@ class Campaign(Base):
cascade="all, delete-orphan",
order_by="CampaignTest.order_index",
)
parent_campaign = relationship(
"Campaign",
remote_side="Campaign.id",
foreign_keys=[parent_campaign_id],
)
child_campaigns = relationship(
"Campaign",
foreign_keys=[parent_campaign_id],
back_populates="parent_campaign",
)
__table_args__ = (
Index('ix_campaigns_status', 'status'),
Index('ix_campaigns_type', 'type'),
Index('ix_campaigns_threat_actor', 'threat_actor_id'),
Index('ix_campaigns_created_by', 'created_by'),
Index('ix_campaigns_next_run', 'next_run_at'),
)