MITRE ATT&CK STIX data never includes primary_motivation on intrusion-set
objects. Motivation is now derived with a 3-tier fallback:
1. Curated MITRE-ID override map (100+ known groups mapped by hand)
2. STIX primary_motivation field (if MITRE ever adds it)
3. Description keyword inference (financ/ransomware/espionage/
nation-state/destructive/hacktivist patterns)
Re-running MITRE sync will now backfill motivation for existing actors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>