EvidenceLocker
Status: the
evidence-locker-webandevidence-locker-workerdeployables are RETIRED (2026-09-05). Nothing below describes a running host.Successor: the consolidated Evidence service —
../evidence/architecture.md.
EvidenceLocker is no longer a service. Its capability was consolidated into the Evidence family (ADR-039 D14) and its source moved with it:
- Hosts stopped and data moved in the
SPRINT_20260722_011EVD-9 cutover window (2026-09-05).evidence-webandevidence-workerserve the capsule, export, hold and evidence-thread surface fromstellaops_evidence. - Compose keys deleted 2026-09-05 (EVD-8 / EVD-10b), together with their blue/green siblings. The
StellaOps.EvidenceLocker.WebServiceproject has no csproj; the application, domain and infrastructure libraries live undersrc/Evidence/__Libraries/. - The object store was carried, not recreated.
compose_evidence-datakeeps its physical name and is mounted at the same in-container path,/data/evidence, by both consolidated roles. - The
evidencelocker.stella-ops.localalias was deleted with the compose key and is deliberately not claimed by the successor.
Where things went
| You were looking for | Read instead |
|---|---|
| architecture, database, HTTP surface, authorization | ../evidence/architecture.md |
| capsule sealing and RFC 3161 anchoring | ../evidence/architecture.md§5 |
| tenant isolation, residency and legal holds | ../evidence/architecture.md§6 |
| the evidence-pack and export formats | this directory — the formats moved unchanged |
Everything below this line is the pre-consolidation documentation. It remains accurate about bundle packaging, export formats, evidence-pack schemas and retention semantics, all of which moved unchanged. Treat any statement about hosts, containers, ports, compose keys or gateway routes as history.
Status: Implemented Source: src/EvidenceLocker/ Owner: Platform Team
Purpose
EvidenceLocker provides sealed, immutable storage for vulnerability-scan evidence and audit logs. It guarantees tamper-evident evidence chains for compliance and forensic analysis through content-addressable storage and cryptographic sealing (Merkle root + DSSE).
Audience: compliance and forensics operators who store, hold, and replay release evidence, and service authors integrating decision capsules, verdict attestations, or portable/air-gapped bundle export.
Components
Services:
StellaOps.EvidenceLocker.WebService- HTTP API for evidence submission and retrieval; also hosts the startup auto-migration, capsule retention-sweep, and legacy-PII audit hosted servicesStellaOps.EvidenceLocker.Worker- Background host. Verifies database connectivity and runs the shared hosted services (migration, retention sweep, legacy-PII audit). It does not perform sealing — sealing is synchronous on the write path.
Libraries:
StellaOps.EvidenceLocker- Composition-root project: HTTP contracts, minimal-API endpoint groups, Decision Capsule pipeline, repository contracts/implementationsStellaOps.EvidenceLocker.Core- Domain model, options, Merkle/signature abstractions, object-store and timeline interfacesStellaOps.EvidenceLocker.Infrastructure- Storage adapters (FileSystem / S3-compatible), persistence + embedded migrations, signers, hosted services__Libraries/StellaOps.EvidenceLocker.Exportand__Libraries/StellaOps.EvidenceLocker.Timestamping- portable/audit bundle export and RFC3161 (re)timestamping (standalone projects).__Libraries/StellaOps.EvidenceLocker.Import/EvidenceBundleImporter.csis a dormant source-only prototype, not a project or supported importer; it has no production composition or storage implementation.__Apps/StellaOps.EvidenceLocker.BackupCli- encrypted backup/restore CLI
API Surface
All routes require Authority OAuth2 bearer auth and a resolved tenant (RequireTenant()). The service FallbackPolicy requires evidence:read, so every route is at minimum read-gated. Scope policies map to: evidence:read → EvidenceRead, evidence:create → EvidenceCreate, evidence:hold → EvidenceHold, export.operator → ExportOperator, export.viewer → ExportViewer (constants in StellaOpsScopes; defined in Program.cs and the *Endpoints.cs files).
Evidence snapshots / gate artifacts (Api/EvidenceCoreEndpoints.cs, consolidated Evidence host):
EVD-10a retired
evidence-locker-web. Every route below is served by the consolidated Evidence host beneath/api/evidence/v1; the unprefixed predecessor forms are gone.POST /evidence(gate-artifact store) was withdrawn, not carried — it had no consumers. Its read side,GET /evidence/score, survives.
GET /api/evidence/v1/evidence/score?artifact_id=...— get evidence score by artifact id (evidence:read)POST /api/evidence/v1/evidence/snapshot— create an evidence snapshot/bundle (evidence:hold)GET /api/evidence/v1/evidence/{bundleId:guid}— get bundle metadata (evidence:read)GET /api/evidence/v1/evidence/{bundleId:guid}/chain— walk the supersede chain, oldest-first (evidence:read)GET /api/evidence/v1/evidence/{bundleId:guid}/download— download sealed bundle asapplication/gzip(evidence:read)GET /api/evidence/v1/evidence/{bundleId:guid}/portable— download portable/air-gapped bundle (evidence:read)GET /api/evidence/v1/evidence/by-release/{releaseId}/portable— resolve a release id to its chain-head bundle and download the portable pack (evidence:read)POST /api/evidence/v1/evidence/verify— verify bundle root hash (evidence:read)POST /api/evidence/v1/evidence/hold/{caseId}— create a legal hold (evidence:create)POST /api/evidence/v1/evidence/qa/assurance-cases/{caseId}/readback-import— QA-only readback/import proof (evidence:create)
Decision Capsules (Api/Capsules/CapsuleEndpoints.cs, group /api/v1/evidence/capsules):
POST /— create an unsealed capsule (evidence:create)POST /{capsuleId}/seal— seal via DSSE envelope (evidence:create)POST /{capsuleId}/verify— verify content hash + signature (evidence:read)POST /{capsuleId}/export— export asapplication/zip(evidence:read)POST /{capsuleId}/replay— reconstruct verdict from sealed capsule (evidence:read)POST /tlpt-packs— assemble + sign a DORA TLPT evidence pack capsule (evidence:create)
Bundle export jobs (Api/ExportEndpoints.cs, group /api/v1/bundles):
POST /{bundleId}/export— trigger async export job,202 Accepted(export.operator)GET /{bundleId}/export/{exportId}— poll export status (export.viewer)GET /{bundleId}/export/{exportId}/download— download completed export (export.viewer)
Verdict attestations (Api/VerdictEndpoints.cs, group /api/v1/verdicts):
POST /— store a verdict attestation (evidence:create)GET /{verdictId}— retrieve a verdict (evidence:read)POST /{verdictId}/verify— verify DSSE signature (currently fail-closed; trust roots unavailable) (evidence:read)GET /{verdictId}/envelope— download raw DSSE envelope JSON (evidence:read)GET /api/v1/runs/{runId}/verdicts— list verdicts for a policy run (evidence:read)
Evidence & Audit adapter (Api/EvidenceAuditEndpoints.cs, group /api/v1/evidence, all evidence:read):
GET /(evidence home summary),GET /packs,GET /packs/{id},GET /proofs/{subjectDigest},GET /receipts/cvss/{id}, andGET /audit(deprecated;Sunset 2027-10-19, successor/api/v1/audit/events?modules=evidencelockervia Timeline). Note:proofs,receipts/cvss, andauditcurrently return static in-process fixtures; packs are tenant-scoped viaIPackRepository.
Evidence Threads / Artifact Canonical Record (Api/EvidenceThreadEndpoints.cs, group /api/v1/evidence/thread, evidence:read):
GET /{canonicalId}andGET /?purl=...
EU regulatory artifact ledger (Api/RegulatoryArtifactLedgerEndpoints.cs, group /api/v1/regulatory/artifact-ledger, evidence:read):
GET /— tenant-scoped ledger query (regime/artifactType/reportingYear/cursor;requireMatch=trueis fail-closed)
Operational endpoints (anonymous): GET /healthz, GET /readyz, GET /health/ready (legacy), GET /buildinfo.json, and GET /openapi.
Configuration
Configuration binds to the EvidenceLocker section (EvidenceLockerOptions.SectionName); there is no etc/evidence-locker.yaml.sample shipped in this repo. Sealing is synchronous on the write path (no immediate-vs-batch policy toggle).
Key settings (see StellaOps.EvidenceLocker.Core/Configuration/EvidenceLockerOptions.cs):
EvidenceLocker:Database—ConnectionString(required) andApplyMigrationsAtStartup(defaulttrue)EvidenceLocker:ObjectStore—Kind(FileSystem=1 /AmazonS3=2),EnforceWriteOnce(WORM, defaulttrue), plusFileSystem.RootPathorAmazonS3.{BucketName,Region,ServiceKind,Endpoint,ForcePathStyle,Tls,Prefix,UseIntelligentTiering,ObjectLock}.ServiceKind=S3Compatiblerequires an explicit endpoint, addressing choice, and TLS verification choice; production external endpoints require verified HTTPS.EvidenceLocker:Signing—Enabled,Algorithm(default ES256),KeyId,PayloadType,UseCryptoRegistry(route signing throughICryptoProviderRegistry),AllowEphemeralKeyMaterial,AllowUnsignedCapsules, optionalKeyMaterial(Ed25519/EC) andTimestampingEvidenceLocker:Crypto—HashAlgorithm(default SHA256; also SHA384/SHA512/GOST3411-2012-256/512) andPreferredProviderEvidenceLocker:Quotas— material count/size and metadata limitsEvidenceLocker:Timeline— optional Timeline anchoring (Enabled,Endpoint, auth)EvidenceLocker:RetentionSweep— background sweep of expired non-RoI capsules (Enableddefaultfalse,DryRun,DefaultRetentionDaysdefault 3650,InitialDelay,Interval)EvidenceLocker:Incident— incident-mode retention extensionEvidenceLocker:DataResidency—DefaultRegion,AllowedRegionsEvidenceLocker:Portable— portable bundle artifact/file names
Dependencies
- PostgreSQL (schemas
evidence_lockerfor data +evidence_locker_appfor the RLSrequire_current_tenant()tenant-isolation function; forward-only embedded SQL migrations applied on startup byEvidenceLockerMigrationRunner/EvidenceLockerMigrationHostedService, tracked inevidence_locker.evidence_schema_version) - Object store: filesystem (
ObjectStore:Kind=FileSystem) or the S3 driver (ObjectStore:Kind=AmazonS3). RustFS/MinIO support is conditional on the validatedAmazonS3:ServiceKind=S3Compatibleendpoint/path-style/TLS contract documented inarchitecture.md§5.1; it is not an unqualified compatibility claim for every server version or Object Lock implementation. - StellaOps Cryptography (
ICryptoProviderRegistry, BouncyCastle Ed25519) for in-process bundle/capsule signing — there is no separate Signer service dependency - Authority (OAuth2 resource-server auth;
evidence:read/evidence:create/evidence:holdscopes) - Optional: RFC3161 timestamp authority, Timeline/TimelineIndexer, audit emission
- ExportCenter / Export Center scopes for bundle export (
export.operator/export.viewer)
Related Documentation
- Architecture:
architecture.md - API reference:
api-reference.md - Evidence-bundle contract:
evidence-bundle-v1.md - Encrypted backup & restore:
encrypted-backup-restore.md - Promotion evidence contract:
promotion-evidence-contract.md - DORA RoI retention policy:
dora-roi-retention.md - Portable audit pack — contract:
portable-audit-pack-contract.md; manifest schema:schemas/portable-audit-pack-manifest.v1.schema.json; compatibility:portable-audit-pack-compatibility.md; determinism:portable-audit-pack-determinism.md; Rekor offline:portable-audit-pack-rekor-offline.md; CLI runbook:portable-audit-pack-cli-runbook.md; Parquet profile:portable-audit-pack-parquet-profile.md; verification matrix:portable-audit-pack-test-matrix.md - Export Center:
../export-center/ - Attestor:
../attestor/ - High-Level Architecture:
../../ARCHITECTURE_OVERVIEW.md
Current Status
Implemented with WebService and Worker components. Supports sealed evidence storage with cryptographic verification (Merkle root + DSSE), decision-capsule create/seal/verify/export/replay, verdict attestations, an EU regulatory artifact ledger, evidence-thread (Artifact Canonical Record) reads, and portable/air-gapped bundle download. Bundle export jobs and capsule export integrate with the Export Center scopes (export.operator / export.viewer). The Decision Capsule pipeline enforces PII rejection (CapsulePiiGuard) and data residency on write/read. Verdict-attestation DSSE verification is currently fail-closed (trust roots not yet wired). The /api/v1/evidence/audit slice is deprecated in favour of Timeline’s unified audit store.
