Overview
Every Corsair assessment produces an evidence chain — a JSONL file where each record is cryptographically linked to the previous one via SHA-256 hashing. This creates a tamper-proof audit trail that proves no evidence has been modified after collection.
How It Works
Each evidence record contains:
{
"sequenceNumber": 1,
"timestamp": "2026-02-06T10:30:00.000Z",
"phase": "EVIDENCE",
"type": "snapshot",
"data": { "...": "..." },
"previousHash": "0000000000000000000000000000000000000000000000000000000000000000",
"hash": "a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0"
}
Chain Mechanics
- The first record has
previousHashset to all zeros (genesis) - Each subsequent record includes the
hashof the previous record as itspreviousHash - The
hashis computed asSHA-256(canonical(record_without_hash))usingsorted-json-v1 - Breaking any record invalidates all subsequent hashes
Chain Digest
Each evidence chain also exposes a chain digest — a Merkle root computed over all record hashes.
This provides a single stable fingerprint for the entire chain and is embedded in CPOEs as
evidenceChain.chainDigest alongside chainType, algorithm, and canonicalization.
Evidence Receipts (Optional)
Evidence receipts are lightweight inclusion proofs. They prove a specific evidence record exists in the chain without disclosing the record itself.
corsair receipts generate --evidence ./evidence/assessment.jsonl --index 0 --output receipt.json
corsair receipts verify --file receipt.json --cpoe cpoe.jwt
Verification
Verify a chain programmatically:
import { verifyChain } from "corsair/evidence";
const records = readJsonl("./evidence/assessment.jsonl");
const result = verifyChain(records);
// { valid: true, recordCount: 12, brokenAt: null }
Or via the CLI (strict match on chainDigest):
corsair verify --file cpoe.jwt --evidence ./evidence/assessment.jsonl --require-evidence-chain
Input Binding (Optional)
To bind a CPOE back to the raw evidence JSON, compare the canonical JSON hash to
provenance.sourceDocument:
corsair verify --file cpoe.jwt --source-document ./evidence/assessment.json --require-input-binding
Evidence Phases
Evidence records are tagged with their pipeline phase:
| Phase | Evidence Type |
|---|---|
| EVIDENCE | Accepted tool output and evidence artifacts |
| SIGN | Provenance recording and signed attestation |
| CHART | Framework mapping results (optional enrichment) |
| QUARTER | Governance scores (optional enrichment) |
JSONL Format
Evidence uses JSONL (JSON Lines) — one JSON object per line. This format is:
- Appendable — New records are appended without rewriting the file
- Streamable — Process records one at a time without loading the full file
- Portable — Standard format supported by jq, Splunk, Datadog, etc.
Integration
Evidence chains integrate with:
- OSCAL output — Hash chain status included in Assessment Results metadata
- Marque documents — Chain digest and record count are part of the signed attestation
- GRC platforms — JSONL can be ingested by ServiceNow, Jira, Splunk via webhooks
Compaction
For repeated assessments, the evidence compaction engine can merge multiple chains while preserving integrity:
bun corsair.ts --compact ./evidence/assessment-*.jsonl --output ./evidence/compacted.jsonl
Compaction creates a new chain that references the original chains' digests, maintaining the full audit trail.
SCITT Transparency Log Integration
As part of the Parley protocol, evidence chains can be registered with an IETF SCITT (Supply Chain Integrity, Transparency, and Trust) transparency service. When a Marque is issued, the signed attestation and its evidence chain digest can be submitted as a SCITT statement, producing a COSE receipt that proves inclusion in the append-only log.
This provides two properties beyond the existing hash chain:
- Non-repudiation — The issuer cannot deny having issued the attestation at the recorded time
- Discoverability — Third parties can audit the transparency log to verify CPOE history
SCITT integration is production-ready with a Postgres-backed append-only transparency log. Statements are registered with SHA-256 Merkle tree hashing, and receipts are generated as COSE_Sign1 signed envelopes (RFC 9052) using Ed25519 — with hand-rolled CBOR encoding (RFC 8949) and zero external crypto dependencies. The API is available at /scitt/entries for registration and /scitt/entries/:id/receipt for receipt retrieval.
Proof-only mode registers only a hash commitment (no CPOE stored) while still returning a COSE receipt:
corsair log register --file cpoe.jwt --scitt https://log.example.com/scitt/entries --proof-only