# 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.event.v1` Uniform envelope that wraps every emitted record with a typed discriminator. This is the Python↔Go interoperability contract: any implementation must emit the same envelope for the same input. Modeled on Suricata's EVE JSON — the type-specific payload lives under a key named by `event_type`. Required fields: | Field | Type | Meaning | |---|---|---| | `schema` | string | `enodia.event.v1`. | | `event_type` | string | Discriminator: `alert`, `incident`, or `status` (additive set). | | `timestamp` | string | ISO-8601 emission time. | | `host` | string | Hostname at emission time. | | `` | object | Payload, under a key equal to `event_type` (e.g. `alert` holds an `enodia.alert.v1` object). | ## `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. | | `correlations` | array | Higher-confidence correlation records derived from the incident's raw alerts. Empty when no correlation rule matched. | Each correlation record is additive evidence on the incident and keeps the raw alerts visible. Current fields are `sid`, `signature`, `classtype`, `severity`, `summary`, `window_seconds`, and `matched_signatures`. `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. | | `hash_chain` | object | Local append-only hash-chain summary for snapshots and event logs: path, exists flag, record count, and last chain hash. | | `read_only` | boolean | Always true for this dashboard API. | ## `enodia.hash_chain.v1` JSONL record appended to `hash-chain.jsonl` when Sentinel captures forensic artifacts. This is a local tamper-evidence chain; future fleet/external anchors can mirror the same records off-box. Required fields: | Field | Type | Meaning | |---|---|---| | `schema` | string | `enodia.hash_chain.v1`. | | `time` | number | Unix timestamp when the chain record was appended. | | `kind` | string | Artifact kind, such as `snapshot-log`, `snapshot-json`, or `events-log`. | | `path` | string | Local artifact path that was hashed. | | `size` | integer | Artifact size in bytes, or `0` if unavailable. | | `sha256` | string | SHA-256 of the artifact bytes, empty if unavailable. | | `prev_hash` | string | Previous chain hash, empty for the first usable record. | | `chain_hash` | string | SHA-256 over this record and `prev_hash`. | ## `enodia.first_seen.v1` Local detector state stored in `first-seen.json`. The first detector pass builds a baseline silently; later passes alert on new public destinations per process name and new listener ports per process name. Required fields: | Field | Type | Meaning | |---|---|---| | `schema` | string | `enodia.first_seen.v1`. | | `initialized` | boolean | Whether the initial silent baseline pass has completed. | | `public_destinations` | object | Process name to sorted `host:port` destinations. | | `listener_ports` | object | Process name to sorted listener port strings. | ## `enodia.response.plan.v1` Dry-run response plan from `respond plan `. 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 or rehearses a saved plan with `respond apply --dry-run`. Required fields: | Field | Type | Meaning | |---|---|---| | `schema` | string | `enodia.response.audit.v1`. | | `time` | string | ISO-8601 audit time. | | `event` | string | `response_plan_generated` or `response_apply_rehearsed`. | | `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. | Apply rehearsal records also include `executed: false` and a short `reason`. ## `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`.