# Witness Schema v1 Contract > **Version**: `stellaops.witness.v1` > **Status**: Draft > **Sprint**: `SPRINT_3700_0001_0001_witness_foundation` --- ## Overview A **witness** is a cryptographically-signed proof of a reachability path from an entrypoint to a vulnerable sink. Witnesses provide: 1. **Auditability** - Proof that a path was found at scan time 2. **Offline verification** - Verify claims without re-running analysis 3. **Provenance** - Links to the source graph and analysis context 4. **Transparency** - Can be published to transparency logs --- ## Schema Definition ### PathWitness ```json { "$schema": "https://stellaops.org/schemas/witness-v1.json", "schema_version": "stellaops.witness.v1", "witness_id": "uuid", "witness_hash": "blake3:abcd1234...", "witness_type": "reachability_path", "created_at": "2025-12-18T12:00:00Z", "provenance": { "graph_hash": "blake3:efgh5678...", "scan_id": "uuid", "run_id": "uuid", "analyzer_version": "1.0.0", "analysis_timestamp": "2025-12-18T11:59:00Z" }, "path": { "entrypoint": { "fqn": "com.example.MyController.handleRequest", "kind": "http_handler", "location": { "file": "src/main/java/com/example/MyController.java", "line": 42 } }, "sink": { "fqn": "org.apache.log4j.Logger.log", "cve": "CVE-2021-44228", "package": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1" }, "steps": [ { "index": 0, "fqn": "com.example.MyController.handleRequest", "call_site": "MyController.java:45", "edge_type": "call" }, { "index": 1, "fqn": "com.example.LoggingService.logMessage", "call_site": "LoggingService.java:23", "edge_type": "call" }, { "index": 2, "fqn": "org.apache.log4j.Logger.log", "call_site": "Logger.java:156", "edge_type": "sink" } ], "hop_count": 3 }, "gates": [ { "type": "auth_required", "location": "MyController.java:40", "description": "Requires authenticated user" } ], "evidence": { "graph_fragment_hash": "blake3:ijkl9012...", "path_hash": "blake3:mnop3456..." } } ``` --- ## Field Definitions ### Root Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `schema_version` | string | Yes | Must be `stellaops.witness.v1` | | `witness_id` | UUID | Yes | Unique identifier | | `witness_hash` | string | Yes | BLAKE3 hash of canonical JSON | | `witness_type` | enum | Yes | `reachability_path`, `gate_proof` | | `created_at` | ISO8601 | Yes | Witness creation timestamp (UTC) | ### Provenance | Field | Type | Required | Description | |-------|------|----------|-------------| | `graph_hash` | string | Yes | BLAKE3 hash of source rich graph | | `scan_id` | UUID | No | Scan that produced the graph | | `run_id` | UUID | No | Analysis run identifier | | `analyzer_version` | string | Yes | Analyzer version | | `analysis_timestamp` | ISO8601 | Yes | When analysis was performed | ### Path | Field | Type | Required | Description | |-------|------|----------|-------------| | `entrypoint` | object | Yes | Entry point of the path | | `sink` | object | Yes | Vulnerable sink at end of path | | `steps` | array | Yes | Ordered list of path steps | | `hop_count` | integer | Yes | Number of edges in path | ### Path Step | Field | Type | Required | Description | |-------|------|----------|-------------| | `index` | integer | Yes | Position in path (0-indexed) | | `fqn` | string | Yes | Fully qualified name of node | | `call_site` | string | No | Source location of call | | `edge_type` | enum | Yes | `call`, `virtual`, `static`, `sink` | ### Gates Optional array of protective controls encountered along the path. | Field | Type | Required | Description | |-------|------|----------|-------------| | `type` | enum | Yes | `auth_required`, `feature_flag`, `admin_only`, `non_default_config` | | `location` | string | No | Source location of gate | | `description` | string | No | Human-readable description | --- ## Hash Computation The `witness_hash` is computed as: 1. Serialize the witness to canonical JSON (sorted keys, no whitespace) 2. Exclude `witness_id`, `witness_hash`, and `created_at` fields 3. Compute BLAKE3 hash of the canonical bytes 4. Prefix with `blake3:` and hex-encode ```csharp var canonical = JsonSerializer.Serialize(witness, canonicalOptions); var hash = Blake3.Hasher.Hash(Encoding.UTF8.GetBytes(canonical)); var witnessHash = $"blake3:{Convert.ToHexString(hash.AsSpan()).ToLowerInvariant()}"; ``` --- ## DSSE Signing Witnesses are signed using [DSSE (Dead Simple Signing Envelope)](https://github.com/secure-systems-lab/dsse): ```json { "payloadType": "application/vnd.stellaops.witness.v1+json", "payload": "", "signatures": [ { "keyid": "sha256:abcd1234...", "sig": "" } ] } ``` ### Verification 1. Decode the payload from base64url 2. Parse as PathWitness JSON 3. Recompute witness_hash and compare 4. Verify signature against known public key 5. Optionally check transparency log for inclusion --- ## Storage Witnesses are stored in `scanner.witnesses` table: | Column | Type | Description | |--------|------|-------------| | `witness_id` | UUID | Primary key | | `witness_hash` | TEXT | BLAKE3 hash (unique) | | `payload_json` | JSONB | Full witness JSON | | `dsse_envelope` | JSONB | Signed envelope (nullable) | | `graph_hash` | TEXT | Source graph reference | | `sink_cve` | TEXT | CVE for quick lookup | --- ## API Endpoints | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/v1/witnesses/{id}` | Get witness by ID | | `GET` | `/api/v1/witnesses?cve={cve}` | List witnesses for CVE | | `GET` | `/api/v1/witnesses?scan={scanId}` | List witnesses for scan | | `POST` | `/api/v1/witnesses/{id}/verify` | Verify witness signature | --- ## Related Documents - [Rich Graph Contract](richgraph-v1.md) - [DSSE Specification](https://github.com/secure-systems-lab/dsse) - [BLAKE3 Hash Function](https://github.com/BLAKE3-team/BLAKE3)