feat: add verifiable audit evidence bundles
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# Audit evidence bundles
|
||||
|
||||
Audit evidence bundles are bounded, portable JSON artifacts for independent
|
||||
review. They are not database backups. A bundle contains selected audit facts,
|
||||
trace context, policy and source provenance, external evidence references, and
|
||||
redaction declarations. It never embeds referenced files, raw messages, full
|
||||
recipient lists, credentials, tokens, or arbitrary feature payloads.
|
||||
|
||||
## Export lifecycle and permissions
|
||||
|
||||
Create an export with `POST /api/v1/admin/audit/evidence-bundles`. A tenant
|
||||
export requires `audit:evidence:export` and is constrained to the principal's
|
||||
active tenant. `system` and `all` scopes require
|
||||
`audit:system_evidence:export`. Selection is limited to 500 audit records and
|
||||
200 external references. An over-broad selection is rejected instead of being
|
||||
silently truncated.
|
||||
|
||||
The response records the `pending`, `ready`, or `failed` lifecycle state and a
|
||||
canonical bundle SHA-256. Metadata and content are available at:
|
||||
|
||||
- `GET /api/v1/admin/audit/evidence-bundles/{id}`
|
||||
- `GET /api/v1/admin/audit/evidence-bundles/{id}/download`
|
||||
|
||||
The Audit administration page offers **Export page evidence** to create an
|
||||
unsigned bundle for the currently displayed records. Use the API when a review
|
||||
needs a broader filtered selection, explicit module references, or signing.
|
||||
|
||||
Generation and every download produce separate audit records. Download access
|
||||
is re-authorized against the original scope so a tenant switch cannot expose a
|
||||
bundle from another tenant. Audit also checks the stored bundle against its
|
||||
persisted canonical hash before each download and fails the lifecycle record if
|
||||
storage integrity no longer matches.
|
||||
|
||||
## Module evidence references
|
||||
|
||||
Feature modules keep their evidence and storage ownership. They may record a
|
||||
serialized `govoplan_core.core.institutional.EvidenceReference` in bounded
|
||||
audit details or supply an external reference in the export request. The Audit
|
||||
module stores only its id, kind, owner module, locator, required flag, and
|
||||
optional content SHA-256. This lets modules participate without importing Audit
|
||||
internals or handing Audit file contents.
|
||||
|
||||
External references should include a SHA-256 whenever the referenced artifact
|
||||
can be canonicalized. A missing hash is reported as unverifiable. A required
|
||||
artifact that is not supplied during offline review is reported as missing,
|
||||
and supplied bytes that do not match their hash are reported as tampered.
|
||||
|
||||
## Signatures
|
||||
|
||||
Canonical record and reference hashes are always emitted. Trusted signatures
|
||||
are optional and use Ed25519. To enable signed exports, configure both:
|
||||
|
||||
- `GOVOPLAN_AUDIT_EVIDENCE_SIGNING_KEY_ID`
|
||||
- `GOVOPLAN_AUDIT_EVIDENCE_SIGNING_PRIVATE_KEY` (path to a PEM Ed25519 key)
|
||||
|
||||
The request must set `sign` to `true`; otherwise the bundle remains unsigned.
|
||||
Keep private keys outside the application database and distribute raw,
|
||||
base64-encoded Ed25519 public keys to independent reviewers through a separate
|
||||
trusted channel.
|
||||
|
||||
## Offline verification
|
||||
|
||||
The installed `govoplan-audit-verify` command requires no source database:
|
||||
|
||||
```text
|
||||
govoplan-audit-verify bundle.json --pretty
|
||||
govoplan-audit-verify bundle.json \
|
||||
--trusted-key institution-2026=BASE64_PUBLIC_KEY \
|
||||
--external decision-42=/review/decision-42.json
|
||||
```
|
||||
|
||||
Output is deterministic and returns one of these states:
|
||||
|
||||
- `valid`: schema, canonical hashes, completeness, redaction declarations,
|
||||
supplied external evidence, and any trusted signatures are valid.
|
||||
- `incomplete`: a manifest item or required external artifact is missing.
|
||||
- `unverifiable`: a reference lacks a checksum or a signature key is untrusted.
|
||||
- `tampered`: a canonical item, manifest, external artifact, or trusted
|
||||
signature does not match.
|
||||
- `invalid`: the supported schema or redaction contract is malformed.
|
||||
- `unsupported`: the schema or version is not supported by this verifier.
|
||||
|
||||
An unsigned bundle can still be `valid`: the verifier establishes internal
|
||||
hash consistency, while provenance trust must then be established by the
|
||||
review process.
|
||||
Reference in New Issue
Block a user