Skip to content

Domain types

domain

Our internal domain shapes -- the input side of the builder.

Callers construct these from their own data and hand them to build_detection_finding. They deliberately use our vocabulary (the enums in defaults) and hide OCSF's *_id integers, so producing services never touch OCSF field names directly.

ObservableType

Bases: Enum

The observable kinds we currently emit, mapped to OCSF observable type_id.

(OCSF defines ~48 types; we expose the subset our detectors produce. Add members here and to _OBSERVABLE_TYPE_TO_ID in builders as needed.)

Observable dataclass

Observable(
    type: ObservableType,
    value: str,
    name: str | None = None,
)

An entity a finding refers to (host, IP, user, hash, ...).

MitreAttack dataclass

MitreAttack(
    technique_uid: str,
    technique_name: str | None = None,
    tactic_uid: str | None = None,
    tactic_name: str | None = None,
)

A MITRE ATT&CK reference (technique, optionally its tactic).

Maps to an entry in OCSF finding_info.attacks.

DetectionSignal dataclass

DetectionSignal(
    uid: str,
    title: str,
    severity: Severity,
    message: str,
    activity: Activity = CREATE,
    status: Status = NEW,
    observables: list[Observable] = list(),
    description: str | None = None,
    time_ms: int | None = None,
    data_sources: list[str] = list(),
    confidence: Confidence | None = None,
    confidence_score: int | None = None,
    risk_level: RiskLevel | None = None,
    risk_score: int | None = None,
    attacks: list[MitreAttack] = list(),
    count: int | None = None,
    first_seen_ms: int | None = None,
    last_seen_ms: int | None = None,
)

A detection our services produce, in our own terms.

This is the single input shape build_detection_finding maps from. It is intentionally small and OCSF-agnostic; the builder is responsible for the translation to class_uid 2004.