enodia-sentinal/docs/SCHEMAS.md
2026-07-08 17:05:17 -07:00

180 lines
6.9 KiB
Markdown

# Enodia Sentinel JSON Schemas
Applies to package version: `0.7.0`
Docs version: `0.7`
Schema generation: `v1`
Sentinel uses stable schema IDs for operator-facing JSON contracts. These IDs
are lightweight compatibility markers, not external JSON Schema files. The v1
rule is additive: future releases may add fields, but required v1 fields should
not be removed, renamed, or change type.
Schema IDs live in `enodia_sentinel/schemas.py`, and compatibility tests in
`tests/test_schema_contracts.py` pin the required v1 fields.
## `enodia.alert.v1`
Single detection object, used inside alert snapshots and by commands such as
`posture check --json`.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `sid` | integer | Stable signature/rule id. |
| `severity` | string | `MEDIUM`, `HIGH`, or `CRITICAL`. |
| `signature` | string | Stable machine-readable detection name. |
| `classtype` | string | Snort/Suricata-style category. |
| `key` | string | Cooldown/dedup identity. |
| `detail` | string | Human-readable finding detail. |
| `pids` | array | Process IDs tied to the finding. |
## `enodia.alert.snapshot.v1`
Structured alert sidecar written beside each text snapshot under `log_dir`.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.alert.snapshot.v1`. |
| `time` | string | ISO-8601 capture time. |
| `host` | string | Hostname at capture time. |
| `severity` | string | Highest severity in the snapshot. |
| `incident_id` | string or null | Incident grouping id, when enabled. |
| `alerts` | array | `enodia.alert.v1` objects. |
| `processes` | array | Captured process context for alert PIDs. |
| `enrichment` | object | Best-effort post-alert context: package ownership, executable hashes, parent chain, remote IP classification, file metadata, recent watched writes, and local integrity/rootcheck anchor status. |
## `enodia.incident.v1`
Incident index record stored in `incidents.json`.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.incident.v1`. |
| `id` | string | Stable incident id. |
| `host` | string | Host that produced the incident. |
| `first_ts`, `last_ts` | number | Unix timestamps for first/last activity. |
| `first_seen`, `last_seen` | string | ISO-8601 first/last activity times. |
| `severity` | string | Highest incident severity. |
| `signatures` | array | Unique detection signatures in the incident. |
| `sids` | array | Unique SIDs in the incident. |
| `pids` | array | Alert PIDs observed in the incident. |
| `lineage` | array | Process-lineage IDs used for grouping. |
| `snapshots` | array | Member snapshot filenames. |
| `alert_count` | integer | Total alerts grouped into the incident. |
`incident show --json` returns `enodia.incident.view.v1` with `schema`,
`incident`, and `timeline`. The dashboard incident API returns the same schema
plus `snapshots`. `incident export` returns `enodia.incident.bundle.v1` with
`schema`, `incident`, and inlined `snapshots`.
## `enodia.status.v1`
Health/status object returned by `status --json` and `/api/status`.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.status.v1`. |
| `version` | string | Sentinel package version. |
| `running` | boolean | Whether the daemon pid appears alive. |
| `total_alerts` | integer | Count of retained alert snapshots. |
| `counts` | object | Per-severity retained alert counts. |
| `last_alert` | string or null | Most recent retained alert time. |
| `ebpf`, `ebpf_exec`, `ebpf_syscall` | string | Last observed sensor states. |
| `host` | string | Hostname. |
| `heartbeat_age` | number or null | Seconds since heartbeat, if present. |
| `heartbeat_stale` | boolean | Whether heartbeat exceeds configured max age. |
## `enodia.integrity.v1`
Integrity/watchdog object returned by `/api/integrity`. This is a read-only
summary of existing state; the dashboard endpoint does not run live FIM or
package verification work.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.integrity.v1`. |
| `generated_at` | number | Unix timestamp when the report was built. |
| `status` | string | Overall state: `ok`, `review`, or `critical`. |
| `checks` | object | Compact per-check status map. |
| `watchdog` | object | Daemon running state, heartbeat age, stale flag, max age, and verdict message. |
| `anchors` | object | FIM baseline, package DB anchor, pacman keyring, and SigLevel summary. |
| `sentinel_footprint` | object | Configured Sentinel self-integrity paths and present/missing counts. |
| `read_only` | boolean | Always true for this dashboard API. |
## `enodia.response.plan.v1`
Dry-run response plan from `respond plan <incident-id>`.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.response.plan.v1`. |
| `plan_id` | string | Stable plan id for the incident. |
| `incident_id` | string | Source incident. |
| `created_at` | string | ISO-8601 plan time. |
| `mode` | string | Currently `dry-run`. |
| `apply_supported` | boolean | Currently `false`. |
| `summary` | object | Severity, signatures, snapshot/action counts. |
| `actions` | array | Reviewable action proposals. |
| `notes` | array | Operator cautions. |
CLI-generated plans may also include `artifacts` with saved plan/audit paths.
## `enodia.response.audit.v1`
JSONL record appended when the CLI persists a response plan.
Required fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.response.audit.v1`. |
| `time` | string | ISO-8601 audit time. |
| `event` | string | Currently `response_plan_generated`. |
| `actor` | string | Caller identity supplied by the CLI/workflow. |
| `plan_id` | string | Persisted plan id. |
| `incident_id` | string | Source incident id. |
| `mode` | string | Plan mode. |
| `apply_supported` | boolean | Whether the plan supports apply. |
| `action_count` | integer | Number of proposed actions. |
| `plan_path` | string | Persisted plan artifact path. |
## `enodia.reconcile.v1`
Acknowledged-drift store written by `baseline accept/revoke/list`
(`log_dir/reconciliation.json`, overridable via `reconcile_store`) and emitted
by `baseline list --json`.
Top-level fields:
| Field | Type | Meaning |
|---|---|---|
| `schema` | string | `enodia.reconcile.v1`. |
| `records` | array | Acknowledgement records (below). |
Each record:
| Field | Type | Meaning |
|---|---|---|
| `kind` | string | `fim`, `pkgfile`, `listener`, or `suid`. |
| `target` | string | Path, or `port/comm` key for listeners. |
| `fingerprint` | object | Kind-specific identity compared each sweep. |
| `reason` | string | Mandatory operator justification. |
| `actor` | string | Who recorded the acceptance. |
| `accepted_at` | string | ISO-8601 UTC acceptance time. |
| `status` | string | `ok` or `stale`. |
| `expires_at` | string | ISO-8601 UTC TTL; absent when no TTL. |
The dashboard `enodia.integrity.v1` payload also carries a `reconciliation`
summary object (`total`, `ok`, `stale`, `stale_items`) and a `reconciliation`
entry under `checks`.