Run manifest v1
| Field | Value |
|---|---|
| Status | Published with BMP-P3-E3.5-S02 (layout v1) |
| Requirements | FR-STO.4, FR-STO.5, FR-STO.12, FR-DR.1, NFR-30 |
| Design | Storage, retention & restore §5.1–§5.6 · Formats & encryption §21 · ADR-006 decision 6 |
| Schema | v1/bmp.manifest.v1.schema.json (JSON Schema 2020-12) |
| Example | v1/example/_manifest.json signed with the test-only key in v1/example/manifest-signing-keys.json |
| Reference verifier | docs/specs/manifest/reference/manifest_ref.py (Python 3, pyca/cryptography) |
A backup run is committed by one file, _manifest.json, written last into the run’s folder. It lists every
verified artifact of the run with what is needed to find, check and restore it without the platform’s catalogue.
A run folder without a manifest is not a restore point.
1. Where it lives
Section titled “1. Where it lives”{root}/v1/{instanceId}/{env}/{serverKey}/{planKey}/{yyyy}/{MM}/{runStamp}_{runId}/{artifactFile}{root}/v1/{instanceId}/{env}/{serverKey}/{planKey}/{yyyy}/{MM}/{runStamp}_{runId}/_manifest.jsonKeys are lower-case [a-z0-9._/-], hold no colon, and are built only by ObjectKeyBuilder. runStamp is the UTC
start of the run as yyyyMMddTHHmmssZ written in lower case (20260915t020004z). The manifest carries the Object
Lock of its longest-locked artifact.
2. Content
Section titled “2. Content”Plaintext metadata only: platform, run (plan, server, environment, trigger, times, status, failed sources) and, per
artifact, its key, source, engine and tool, format, layers, compression, encryption mode, envelope, key id,
version and fingerprint, stored size, plain size, SHA-256 of the stored bytes, and storage version, ETag and parts.
The schema lists every member; every member is always present, null when it does not apply.
It never holds a key, a password, a wrapped key, or the plaintext hash of an encrypted artifact (AC-OR2-5).
3. Canonical form and signature
Section titled “3. Canonical form and signature”- The stored bytes are the RFC 8785 (JCS) form of the manifest: members
sorted by their UTF-16 code units, no insignificant whitespace, strings escaped as ECMAScript’s
JSON.stringifyescapes them. Every number is an integer below 2^53, so a number is written as its digits. - The signature is Ed25519 over the JCS form of the manifest without its
signaturemember:"signature": {"alg": "Ed25519", "keyId": "<uuid>", "canonicalization": "RFC8785", "value": "<base64>"}. keyIdis the key ring row of the platform’sManifestSigningkey. Its public key is published in{root}/v1/_tools/manifest-signing-keys.json-{"keys": [{"keyId", "algorithm": "Ed25519", "publicKey": "<base64>"}]}- and old keys are never removed from it, because a manifest outlives the key version that signed it.
4. Checking one
Section titled “4. Checking one”A reader refuses, never merely warns about: a file over 1 MiB, JSON with a duplicate member, a number with a
fraction or an exponent or beyond 2^53, a schema other than bmp.manifest/v1 (or v1.N), a missing signature, an
algorithm other than Ed25519, a key it does not know, and a signature that does not verify.
python docs/specs/manifest/reference/manifest_ref.py verify --manifest _manifest.json --keys manifest-signing-keys.json5. The example
Section titled “5. The example”v1/example/_manifest.json is the example of storage §5.4, signed with a test-only key whose private seed is
the 32 bytes 00 01 02 … 1f. That key signs nothing but this example; it is published so that anybody can
reproduce the file byte for byte. The platform’s own test (RunManifestTests) re-signs the example on every build
and fails if one byte differs, which is what keeps the format from drifting within layout v1 (NFR-30).