feat(backend): enforce campaign scheduling, add reviewer queue filter, tactic order, duplicate-test counts
- start_execution now blocks a test from starting before its campaign's start_date, closing a gap where the field was persisted but never enforced - GET /tests gains a reviewer_id "my reviews" filter for the red_review/ blue_review lead-gate stage, distinct from pending_validation_side (which only ever covered the later in_review stage and ignored assignment entirely) - get_coverage_by_tactic now returns all 14 MITRE tactics in canonical kill-chain order instead of an alphabetical, partial list — the regular Dashboard and Executive Dashboard both consume this endpoint and previously disagreed on order/completeness - test-template listing now includes existing_test_count per technique so the catalog can warn before creating a likely-duplicate test
This commit is contained in:
@@ -28,6 +28,7 @@ from sqlalchemy.orm import Session
|
||||
from app.config import settings
|
||||
from app.domain.exceptions import BusinessRuleViolation, InvalidOperationError
|
||||
from app.domain.test_entity import TestEntity
|
||||
from app.models.campaign import Campaign, CampaignTest
|
||||
from app.models.enums import TestState, TeamSide
|
||||
from app.models.evidence import Evidence
|
||||
from app.models.test import Test
|
||||
@@ -174,8 +175,26 @@ def transition_state(
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _get_campaign_start_date(db: Session, test_id) -> datetime | None:
|
||||
"""Return the scheduled start_date of the campaign *test_id* belongs to, if any."""
|
||||
campaign = (
|
||||
db.query(Campaign)
|
||||
.join(CampaignTest, CampaignTest.campaign_id == Campaign.id)
|
||||
.filter(CampaignTest.test_id == test_id)
|
||||
.first()
|
||||
)
|
||||
return campaign.start_date if campaign else None
|
||||
|
||||
|
||||
def start_execution(db: Session, test: Test, user: User) -> Test:
|
||||
"""Move from ``draft`` → ``red_executing``."""
|
||||
campaign_start_date = _get_campaign_start_date(db, test.id)
|
||||
if campaign_start_date and campaign_start_date > datetime.utcnow():
|
||||
raise BusinessRuleViolation(
|
||||
"This test's campaign is scheduled to start on "
|
||||
f"{campaign_start_date.date().isoformat()} — it cannot be started before then."
|
||||
)
|
||||
|
||||
entity = TestEntity.from_orm(test)
|
||||
# Call entity.start_execution()
|
||||
entity.start_execution()
|
||||
|
||||
Reference in New Issue
Block a user