Evidence¶
Every compliance check produces evidence objects that can be audited independently of the Opencomplai platform.
What Opencomplai considers evidence¶
| Evidence type | Where it is stored | How it is referenced |
|---|---|---|
RiskResult JSON | Local: compliance-artifact.json. Service mode: evidence-vault CAS. | evidence_hashes[] in ScanStatusArtifact |
| Per-rule rationale | Embedded in RiskResult.rule_results[].rationale | rationale_hash (SHA-256) in ScanStatusArtifact |
| Ledger events | PostgreSQL + append-only log in evidence-vault | event_id UUIDs |
Content-addressed storage (CAS)¶
In service-backed mode (Docker Compose stack), evidence objects are stored in the evidence-vault service using a content-addressed model: each object's SHA-256 hash is its storage key. This means evidence objects are immutable — the same hash always refers to the same content.
The hash-chained ledger¶
The evidence-vault service maintains an append-only hash-chained event ledger. Each LedgerEvent records:
event_id— UUIDts— timestampevent_type— e.g.compliance_check_started,compliance_check_completedpayload_hash— SHA-256 of the event payloadprev_hash— SHA-256 of the previous event (creating the chain)
The ledger chain can be independently verified with tools/verify-ledger/verify_ledger.py.
Verifying the ledger¶
Expected output on a valid chain:
[INFO] Checking ledger integrity at: http://localhost:8080/v1/evidence/verify-chain
[PASS] Evidence ledger chain is valid — no tampering detected
In local (non-service) mode¶
When OPENCOMPLAI_API_URL is not set, compliance-artifact.json is the sole evidence output. In local mode evidence_hashes lists the SHA-256 digests (prefix sha256:) of the files the run read or wrote: the manifest, and with --scan or --sample-set the scan-report.json or eval-report.json sidecar, plus the canonical scan report_hash. Digests are taken over the file text with CRLF folded to LF, so one file hashes the same on Windows and Linux. Only hashes are stored, never file content. In service mode the list holds ledger event ids, as before.
Scanner signal categories and detectors¶
Code-corroboration scan evidence (opencomplai scan) is tagged with a SignalCategory and produced by a versioned detector_id, so evidence stays traceable to the exact detection logic that produced it:
| Signal category | Detector(s) | Notes |
|---|---|---|
AGENT_FRAMEWORK | DET_FRAMEWORK_AST_V1 | Opt-in (--framework-detectors). AST-level: fires on framework object construction + invocation (LangChain, CrewAI, AutoGen, LangGraph), not just a lexical import. See scan reference. |
Other signal categories (AI SDK usage, ML frameworks, vector/embedding stores, PII dataflow, biometric, scoring/profiling) are produced by the existing lexical detectors and are always-on (no opt-in flag).
Some signal categories are detection-only: agent_framework, mcp_server and pii_dataflow. A finding in one of them never produces a MET gap row on its own; it reads UNVERIFIED ("detected, no compliance verdict") until other evidence resolves the article.