# Runtime Evidence Schema Reference ## Overview Runtime evidence is serialized as NDJSON (Newline-Delimited JSON), with one event per line. The schema ensures deterministic output for reproducible evidence chains. ## Schema Location - JSON Schema: `docs/schemas/runtime-evidence-v1.json` - C# Models: `src/Signals/__Libraries/StellaOps.Signals.Ebpf/Schema/` ## Common Fields Every evidence record includes these base fields: | Field | Type | Required | Description | |-------|------|----------|-------------| | `ts_ns` | integer | Yes | Nanoseconds since system boot | | `src` | string | Yes | Event source identifier | | `pid` | integer | Yes | Process ID | | `tid` | integer | No | Thread ID (if available) | | `cgroup_id` | integer | Yes | Kernel cgroup ID | | `container_id` | string | No | Container ID (enriched) | | `image_digest` | string | No | Image digest (enriched) | | `comm` | string | No | Process command name (max 16 chars) | | `event` | object | Yes | Type-specific event data | ## Event Types ### File Access (`file_access`) Captured from `sys_enter_openat` tracepoint. ```json { "ts_ns": 1234567890123456789, "src": "tracepoint:syscalls:sys_enter_openat", "pid": 1234, "cgroup_id": 5678, "container_id": "abc123def456", "image_digest": "sha256:...", "comm": "nginx", "event": { "type": "file_access", "path": "/etc/nginx/nginx.conf", "flags": 0, "mode": 0, "access": "read" } } ``` | Field | Type | Description | |-------|------|-------------| | `path` | string | File path (max 256 chars) | | `flags` | integer | Open flags (`O_RDONLY`, `O_WRONLY`, etc.) | | `mode` | integer | File mode (for creation) | | `access` | string | Derived access type: `read`, `write`, `read_write` | ### Process Execution (`process_exec`) Captured from `sched_process_exec` tracepoint. ```json { "ts_ns": 1234567890123456789, "src": "tracepoint:sched:sched_process_exec", "pid": 1234, "cgroup_id": 5678, "container_id": "abc123def456", "image_digest": "sha256:...", "comm": "python3", "event": { "type": "process_exec", "filename": "/usr/bin/python3", "ppid": 1000, "argv": ["python3", "script.py", "--config", "/etc/app.conf"] } } ``` | Field | Type | Description | |-------|------|-------------| | `filename` | string | Executed binary path | | `ppid` | integer | Parent process ID | | `argv` | string[] | Command arguments (limited to first 4) | ### TCP State Change (`tcp_state`) Captured from `inet_sock_set_state` tracepoint. ```json { "ts_ns": 1234567890123456789, "src": "tracepoint:sock:inet_sock_set_state", "pid": 1234, "cgroup_id": 5678, "container_id": "abc123def456", "image_digest": "sha256:...", "comm": "curl", "event": { "type": "tcp_state", "family": "ipv4", "old_state": "SYN_SENT", "new_state": "ESTABLISHED", "src_addr": "10.0.0.5", "src_port": 45678, "dst_addr": "93.184.216.34", "dst_port": 443 } } ``` | Field | Type | Description | |-------|------|-------------| | `family` | string | Address family: `ipv4` or `ipv6` | | `old_state` | string | Previous TCP state | | `new_state` | string | New TCP state | | `src_addr` | string | Source IP address | | `src_port` | integer | Source port | | `dst_addr` | string | Destination IP address | | `dst_port` | integer | Destination port | TCP States: `CLOSED`, `LISTEN`, `SYN_SENT`, `SYN_RECV`, `ESTABLISHED`, `FIN_WAIT1`, `FIN_WAIT2`, `CLOSE_WAIT`, `CLOSING`, `LAST_ACK`, `TIME_WAIT` ### Network Operation (`network_op`) Captured from libc `connect`/`accept` uprobes. ```json { "ts_ns": 1234567890123456789, "src": "uprobe:libc.so.6:connect", "pid": 1234, "cgroup_id": 5678, "container_id": "abc123def456", "image_digest": "sha256:...", "comm": "app", "event": { "type": "network_op", "operation": "connect", "family": "ipv4", "addr": "10.0.1.100", "port": 5432, "result": 0 } } ``` | Field | Type | Description | |-------|------|-------------| | `operation` | string | `connect` or `accept` | | `family` | string | Address family | | `addr` | string | Remote address | | `port` | integer | Remote port | | `result` | integer | Return value (0 = success) | ### SSL Operation (`ssl_op`) Captured from OpenSSL `SSL_read`/`SSL_write` uprobes. ```json { "ts_ns": 1234567890123456789, "src": "uprobe:libssl.so.3:SSL_write", "pid": 1234, "cgroup_id": 5678, "container_id": "abc123def456", "image_digest": "sha256:...", "comm": "nginx", "event": { "type": "ssl_op", "operation": "write", "requested_bytes": 1024, "actual_bytes": 1024, "ssl_ptr": 140234567890 } } ``` | Field | Type | Description | |-------|------|-------------| | `operation` | string | `read` or `write` | | `requested_bytes` | integer | Bytes requested | | `actual_bytes` | integer | Bytes actually transferred | | `ssl_ptr` | integer | SSL context pointer (for correlation) | ### Symbol Call (`symbol_call`) Captured from function uprobes. ```json { "ts_ns": 1234567890123456789, "src": "uprobe:app:vulnerable_parse_json", "pid": 1234, "cgroup_id": 5678, "container_id": "abc123def456", "image_digest": "sha256:...", "comm": "app", "event": { "type": "symbol_call", "symbol": "vulnerable_parse_json", "library": "/usr/lib/libapp.so", "offset": 4096, "address": 140234571986 } } ``` | Field | Type | Description | |-------|------|-------------| | `symbol` | string | Function symbol name | | `library` | string | Library/binary path | | `offset` | integer | Offset within library | | `address` | integer | Runtime address | ## Determinism Requirements For byte-identical output across runs: 1. **Field Ordering**: All JSON keys sorted alphabetically 2. **Number Format**: Integers as-is, no floating point variance 3. **String Encoding**: UTF-8 with NFC normalization 4. **Null Handling**: Null fields omitted (not `"field": null`) 5. **Whitespace**: No trailing whitespace, single newline per record ## Chunk Metadata Each evidence chunk includes metadata in its DSSE attestation: ```json { "predicateType": "stella.ops/runtime-evidence@v1", "predicate": { "chunk_id": "sha256:abc123...", "chunk_sequence": 42, "previous_chunk_id": "sha256:def456...", "event_count": 150000, "time_range": { "start": "2026-01-27T10:00:00Z", "end": "2026-01-27T11:00:00Z" }, "collector_version": "1.0.0", "kernel_version": "5.15.0-generic", "compression": null, "host_id": "node-01.cluster.local", "container_ids": ["abc123", "def456"] } } ``` ## Validation Evidence can be validated against the JSON Schema: ```bash # Validate single file stella evidence validate evidence-chunk-001.ndjson # Validate and show statistics stella evidence validate --stats evidence-chunk-001.ndjson ``` ## Migration from v0 Schemas If using earlier per-language schemas, migrate to v1 unified schema: 1. Update field names to snake_case 2. Wrap type-specific fields in `event` object 3. Add `src` field with probe identifier 4. Ensure `ts_ns` uses nanoseconds since boot Example migration: ```json // v0 (old) {"timestamp": 1234567890, "type": "file", "path": "/etc/config"} // v1 (new) {"ts_ns": 1234567890000000000, "src": "tracepoint:syscalls:sys_enter_openat", "pid": 1234, "cgroup_id": 5678, "event": {"type": "file_access", "path": "/etc/config", "flags": 0, "mode": 0, "access": "read"}} ```