Evidence Flow
This document describes how evidence bundles are created, signed, and verified.
Overviewโ
QCOS Evidence provides audit-grade proof of quantum/HPC operations with:
- Provenance - Git commit, config hash, compiler version
- Timeline - Submitted, compiled, executed, packaged timestamps
- Cost - Estimate vs final, chargeback tags
- Artifacts - Circuits, results, logs with hashes
- Signature - Cryptographic proof via QuantumLock
Evidence Bundle Lifecycleโ
stateDiagram-v2
[*] --> JobCreated: Job submitted
JobCreated --> JobRunning: Execution starts
JobRunning --> JobCompleted: Success
JobRunning --> JobFailed: Error
JobCompleted --> BundlePending: Request evidence
BundlePending --> BundlePackaging: Worker picks up
BundlePackaging --> BundleSigned: QuantumLock signs
BundleSigned --> BundleVerified: First verification
JobFailed --> [*]: No evidence generated
BundleVerified --> [*]: Available for download
Bundle Generation Flowโ
sequenceDiagram
autonumber
participant PF as Portal Frontend
participant PB as Portal Backend
participant EW as Evidence Worker
participant DB as PostgreSQL
participant OBJ as Object Storage
participant QL as QuantumLock
PF->>PB: GET /api/v2/jobs/{id}/evidence
PB->>DB: Check if bundle exists
alt Bundle exists
DB-->>PB: Return bundle metadata
PB-->>PF: Evidence summary + download URL
else Bundle not created
PB->>EW: enqueue(pack_evidence, job_id)
PB-->>PF: 202 Accepted - packaging in progress
Note over EW: Async processing
EW->>DB: Read job + artifacts metadata
EW->>EW: Build manifest
EW->>EW: Compute merkle root
EW->>OBJ: Upload bundle JSON
EW->>QL: POST /api/v1/quantum/crypto/sign
QL-->>EW: signature + key_id
EW->>DB: Store bundle metadata
end
Evidence Bundle Schema (v1.0)โ
{
"version": "1.0",
"bundle_id": "bundle_20250104_abc123",
"job_id": "job_xyz789",
"tenant_id": "tenant_abc",
"provenance": {
"git_commit": "a1b2c3d4e5f6",
"image_digest": "sha256:...",
"config_hash": "sha256:...",
"circuit_hash": "sha256:...",
"compiler_version": "qiskit-1.0.0"
},
"capabilities_snapshot": {
"backend_id": "ibm_washington",
"backend_version": "2.1.0",
"backend_provider": "IBM Quantum"
},
"timeline": {
"submitted_at": "2025-01-04T10:00:00Z",
"queued_at": "2025-01-04T10:00:01Z",
"started_at": "2025-01-04T10:00:05Z",
"completed_at": "2025-01-04T10:01:00Z",
"packaged_at": "2025-01-04T10:01:30Z"
},
"cost": {
"estimate_usd": 0.50,
"final_usd": 0.48,
"currency": "USD",
"chargeback_tags": ["project:alpha", "team:research"]
},
"execution": {
"shots_requested": 1000,
"shots_completed": 1000,
"success_rate": 0.987,
"status": "completed"
},
"artifacts": [
{
"name": "circuit.qasm",
"hash": "sha256:abc123...",
"hash_algorithm": "sha256",
"size_bytes": 2048,
"content_type": "application/qasm"
},
{
"name": "results.json",
"hash": "sha256:def456...",
"size_bytes": 8192,
"content_type": "application/json"
}
],
"results_summary": {
"result_hash": "sha256:..."
},
"merkle_root": "sha256:789xyz...",
"signature": {
"algorithm": "ML-DSA-65",
"key_id": "ql_key_prod_001",
"value": "base64...",
"signed_at": "2025-01-04T10:01:30Z"
}
}
Verification Flowโ
sequenceDiagram
autonumber
participant PF as Portal Frontend
participant PB as Portal Backend
participant QL as QuantumLock
participant DB as PostgreSQL
PF->>PB: POST /api/v2/evidence/verify
Note over PF,PB: {bundle_hash, signature, key_id}
PB->>QL: POST /api/v1/quantum/crypto/verify
Note over PB,QL: {message, signature, key_id, algorithm}
QL->>QL: Validate signature<br/>Check key not revoked
QL-->>PB: {valid: true/false, verified_at}
PB->>DB: Update bundle verification count
PB-->>PF: Verification result
API Endpointsโ
Get Job Evidenceโ
GET /api/v2/jobs/{job_id}/evidence
Authorization: Bearer <token>
Response (200):
{
"manifest": {
"version": "1.0",
"job_id": "job_xyz789",
"backend": {
"id": "softquantus_sim",
"provider": "SoftQuantus",
"qubits": 40,
"status": "online"
},
"execution": {
"submitted_at": "2025-01-04T10:00:00Z",
"completed_at": "2025-01-04T10:01:00Z",
"shots": 1000,
"status": "completed"
},
"artifacts": [...],
"merkle_root": "sha256:...",
"signature_algorithm": "ML-DSA-65"
},
"download_url": "https://storage.softquantus.com/bundles/...",
"verified": true,
"verification_details": {
"signature_valid": true,
"hash_matches": true,
"chain_verified": true
}
}
Verify Evidenceโ
POST /api/v2/evidence/verify
Authorization: Bearer <token>
Content-Type: application/json
{
"bundle_hash": "sha256:abc123...",
"signature": "base64...",
"key_id": "ql_key_prod_001"
}
Response (200):
{
"valid": true,
"verified_at": "2025-01-04T10:00:00Z",
"verification_method": "ML-DSA-65",
"trust_chain": "QuantumLock Root CA โ Evidence Signing Key",
"details": {
"bundle_hash_verified": true,
"signature_valid": true,
"key_not_revoked": true,
"timestamp_within_validity": true
}
}
List Artifactsโ
GET /api/v2/jobs/{job_id}/artifacts
Authorization: Bearer <token>
Response (200):
{
"job_id": "job_xyz789",
"artifacts": [
{
"name": "circuit.qasm",
"size_bytes": 2048,
"content_type": "application/qasm",
"download_url": "https://storage.softquantus.com/artifacts/..."
},
{
"name": "results.json",
"size_bytes": 8192,
"content_type": "application/json",
"download_url": "https://storage.softquantus.com/artifacts/..."
}
],
"total_size_bytes": 10240
}
Storage Architectureโ
flowchart LR
subgraph EvidencePlane[Evidence Plane]
API[API Endpoints]
Worker[Evidence Worker]
DB[(PostgreSQL)]
end
subgraph Storage[Object Storage]
Bundles[๐ฆ Bundles]
Artifacts[๐ Artifacts]
end
subgraph QuantumLock[QuantumLock]
Sign[Sign API]
Verify[Verify API]
end
API --> DB
Worker --> DB
Worker --> Bundles
Worker --> Artifacts
Worker --> Sign
API --> Verify
Bundles -.->|S3/MinIO/Azure| Storage
Artifacts -.->|S3/MinIO/Azure| Storage
Database Schemaโ
-- Jobs metadata
CREATE TABLE jobs (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
backend_id VARCHAR(100) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
shots_requested INTEGER,
submitted_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
cost_estimate NUMERIC(10, 4),
cost_final NUMERIC(10, 4),
-- ... provenance fields
);
-- Evidence bundles
CREATE TABLE evidence_bundles (
id UUID PRIMARY KEY,
job_id UUID REFERENCES jobs(id),
manifest JSONB NOT NULL,
manifest_hash VARCHAR(64) NOT NULL,
merkle_root VARCHAR(64),
signature_algorithm VARCHAR(50),
signature_key_id VARCHAR(100),
signature_value TEXT,
storage_uri TEXT NOT NULL,
status VARCHAR(20) DEFAULT 'pending'
);
-- Individual artifacts
CREATE TABLE artifacts (
id UUID PRIMARY KEY,
job_id UUID REFERENCES jobs(id),
name VARCHAR(255) NOT NULL,
hash_value VARCHAR(64) NOT NULL,
storage_uri TEXT NOT NULL
);
-- Audit log (append-only)
CREATE TABLE evidence_audit_log (
id BIGSERIAL PRIMARY KEY,
timestamp TIMESTAMPTZ DEFAULT NOW(),
tenant_id UUID,
action VARCHAR(50) NOT NULL,
resource_type VARCHAR(50),
resource_id UUID,
details JSONB
);
Retention Policiesโ
| Bundle Type | Retention | Immutable |
|---|---|---|
| Standard | 365 days | No |
| Compliance | 7 years | Yes (WORM) |
| Enterprise | Configurable | Configurable |
Expired bundles are archived or deleted based on tenant policy.