Skip to content

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.

{root}/v1/{instanceId}/{env}/{serverKey}/{planKey}/{yyyy}/{MM}/{runStamp}_{runId}/{artifactFile}
{root}/v1/{instanceId}/{env}/{serverKey}/{planKey}/{yyyy}/{MM}/{runStamp}_{runId}/_manifest.json

Keys 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.

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).

  • 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.stringify escapes 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 signature member: "signature": {"alg": "Ed25519", "keyId": "<uuid>", "canonicalization": "RFC8785", "value": "<base64>"}.
  • keyId is the key ring row of the platform’s ManifestSigning key. 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.

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.json

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).