JSON output

--json writes the report to stdout; --output-json <file> writes it to a file; --server POSTs it (see Shipping reports to a server). A JSON schema for validation lives at docs/json-schema.json.

Structure

{
  "timestamp": "2026-05-30T09:12:50",
  "hostname": "...",
  "version": "0.0.3",
  "config_file": "policy.json",
  "overall_status": "passed",
  "data_consistent": true,
  "file_check":       { "...": "..." },
  "process_check":    { "...": "..." },
  "port_check":       { "...": "..." },
  "filesystem_check": { "...": "..." },
  "memory": {
    "total_kb": 16316248, "available_kb": 9912344, "available_pct": 60,
    "slab_kb": 524288, "slab_unreclaimable_kb": 262144,
    "slab": { "allocator": "slub", "slabinfo_mode": "0400", "caches": 137,
              "reported_kb": 520100, "freelist_hardened": true,
              "freelist_random": true, "slub_debug": false,
              "top_caches": [ { "name": "dentry", "kb": 61440, "objs": 320000, "objsize": 192 } ] },
    "consistency": { "...": "..." }
  },
  "trace": {
    "backend": "ebpf", "window_ms": 1000, "total": 48211,
    "rate_per_sec": 48211, "dropped": 0, "truncated": false,
    "processes_observed": 37,
    "arguments": true,
    "processes": [ { "pid": 812, "name": "nginx", "total": 9120,
                     "rate_per_sec": 9120, "classes": ["network"],
                     "syscalls": [ { "name": "epoll_wait", "count": 3011 } ],
                     "details": [ { "call": "connect",
                                    "args": "addr=10.0.0.9:5432",
                                    "count": 12 } ] } ]
  },
  "device": { "os": "Debian GNU/Linux 12", "kernel": "6.1.0", "machine_id": "..." },
  "stun": { "reachable": true, "public": "[2001:db8::1]:54321", "rtt_ms": 21 },
  "risk": { "score": 0, "grade": "A" },
  "violations": [ ],
  "violation_count": 0,
  "summary": "All checks passed"
}
  • Metadata — timestamp (ISO 8601), hostname, version, config_file, and token (when --token is given — identifies the source to a collector; see Shipping reports to a server).

  • Per-domain results — *_check objects carry counts (scanned / matched / unexpected), a status (passed / failed / skipped / error) and a cross-source consistency block.

  • overall_status — the aggregate pass/fail, mirrored by the process exit code.

  • data_consistent — true when no cross-source mismatches were seen during collection (each domain reads twice and diffs).

  • memory — kernel memory posture: the /proc/meminfo totals, the SLAB/SLUB allocator state (flavor, /proc/slabinfo permissions, cache count, the largest caches, freelist hardening — null when no kernel config was readable) and the meminfo-vs-slabinfo consistency block. Any *_kb field the kernel did not report is omitted. See Threat detection.

  • trace — the syscall behavior sample, present when --trace ran. It gives the backend that operated (or none and a note), the window, the totals, and a profile for each process with its behavior classes and its loudest syscalls. With --trace-args the block contains "arguments": true, and each process also gets details: the decoded arguments (paths, peer addresses, protection bits) with a count. Delta ships a maximum of 20 processes, 8 syscalls for each process and 10 details for each process. truncated states that Delta reached a limit. See Syscall behavior tracing.

  • device — device identity (OS, kernel, machine-id), when determinable.

  • stun — NAT reachability beacon (reachable / public / rtt_ms), present when --stun is given. See Shipping reports to a server.

  • risk — aggregate posture: score (0–100, severity-weighted) and grade (A–F). See Threat detection.

Violations

Every policy failure appends a violation:

Field

Meaning

category

process / port / filesystem / file / package / vulnerability / network / threat / integrity / persistence / account / hardening / memory / syscalls

severity

critical / high / medium / low / info

description

human-readable explanation

resource

the affected item (e.g. port 8080, /etc/shadow, eth0)

expected / actual

the policy value vs. what was observed (optional)

attack

MITRE ATT&CK technique id (e.g. T1071), where applicable (optional)

Monitor stream

In monitor mode (Continuous monitoring) --json emits one compact NDJSON object per cycle instead of a full report:

{"cycle":2,"timestamp":"...","checks_passed":true,"baseline":false,
 "added":["port:4444/tcp/LISTEN"],"removed":[],
 "anomalies":["conn_established=412 (z=+5.3)"],
 "stun":{"reachable":true,"public":"[2001:db8::1]:54321","rtt_ms":21}}

checks_passed reflects the policy; added / removed are the temporal drift in feature-key form.