ExecutionManifest
Pydantic model representing the full sealed manifest. The Go API serializes these fields in PascalCase; the SDK exposes them in snake_case via Pydantic field aliases, both naming styles work.
Import
from verdifax import ExecutionManifest
Fields
| Field | Type | Stage | Notes |
|---|---|---|---|
envelope_id | str | 1 (DOG) | |
envelope_hash | str | 1 (DOG) | 64-char hex |
sequence_id | str | 2 (DTL) | |
transport_hash | str | 2 (DTL) | 64-char hex |
epa_hash | str | 3 (DKEC) | 64-char hex |
efa_hash | str | 3 (DKEC) | 64-char hex |
execution_ids | List[str] | 3 (DKEC) | Six entries, DSE, TOK, DSC, NREP, AIVP, DCAE |
aer_hash | str | 4 (AER) | 64-char hex |
transcript_hash | str | 5 (ZKSP, ZK transcript) | 64-char hex |
hardware_attestation_hash | str | 5 (ZKSP, legacy) | 64-char hex. Legacy placeholder, never computed over a quote; the run's hardware measurement is the bundle's execution_record.hardware_attestation_hash. See scaffold-gaps |
leakage_bundle_hash | str | 5 (ZKSP, leakage bound) | 64-char hex |
formal_verifier_status | str | 5 (ZKSP, formal verifier) | Carries the formal-verifier success token. Scaffold today, see scaffold-gaps |
zksp_binding_hash | str | 6 (Sealing) | 64-char hex |
migration_token_hash | str | 6 (Sealing) | 64-char hex |
replay_fingerprint | str | 6 (Sealing) | 64-char hex |
pote_proof_hash | str | 7 (Ledger) | 64-char hex |
log_entry_id | str | 7 (Ledger) | Rekor-style id |
registry_artifact_count | int | 8 (Registry) | 20 when PEPG admitted the run (its policy_hash and evaluation_hash are registered too); 18 without PEPG |
final_vfa_hash | str | 9 (DLA) | 64-char hex |
independent_verified | bool | 9 (DLA) | Must be True for a sealed manifest |
manifest_hash | str | (seal) | The headline 64-char hex |
Methods
manifest.kernel_executions() -> dict[str, str]
# → {"DSE": "...", "TOK": "...", "DSC": "...", "NREP": "...", "AIVP": "...", "DCAE": "..."}
manifest.stages() -> list[StageResult]
# → 9-element list, one per pipeline stage
list(manifest) # iter, same as .stages()
Validation
Constructing an ExecutionManifest via ExecutionManifest.model_validate(...) enforces:
execution_idshas exactly 6 entriesregistry_artifact_countis non-negative- All required fields are present
Invalid responses raise Pydantic's ValidationError.
Manifest structure for non-OK runs
For deny and halt runs (pepg_deny, ccv_halt, macc_halt, aivp_t4_halt), the persisted JSON wraps the partial manifest under a manifest key alongside exactly one sealed receipt and, once the receipt is anchored (receipt anchoring started at run 241), its receipt_anchor. A pepg_deny record, for example:
{
"manifest": {
"EnvelopeID": "env-...",
"PepgOutcome": "deny",
...
},
"deny_receipt": { ... },
"receipt_anchor": { ... }
}
The other kinds use ccv_halt_receipt, macc_halt_receipt or aivp_t4_halt_receipt in place of deny_receipt. An attestation_gap record has no manifest, only attestation_gap_receipt and receipt_anchor.
Deny and halt runs have no audit bundle, so GET /runs/{id}/artifacts returns 404 for them. Fetch the receipt from its own endpoint instead (see Sealed artifacts), using the outcome_kind field on the run summary to pick it. In the SDK, a deny or halt raises a generic StageError; branch on its .stage and read the receipt from .response_body.
