Exporting a locker
Getting a portable, verifiable copy of a run's evidence.
An export packages one sealed run as a zip that can be checked without Pentr. There is no console screen for it — the Evidence sidebar entry is greyed out — so the export is an HTTP call.
The call¶
API="https://<your-console-host>" # same origin as the console; there is no separate API host
TOKEN=... # your Kratos session token
ENGAGEMENT_ID=... # the engagement to export
curl -OJ -H "Authorization: Bearer $TOKEN" \
"$API/api/engagements/$ENGAGEMENT_ID/locker"
The response is application/zip, named pentr-locker-<engagement id>.zip. The
zip is built on demand for each request, so two exports of the same run are not
byte-identical: seal.json records a fresh exported_at, and each member is
stamped with the time it was written into the archive. Nothing that the
signature covers changes between them.
Failure responses:
| Status | Meaning |
|---|---|
404 |
No such engagement, or it belongs to another organization. The two answer identically on purpose. |
409 |
The run is not sealed, so there is nothing to export. |
409 |
The run was sealed before signing existed and has no signature. It cannot be exported as a verifiable locker. |
500 |
The server cannot read the evidence store, or the signing key row the seal names is gone. |
To hand a locker to someone without an account, use a share link instead; it serves the same zip.
What is in the zip¶
manifest.json
signature_block.json
signature.bin
public_key.pem
seal.json
README.txt
artifacts/<sha256>
manifest.json — the sealed, ordered record of every artifact: the format
version, the chain algorithm, the genesis value, the run block with the
framework and scope digest, one object per entry, the chain head and the entry
count. The bytes are copied from the store exactly as they were hashed.
signature_block.json — the bytes that were signed. It holds the signature
version and algorithm, the chain head, the manifest's SHA-256, the signing key
id and signed_at.
signature.bin — the raw Ed25519 signature over those bytes.
public_key.pem — the public half of the key named by the seal. A recipient
who wants to prove provenance pins a copy they obtained from you independently
and passes it with --key; the bundled copy alone proves only internal
consistency.
seal.json — an unsigned summary header: the locker format, the run id, the
chain head, the manifest hash, the entry count, the algorithms, the signing key
id, signed_at, sealed_at and exported_at. Nine of the eleven are
cross-checked at verification time: eight against the signed bytes, and the
format against the verifier's own version constant. sealed_at and
exported_at are checked against nothing, so neither is evidence of when the
run was sealed or when the archive was produced.
README.txt — how to verify the locker, what a pass and a fail mean, and a
note on key custody. It is not covered by the signature.
artifacts/<sha256> — one file per sealed artifact, named by its hash, flat
under artifacts/ with no further directories. Every entry in the manifest has
a file here, and a file under artifacts/ that no entry names is a verification
failure rather than a harmless extra. A member with any other top-level name, or
a path that walks outside the locker, is rejected before verification begins: a
malformed locker rather than a tampered one.
Three version strings¶
The locker's packaging version, the manifest's schema version and the
signature block's version are separate values that all read pentr-locker-1.
They are deliberately not aliases of one another: the container format, the
manifest schema and the signature block schema are three concerns that
happened to ship together, and each has to be able to change without the
others. If the manifest schema were bumped through a shared constant, the
locker would silently start advertising a container format that had not
changed.
Read seal.json's format for the container, manifest.json's version for
the manifest, and signature_block.json's version for the block.
Next¶
Verifying a locker is what the recipient does with the
zip: installing pentr-verify, running it against the file, and reading the
result.
Last updated 2026-09-24