feat(templates,campaigns): validate MITRE technique IDs, surface template suggestions first, manager can re-approve rejected campaigns
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled

- TestTemplate/TemplateSuggestion creation and updates now reject any
  mitre_technique_id that doesn't match a real, already-synced MITRE
  ATT&CK technique. Frontend swaps the free-text ID input for a
  technique picker.
- Test Catalog now shows pending template suggestions before the
  catalog grid, with full field detail (platform, severity, tool,
  atomic ID, source URL, remediation) instead of just name/procedure.
- A manager can edit and directly re-approve a campaign they previously
  rejected, instead of needing the original lead to resubmit it.
This commit is contained in:
kitos
2026-07-16 14:29:01 +02:00
parent 4809c4a662
commit 82ac9c7014
9 changed files with 327 additions and 21 deletions
@@ -19,7 +19,7 @@ from app.models.template_suggestion import TemplateSuggestion
from app.models.test_template import TestTemplate
from app.models.user import User
from app.services.notification_service import notify_role
from app.services.test_template_service import create_template
from app.services.test_template_service import create_template, validate_mitre_technique_id
_TEAM_BY_ROLE = {"red_tech": "red", "blue_tech": "blue"}
_LEAD_ROLE = {"red": "red_lead", "blue": "blue_lead"}
@@ -45,6 +45,7 @@ def create_template_suggestion(db: Session, submitter: User, **fields: object) -
Does not commit; caller uses UnitOfWork.
"""
team = team_for_submitter(submitter)
validate_mitre_technique_id(db, fields["mitre_technique_id"])
suggestion = TemplateSuggestion(team=team, submitted_by=submitter.id, **fields)
db.add(suggestion)
db.flush()