feat(ttp): inspector drawer surfaces evidence + rule_id behind each technique
The TTPsObservedSection rollup tells the operator "we saw T1059" but
not why. Click any technique row → side drawer opens listing every
ttp_tag row in scope with the persisted evidence JSON, firing
rule_id / rule_version, source_kind / source_id, confidence, and
created_at. Mirrors the CredentialReuseInspector / BountyInspector
pattern (drawer-backdrop + bd-head/bd-body + kvs grid).
Backend:
- New `GET /api/v1/ttp/tags/by-{scope}/{uuid}/{technique_id}`
(`scope ∈ {identity, attacker, session}`, optional
`?sub_technique_id=`, `?limit=` capped to 1000). Returns raw
TTPTag rows newest-first.
- New `TTPTagDetailRow` Pydantic model + re-export.
- New repo method `list_tags_by_scope_and_technique` on
TTPMixin (+ abstract on BaseRepository) — single query branched
on scope; identity scope projects through `Attacker.identity_id`
the same way `list_techniques_by_identity` does.
- Tests: evidence round-trips, sub_technique filter, JWT-required,
empty scope, unknown scope rejected.
Frontend:
- New `TTPInspector.tsx` + `TTPInspector.css` (violet accent, slide
animation, focus-trapped panel matching the existing inspector
family).
- `TTPsObservedSection`'s TechniqueBar is now click+keyboard
activatable; clicking opens the inspector for that
(technique, sub_technique) tuple.
mypy clean. 532 passed in the targeted sweep.
This commit is contained in:
@@ -200,6 +200,7 @@ from .ttp import (
|
||||
TTPRule,
|
||||
TTPRuleState,
|
||||
TTPTag,
|
||||
TTPTagDetailRow,
|
||||
TechniqueRollupRow,
|
||||
compute_tag_uuid,
|
||||
)
|
||||
@@ -369,6 +370,7 @@ __all__ = [
|
||||
"CommandEvidence",
|
||||
"EmailEvidence",
|
||||
"IdentityTechniqueRow",
|
||||
"TTPTagDetailRow",
|
||||
"IntelEvidence",
|
||||
"NavigatorLayer",
|
||||
"NavigatorTechnique",
|
||||
|
||||
Reference in New Issue
Block a user