Bundle Specification
This page specifies the PolicyBundle format version v1alpha1 as implemented on the main branch. For a guided introduction, refer to Bundle Structure.
Artifact
A signed bundle is one UTF-8 YAML file containing two YAML documents:
- The manifest payload, a
PolicyBundledocument. - After a
---separator, the signature document.
The member documents live in separate files next to the manifest.
Manifest Fields
The runtime ignores unknown manifest fields. The JSON Schema rejects them, so validate before signing.
Member paths are joined to the manifest’s directory without normalization. Keep them relative and inside the bundle directory.
Signature Document
Trust Roots
A verifier loads every file in its trust-root directory with one of these extensions. The file name without the extension is the key ID.
Member Files
A member file is a YAML document whose kind decides how it is used. Refer to Policy Schemas. A member may itself carry a yaml-sigil signature. APF then uses the member’s payload, but it does not verify the member’s signature against a trust root. The bundle signature, through the manifest digest of the member’s raw bytes, is what protects it.
Verification Order
A verifier processes a bundle in this order.
- Signature. Decompose the artifact, resolve
keyidin the trust roots, and verify the signature. On failure, stop withsignature_invalid. - Parse. Parse the verified payload as a
PolicyBundle. On failure, stop withbundle_parse_failed. - Members. For every manifest entry, read the file and compare its SHA-256 with the declared value:
manifest_member_unreadable,manifest_hash_unset, ormanifest_hash_mismatch. - Validity window. Check
not_beforeandexpires_atagainst the current time:not_before_invalid,expires_at_invalid,bundle_not_yet_valid, orbundle_expired. - Runtime compatibility. Check
min_versionvalues:runtime_compat_invalidorruntime_compat_mismatch. - Revision. Check
policy_revisionagainst the counter store:counter_regressionorcounter_content_mismatch.
Steps 3 to 6 all run, and every failure is reported, except that an unparseable not_before or expires_at skips the rest of step 4. The bundle is accepted only if none fails. The policy service then loads and compiles the members, and persists the revision only if compilation succeeds.
For the format of each reason, refer to Bundle Rejection Reasons.
Revision Rules
The counter store holds a high-water mark, the highest accepted policy_revision, and the payload digest accepted at it.
The payload digest is the SHA-256 of the verified manifest payload, without the signature document. Re-signing identical content therefore does not change it.
One counter store serves one policy service, whatever the bundle id. Refer to Expiry and Rollback Protection.
Runtime Compatibility
A verifier compares each min_version with the version of that runtime it is given, after removing a leading v. max_version is not evaluated. In this release the policy service supplies no runtime versions, so APF only checks that each min_version is a valid semantic version.
Manifest Order
Distribution Archive
The HTTP policy source fetches a gzipped tar archive of the bundle directory. After unpacking, the policy service tries .yaml files in this order and uses the first that verifies against its trust roots and parses as a bundle:
manifest.yaml.- Files whose name contains
bundle. - All other
.yamlfiles.
Member paths resolve relative to the chosen manifest.
Contract Definitions
Next Steps
- To produce a conforming bundle, refer to Compile and Sign.
- To see the checks in action, follow Reject a Tampered Bundle.