# Verification Event Contract (attestations → ledger_attestations) Status: Draft (2025-11-21) Owners: Provenance Guild · Findings Ledger Guild Purpose: unblock LEDGER-OBS-54-001 by defining the ingestion event emitted by the verifier so we can populate `ledger_attestations`. ``` event_type: verification.attestation.completed payload: tenant_id: string (required) attestation_id: uuid (required) artifact_id: string (required; OCI digest or SBOM id) finding_id: string (optional) verification_status: string enum [verified, failed, unknown] (required) verification_time: string (ISO-8601 UTC, required) dsse_digest: string (sha256, lowercase, required) rekor_entry_id: string (optional) evidence_bundle_ref: string (optional) merkle_leaf_hash: string (sha256, required) root_hash: string (sha256, required) cycle_hash: string (required) projection_version: string (required) ``` Ordering/monotonicity: - Events are emitted with a ledger `sequence_no`. Ingestion must ignore any verification event with `sequence_no` less than the stored `risk_event_sequence` for the same `(tenant_id, attestation_id)`. Determinism for ingestion: - Sort by `(sequence_no ASC, attestation_id ASC)` before upsert. - Upsert target: `ledger_attestations` (see `004_ledger_attestations.sql`). Open question: - Should `verification_status` include `expired`/`revoked`? Need decision before marking schema final. Next step: - Once the verifier confirms this payload, wire ingestion job to project into `ledger_attestations` and flip LEDGER-OBS-54-001 to DOING.