fix(threat-actors): fix 500 on search + populate motivation from STIX
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled

1. fix(search 500): func.cast(col, func.text()) is invalid SQLAlchemy —
   replaced with cast(col, Text) for both aliases and target_sectors
   JSONB columns. Generating correct CAST(col AS TEXT) SQL.

2. feat(motivation): extract primary_motivation and sophistication from
   STIX intrusion-set objects during MITRE sync. Added _normalize_motivation()
   to map STIX vocabulary → simplified frontend values (espionage / financial /
   destruction / hacktivism). Both create and update paths now set these fields.
   Run MITRE sync to backfill existing actors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kitos
2026-05-29 14:09:04 +02:00
parent 7d856bef43
commit e49eca0b24
2 changed files with 49 additions and 3 deletions

View File

@@ -10,7 +10,7 @@ from __future__ import annotations
from typing import Any
from sqlalchemy import case, func, or_
from sqlalchemy import case, cast, func, or_, Text
from sqlalchemy.orm import Session
from app.domain.errors import EntityNotFoundError
@@ -49,7 +49,7 @@ def list_actors(
or_(
ThreatActor.name.ilike(pattern),
ThreatActor.description.ilike(pattern),
func.cast(ThreatActor.aliases, func.text()).ilike(pattern),
cast(ThreatActor.aliases, Text).ilike(pattern),
)
)
@@ -64,7 +64,7 @@ def list_actors(
if target_sectors:
query = query.filter(
func.cast(ThreatActor.target_sectors, func.text()).ilike(
cast(ThreatActor.target_sectors, Text).ilike(
f"%{escape_like(target_sectors)}%"
)
)