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:
@@ -10,6 +10,7 @@ from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
# Import Session, joinedload from sqlalchemy.orm
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
|
||||
# Import from app.domain.errors
|
||||
@@ -63,6 +64,8 @@ def list_tests(
|
||||
created_by: uuid.UUID | None = None,
|
||||
# Entry: pending_validation_side
|
||||
pending_validation_side: str | None = None,
|
||||
# Entry: reviewer_id — "my reviews" queue for the red_review/blue_review gate stage
|
||||
reviewer_id: uuid.UUID | None = None,
|
||||
not_in_any_campaign: bool = False,
|
||||
offset: int = 0,
|
||||
# Entry: limit
|
||||
@@ -101,6 +104,23 @@ def list_tests(
|
||||
Test.state == TestState.in_review,
|
||||
Test.blue_validation_status.in_(["pending", None]),
|
||||
)
|
||||
# "My reviews" — tests currently assigned to *reviewer_id* at the
|
||||
# red_review/blue_review lead-review gate (distinct from
|
||||
# pending_validation_side, which covers the later in_review stage).
|
||||
if reviewer_id:
|
||||
if state == TestState.red_review.value:
|
||||
query = query.filter(Test.red_reviewer_assignee == reviewer_id)
|
||||
elif state == TestState.blue_review.value:
|
||||
query = query.filter(Test.blue_reviewer_assignee == reviewer_id)
|
||||
else:
|
||||
query = query.filter(
|
||||
Test.state.in_([TestState.red_review, TestState.blue_review]),
|
||||
or_(
|
||||
Test.red_reviewer_assignee == reviewer_id,
|
||||
Test.blue_reviewer_assignee == reviewer_id,
|
||||
),
|
||||
)
|
||||
|
||||
if not_in_any_campaign:
|
||||
linked = db.query(CampaignTest.test_id).distinct().subquery()
|
||||
query = query.filter(~Test.id.in_(linked))
|
||||
|
||||
Reference in New Issue
Block a user