- Implemented comprehensive unit tests for VexCandidateEmitter to validate candidate emission logic based on various scenarios including absent and present APIs, confidence thresholds, and rate limiting. - Added integration tests for SmartDiff PostgreSQL repositories, covering snapshot storage and retrieval, candidate storage, and material risk change handling. - Ensured tests validate correct behavior for storing, retrieving, and querying snapshots and candidates, including edge cases and expected outcomes.
2.9 KiB
2.9 KiB
Evidence Locker
Status: Draft (2025-11-26) — DOCS-FORENSICS-53-001.
Purpose
Capture forensic artefacts (bundles, logs, attestations) in a WORM-friendly store with retention/legal-hold controls.
Storage model
- Object storage (preferred) with:
- Bucket per tenant (or tenant prefix) and immutable retention policy.
- Server-side encryption (KMS) and optional client-side DSSE envelopes.
- Versioning enabled; deletion disabled during legal hold.
- Index (PostgreSQL) for metadata:
artifactId,tenant,type(bundle/attestation/log),sha256,size,createdAt,retentionUntil,legalHold.provenance: source service, job/run ID, DSSE envelope hash, signer.immutability:worm=true|false,legalHold=true|false,expiresAt.
Ingest rules
- Only append; no overwrite. Use content-addressed paths:
tenant/<type>/<sha256>/<filename>. - Every artefact must include:
- SHA256 (and size)
- DSSE or Sigstore bundle for attestations
- Source metadata (service, run ID)
- Retention/hold directives
- Reject uploads lacking tenant, hash, or provenance.
Retention & legal hold
- Default retention per tenant (e.g., 180d); configurable via policy.
- Legal hold flag prevents deletion/expiry; requires dual-approval to clear.
- Expiry job runs daily; deletes only items past
retentionUntiland not on hold; produce audit log.
Access & audit
- RBAC scopes:
locker:read,locker:write,locker:hold. - All actions logged with tenant, actor, artefact ID, hash, and result.
- Provide
/locker/manifestendpoint to list artefacts by tenant/time/type with pagination.
Verification
locker verify <artifactId>:- Recompute SHA256
- Verify DSSE/Sigstore signature and signer against trust roots
- Return status + provenance summary
- Periodic background verification: sample N artefacts/day; emit
locker.verify.failedevents on mismatch.
Bundle format (minimum)
- Manifest (
manifest.json):artifactId,tenant,type,hashes,createdAt,retentionUntil,legalHoldprovenance(source, signer, dsseEnvelopeHash)pathswith bytes and hashes
- Data files under
data/(gzip/zstd optional) - Signature under
signatures/if provided
Migration from legacy storage
- Export legacy artefacts with hashes; import via Locker API with retention/hold fields.
- Maintain mapping of legacy IDs → new
artifactIdin index. - Keep legacy store read-only until verification completes.
Operational runbook (abridged)
- On ingest failure: log and return 400 with reason; do not partially store.
- On verification failure: mark artefact
suspect=true, emit event, and investigate signer and storage integrity. - For legal hold requests: require ticket/approval metadata; set
legalHold=trueand extend retention.
References
- DSSE: in-toto DSSE spec.
- Sigstore bundles:
docs/forensics/provenance-attestation.md(pending). - Export Center mirror imports and policy attestations feed artefacts here.