From b6aab4a58eafa0bd8248cdad954771586f48447b Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:52:25 -0400 Subject: [PATCH 1/4] schemas: add DiagnosticProbeResult contract --- schemas/DiagnosticProbeResult.json | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 schemas/DiagnosticProbeResult.json diff --git a/schemas/DiagnosticProbeResult.json b/schemas/DiagnosticProbeResult.json new file mode 100644 index 0000000..88a20e7 --- /dev/null +++ b/schemas/DiagnosticProbeResult.json @@ -0,0 +1,100 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/DiagnosticProbeResult.json", + "title": "DiagnosticProbeResult", + "description": "One command/probe execution record within a DiagnosticBundle. Mirrors sysdiagnose-style ledgers (exit, elapsed, timeout, max RSS) and binds the row to any captured stdout/stderr artifacts.", + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "command", + "exit", + "elapsedSeconds", + "timeoutSeconds", + "maxRssKb", + "startedAt", + "endedAt", + "risk" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Stable probe identifier within the bundle (e.g. uptime, rpm_ostree_status)." + }, + "group": { + "type": [ + "string", + "null" + ], + "description": "Optional concurrent group identifier (sysdiagnose-style)." + }, + "command": { + "type": "string", + "minLength": 1, + "description": "The exact shell command executed (after any templating)." + }, + "exit": { + "type": "integer", + "description": "Process exit code (or timeout/kill code if the runner preserves it)." + }, + "elapsedSeconds": { + "type": "number", + "minimum": 0, + "description": "Wall-clock elapsed seconds for the probe run." + }, + "timeoutSeconds": { + "type": "number", + "minimum": 0, + "description": "Runner-enforced timeout seconds for this probe." + }, + "maxRssKb": { + "type": "integer", + "minimum": 0, + "description": "Maximum resident set size in KB measured for the probe process." + }, + "startedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 start timestamp." + }, + "endedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "ISO 8601 end timestamp (null if unknown)." + }, + "risk": { + "type": "string", + "enum": [ + "safe", + "sensitive", + "high-risk" + ], + "description": "Risk classification for the probe output. High-risk probes are opt-in by policy." + }, + "stdoutPath": { + "type": [ + "string", + "null" + ], + "description": "Relative path (inside the bundle) to captured stdout, if any." + }, + "stderrPath": { + "type": [ + "string", + "null" + ], + "description": "Relative path (inside the bundle) to captured stderr, if any." + }, + "metaPath": { + "type": [ + "string", + "null" + ], + "description": "Relative path (inside the bundle) to runner metadata (e.g. GNU time output), if any." + } + } +} From af319b54cbbe4a400194d1324db9c62ba272a3d8 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:58:54 -0400 Subject: [PATCH 2/4] schemas: add DiagnosticBundle contract --- schemas/DiagnosticBundle.json | 220 ++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 schemas/DiagnosticBundle.json diff --git a/schemas/DiagnosticBundle.json b/schemas/DiagnosticBundle.json new file mode 100644 index 0000000..6c0604b --- /dev/null +++ b/schemas/DiagnosticBundle.json @@ -0,0 +1,220 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/DiagnosticBundle.json", + "title": "DiagnosticBundle", + "description": "A sysdiagnose-style diagnostic collection bundle for a host. Captures immutable identity (where available), executed probes, risk policy flags, and artifact hashes so the bundle can be verified and ingested as evidence.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "profile", + "capturedAt", + "host", + "bundle", + "probes", + "artifactHashes" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:diag-bundle:", + "description": "Stable URN identifier. Pattern: urn:srcos:diag-bundle:" + }, + "type": { + "const": "DiagnosticBundle", + "description": "Discriminator constant — always \"DiagnosticBundle\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "profile": { + "type": "string", + "minLength": 1, + "description": "Collector profile identifier (e.g. silverblue-baseline, boot-trust, security-persistence)." + }, + "capturedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 date-time when capture began (or when the bundle was finalized)." + }, + "host": { + "type": "object", + "additionalProperties": false, + "required": [ + "hostname" + ], + "properties": { + "hostname": { + "type": "string", + "description": "System hostname at capture time." + }, + "machineId": { + "type": [ + "string", + "null" + ], + "description": "Optional machine-id (/etc/machine-id) if captured and permitted." + }, + "bootId": { + "type": [ + "string", + "null" + ], + "description": "Optional system boot-id if captured." + }, + "osRelease": { + "type": [ + "string", + "null" + ], + "description": "Optional /etc/os-release content fingerprint or identifier." + }, + "kernel": { + "type": [ + "string", + "null" + ], + "description": "Optional kernel release string (e.g. uname -r)." + }, + "arch": { + "type": [ + "string", + "null" + ], + "description": "Optional architecture (e.g. x86_64, aarch64)." + }, + "immutable": { + "type": [ + "boolean", + "null" + ], + "description": "Optional: whether the host is in an immutable deployment mode (e.g. rpm-ostree)." + }, + "ostree": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "bootedDeployment": { + "type": [ + "string", + "null" + ], + "description": "Optional booted deployment identifier." + }, + "origin": { + "type": [ + "string", + "null" + ], + "description": "Optional origin ref (rpm-ostree)." + }, + "commit": { + "type": [ + "string", + "null" + ], + "description": "Optional OSTree commit hash." + } + }, + "description": "Optional immutable deployment identity fields." + } + }, + "description": "Host identity snapshot.", + "default": {} + }, + "policy": { + "type": "object", + "additionalProperties": false, + "properties": { + "enablePerf": { + "type": "boolean", + "default": false, + "description": "Whether perf sampling collectors were enabled." + }, + "enablePcap": { + "type": "boolean", + "default": false, + "description": "Whether packet capture collectors were enabled." + }, + "deepUserJournal": { + "type": "boolean", + "default": false, + "description": "Whether deeper user-session journald capture was enabled." + } + }, + "description": "Policy flags recorded at capture time (risk-gated collectors)." + }, + "bundle": { + "type": "object", + "additionalProperties": false, + "required": [ + "format", + "rootRef" + ], + "properties": { + "format": { + "enum": [ + "directory", + "tar.gz", + "zip" + ], + "description": "Bundle packaging format." + }, + "rootRef": { + "$ref": "DataRef.json", + "description": "DataRef pointing to the bundle root (directory or archive file)." + }, + "manifestRef": { + "$ref": "DataRef.json", + "description": "Optional DataRef to machine-readable manifest.json within the bundle." + }, + "ledgerRef": { + "$ref": "DataRef.json", + "description": "Optional DataRef to the sysdiagnose-style ledger (manifest.tsv)." + }, + "policyRef": { + "$ref": "DataRef.json", + "description": "Optional DataRef to policy.json emitted by the collector." + } + }, + "description": "Pointers to the bundle and its primary index artifacts." + }, + "probes": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "DiagnosticProbeResult.json" + }, + "description": "Per-probe execution records." + }, + "artifactHashes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "sha256: prefixed hashes for bundle artifacts (including manifest, policy, and any attached files)." + }, + "runRef": { + "type": [ + "string", + "null" + ], + "pattern": "^urn:srcos:run:", + "description": "Optional RunRecord URN if this capture was recorded as a typed workload run." + }, + "telemetryRef": { + "type": [ + "string", + "null" + ], + "pattern": "^urn:srcos:telemetry:", + "description": "Optional TelemetryEvent URN for the bundle creation event." + } + } +} From 10e8684e45a696ad2c0db919cb87ce227e0fb6d1 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Thu, 16 Apr 2026 18:50:44 -0400 Subject: [PATCH 3/4] examples: add DiagnosticProbeResult example (sub-schema) --- examples/diagnosticproberesult.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 examples/diagnosticproberesult.json diff --git a/examples/diagnosticproberesult.json b/examples/diagnosticproberesult.json new file mode 100644 index 0000000..9dcc6ae --- /dev/null +++ b/examples/diagnosticproberesult.json @@ -0,0 +1,15 @@ +{ + "name": "uptime", + "group": "proc_mem", + "command": "uptime", + "exit": 0, + "elapsedSeconds": 0.012, + "timeoutSeconds": 2, + "maxRssKb": 2048, + "startedAt": "2026-04-15T14:00:00Z", + "endedAt": "2026-04-15T14:00:00Z", + "risk": "safe", + "stdoutPath": "cmd/uptime.out", + "stderrPath": "cmd/uptime.err", + "metaPath": "cmd/uptime.meta" +} From a2b3b56bd162fb68e9e63b17ca77fb5ef635c641 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:05:17 -0400 Subject: [PATCH 4/4] examples: add DiagnosticBundle example --- examples/diagnosticbundle.json | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 examples/diagnosticbundle.json diff --git a/examples/diagnosticbundle.json b/examples/diagnosticbundle.json new file mode 100644 index 0000000..f0be4d0 --- /dev/null +++ b/examples/diagnosticbundle.json @@ -0,0 +1,83 @@ +{ + "id": "urn:srcos:diag-bundle:example_001", + "type": "DiagnosticBundle", + "specVersion": "2.0.0", + "profile": "silverblue-baseline", + "capturedAt": "2026-04-15T14:00:00Z", + "host": { + "hostname": "silverblue-host", + "machineId": "c1a2b3c4d5e6f7g8h9i0", + "bootId": "b3b2b1b0-a0a1-a2a3-a4a5-a6a7a8a9aaab", + "osRelease": "Fedora Linux", + "kernel": "6.8.0-0", + "arch": "x86_64", + "immutable": true, + "ostree": { + "bootedDeployment": "fedora:fedora/41/x86_64/silverblue", + "origin": "fedora:fedora/41/x86_64/silverblue", + "commit": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + } + }, + "policy": { + "enablePerf": false, + "enablePcap": false, + "deepUserJournal": false + }, + "bundle": { + "format": "directory", + "rootRef": { + "refType": "file", + "id": "/var/tmp/IN_PROGRESS_sysdiagnose_2026.04.15_14-00-00_silverblue/" + }, + "manifestRef": { + "refType": "file", + "id": "/var/tmp/IN_PROGRESS_sysdiagnose_2026.04.15_14-00-00_silverblue/manifest.json" + }, + "ledgerRef": { + "refType": "file", + "id": "/var/tmp/IN_PROGRESS_sysdiagnose_2026.04.15_14-00-00_silverblue/manifest.tsv" + }, + "policyRef": { + "refType": "file", + "id": "/var/tmp/IN_PROGRESS_sysdiagnose_2026.04.15_14-00-00_silverblue/policy.json" + } + }, + "probes": [ + { + "name": "uptime", + "group": "proc_mem", + "command": "uptime", + "exit": 0, + "elapsedSeconds": 0.012, + "timeoutSeconds": 2, + "maxRssKb": 2048, + "startedAt": "2026-04-15T14:00:00Z", + "endedAt": "2026-04-15T14:00:00Z", + "risk": "safe", + "stdoutPath": "cmd/uptime.out", + "stderrPath": "cmd/uptime.err", + "metaPath": "cmd/uptime.meta" + }, + { + "name": "rpmostree_status", + "group": "silverblue", + "command": "rpm-ostree status", + "exit": 0, + "elapsedSeconds": 0.091, + "timeoutSeconds": 10, + "maxRssKb": 8192, + "startedAt": "2026-04-15T14:00:01Z", + "endedAt": "2026-04-15T14:00:01Z", + "risk": "safe", + "stdoutPath": "cmd/rpmostree_status.out", + "stderrPath": "cmd/rpmostree_status.err", + "metaPath": "cmd/rpmostree_status.meta" + } + ], + "artifactHashes": [ + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + ], + "runRef": "urn:srcos:run:diag_example_001", + "telemetryRef": "urn:srcos:telemetry:diag_bundle_created_001" +}