m5c detection families
Detection families define reusable detector shapes. A family declares which detectors are available, what fields and capabilities they need, what matcher operators they support, what parameters they accept, and how detector output is lowered.
Use families to keep detection rules consistent while allowing many detections to share the same runtime shape.
Where family files live
m5c discovers detection families from *.yaml files under a directory named detection_families inside packages.
A typical layout is:
packages/security-analytics/
detection_families/
identity-access.yaml
repo-activity.yaml
detections/
okta-password-spray.yaml
Build a family
Build a family in this order:
- Name the family around a reusable detection domain.
- Decide the result contract, if generated detections emit one.
- Add one or more detector shapes.
- Give every detector a lowering template.
- Declare required fields and capabilities.
- Declare matcher groups and allowed operators.
- Declare parameters and their types.
- Declare dedupe requirements.
- Add detections that reference the family and run
m5c validate.
Family document
kind: DetectionFamily
apiVersion: semantic-catalog.mach5.io/v1alpha1
metadata:
name: identity_access
display_name: Identity Access
spec:
result_contract: security.finding.v1
detectors:
event_match:
lowering:
template: builtin.identity_access.event_match
requires:
fields: [event_uid]
capabilities:
- identity.authentication_event.v1.principal_available
matchers:
field_match:
operators: [eq, neq, in, regex, exists, contains, startswith, endswith]
parameters: {}
dedupe:
required: true
default_strategy: event_entity
aggregation_threshold:
lowering:
template: builtin.identity_access.aggregation_threshold
requires:
fields: [time]
matchers:
field_match:
operators: [eq, neq, in, regex, exists, contains, startswith, endswith]
parameters:
group_by:
type: list<string>
required: true
min_count:
type: int
required: true
window:
type: duration
required: true
dedupe:
required: true
default_strategy: windowed_entity
Top-level fields
| Field | Required | Meaning |
|---|---|---|
kind | Yes | Must be DetectionFamily. |
apiVersion | Recommended | Current examples use semantic-catalog.mach5.io/v1alpha1. |
metadata.name | Yes | Stable family name referenced by detections. |
metadata.display_name | Optional | Human-readable name. |
spec.result_contract | Optional | Contract emitted by generated detection results. |
spec.detectors | Yes | Map of detector names to detector specifications. Must contain at least one detector. |
Detector shape
Each key under spec.detectors is a detector name that detections use in spec.detector.
detectors:
aggregation_threshold:
lowering:
template: builtin.identity_access.aggregation_threshold
requires:
fields: [time]
matchers:
field_match:
operators: [eq, in, contains]
parameters:
min_count:
type: int
required: true
dedupe:
required: true
default_strategy: windowed_entity
Lowering template
Every detector must define lowering.template.
lowering:
template: builtin.identity_access.event_match
The template name is consumed by lowering. Detections provide rule-specific fields, operators, parameters, and output metadata; the detector template provides the runtime shape.
Requirements
Detector requirements describe fields and capabilities expected by the runtime shape.
requires:
fields: [event_uid, time]
capabilities:
- identity.authentication_event.v1.principal_available
Use fields for target contract fields the template needs. Use capabilities for semantic provider coverage that may vary by module.
Matchers and operators
matchers declares allowed operators. Detections using this family cannot use operators outside this list.
matchers:
field_match:
operators: [eq, neq, in, regex, exists, contains, startswith, endswith]
Common operators:
| Operator | Meaning |
|---|---|
eq | Equal. Empty operator defaults to eq. |
neq | Not equal. |
in | Value is in a list. |
contains | String contains substring. |
startswith | String starts with prefix. |
endswith | String ends with suffix. |
regex | Regex-style matcher where supported by lowering. |
exists | Field existence matcher where supported by lowering. |
Note: source-level expected-finding tests currently evaluate eq, in, contains, startswith, and endswith. Other operators may still be valid for lowering when declared by the family, but should be covered with runtime smoke tests.
Parameters
Parameters define detector-specific values that detections may set.
parameters:
group_by:
type: list<string>
required: true
min_count:
type: int
required: true
window:
type: duration
required: true
Supported validation types include:
| Type | Expected YAML value |
|---|---|
string, duration | String |
int, long | Integer |
double, float | Number |
bool, boolean | Boolean |
list<string> | List of strings |
Unknown parameter types are allowed through validation, but should be avoided unless your lowering template handles them.
Dedupe requirements
Use dedupe.required when every detection using the detector must define dedupe fields.
dedupe:
required: true
default_strategy: event_entity
If required: true, m5c validate requires each detection to define both dedupe.strategy and a non-empty dedupe.fields list.
Relationship to detections
A Detection references a family and detector:
spec:
family: identity_access
detector: aggregation_threshold
m5c validate checks that the referenced family and detector exist, that detector parameters match declared types, that required parameters are present, that matcher operators are allowed, and that required dedupe is present.
Validate
m5c validate apps/security-analytics --workspace --offline
Validation checks family kind, family name, at least one detector, lowering templates, parameter types, and detection compatibility with the family.
Common mistakes
| Mistake | Fix |
|---|---|
| Renaming a family used by detections | Update every detection’s spec.family. |
Omitting lowering.template | Add the template name before validation/lowering. |
| Allowing operators your template cannot lower | Keep operator lists aligned with template support. |
| Declaring required parameters without defaults | Ensure every detection sets those parameters. |
Setting dedupe.required: true but omitting detection dedupe | Add dedupe.strategy and dedupe.fields to each detection. |
Best practices
- Keep families stable and reusable.
- Add a new detector when runtime semantics change.
- Use explicit required fields and capabilities so package coverage reports are meaningful.
- Keep lowering templates generic; app-specific details belong in detections and bindings.
- Add a small native detection as an example for every new detector shape.