Skip to content

Add JSON DTO with computed mitre_tactic / mitre_name when SIEM consumer needs them #64

@Zious11

Description

@Zious11

Trigger

The MITRE ATT&CK mapping spec (`docs/superpowers/specs/2026-04-13-mitre-attack-mapping-design.md`) explicitly defers JSON schema additions for `mitre_tactic` and `mitre_name`. Today the JSON output emits only `mitre_technique` (the ID); downstream consumers must perform their own ID→tactic/name lookup.

Why deferred (already validated)

Brainstorming Question 2 (Perplexity-validated): "tactic derived at render time" was chosen over "tactic stored on `Finding`" because:

  1. STIX 2.1 uses normalized relationship objects (derived).
  2. Suricata EVE denormalizes (stores `mitre_tactic_id` alongside `mitre_technique_id`) for SIEM grep-friendliness — the alternative pattern.
  3. Perplexity recommended the DTO-with-`From<&Original>` pattern as "most maintainable" for adding derived fields without polluting the source struct.

Today there is no SIEM-ingestion consumer of wirerust's JSON output. Adding the derived fields preemptively is YAGNI.

Trigger condition for this issue

When the first SIEM-ingestion or downstream-tooling consumer of `wirerust` JSON output asks for `mitre_tactic` and/or `mitre_name` fields.

Suggested approach if undertaken

Per the brainstorming validation:

```rust
// New file: src/reporter/json_dto.rs (or inline in src/reporter/json.rs)
#[derive(Serialize)]
pub(crate) struct FindingJsonDto<'a> {
#[serde(flatten)]
inner: &'a Finding,
#[serde(skip_serializing_if = "Option::is_none")]
mitre_tactic: Option,
#[serde(skip_serializing_if = "Option::is_none")]
mitre_name: Option<&'static str>,
}

impl<'a> From<&'a Finding> for FindingJsonDto<'a> {
fn from(f: &'a Finding) -> Self {
let id = f.mitre_technique.as_deref();
Self {
inner: f,
mitre_tactic: id
.and_then(crate::mitre::technique_tactic)
.map(|t| t.to_string()),
mitre_name: id.and_then(crate::mitre::technique_name),
}
}
}
```

JSON reporter renders `Vec` instead of `Vec<&Finding>`. `Finding` itself is untouched.

Acceptance criteria

  • New fields appear in JSON output only when `mitre_technique` is set AND it resolves in the lookup.
  • Existing JSON consumers (none today) are unbroken — `mitre_technique` retains its current emission.
  • Snapshot or substring tests covering the JSON output for at least one finding with each field combination.
  • Document the addition in any consumer-facing JSON schema notes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestreporterOutput/export formats

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions