Release-evidence reference¶
This page defines Vexcalibur’s repository-maintained evidence formats. They are not part of the package’s pre-1.0 Python API.
Reviewed inputs¶
release-evidence/review.json and the synthetic conformance review use this
closed-world schema:
Field |
Constraint |
|---|---|
|
Integer |
|
|
|
Positive integer, advanced for each review |
|
Extended RFC 3339 UTC timestamp ending in |
|
Nonempty public attribution; repository review history supplies provenance |
|
|
|
Exact lock SHA-256 as four colon-delimited groups of 16 lowercase hexadecimal characters |
|
|
|
|
|
Exact findings SHA-256 in the same grouped form |
|
Array containing only |
|
Nonempty review conclusion and qualifications |
Unknown and duplicate JSON keys are errors. findings.json follows the
local-findings contract, with additional evidence rules:
its root contains only
findings;every finding explicitly uses
in_triage;every finding selects exactly one product by PURL or component reference;
canonical vulnerability/product pairs are unique; and
production source URLs and analysis text are suitable for public release.
After selector resolution, the reviewed assertion count must equal the canonical CycloneDX assertion count. Equivalent PURL and component-reference selectors cannot inflate the result.
Normal validation accepts only the production input path. The repository’s
synthetic input is accepted only when validate-review or
scripts/generate-release-evidence.sh receives --allow-synthetic. Its local
manifest records evidence_kind: synthetic_fixture and
intended_use: ci_conformance_only; it is never eligible for a publication
inventory. Production local evidence records evidence_kind: production and
intended_use: release_evidence_candidate.
Local bundle: manifest schema 1¶
scripts/generate-release-evidence.sh creates a local bundle. Every bundle
contains:
File |
Contract |
|---|---|
|
Normalized CycloneDX 1.5 reference-runtime SBOM |
|
Exact, hash-locked runtime requirements |
|
Byte-identical reviewed input |
|
Byte-identical reviewed input |
|
CycloneDX 1.6 VEX, including a valid zero-assertion document |
|
Schema-1 release, review, format, generator, validation, and artifact records |
|
Sorted digest inventory for every other file |
A nonempty review also produces vex.openvex.json and
vexcalibur-vex.json. Empty reviews omit them as described above.
The generated manifest has exactly these top-level fields:
Field |
Exact contract |
|---|---|
|
Integer |
|
The reviewed input’s |
|
|
|
Boolean recorded at generation; |
|
Shared release record |
|
|
|
|
|
Shared review-summary record |
|
Exact format records described above |
|
Empty array or the required OpenVEX and CSAF omission records |
|
Exact validation record below |
|
Filename-sorted artifact records for every payload file, excluding |
The inventory values are
coverage: cross-platform-reference-runtime,
sbom: sbom.cdx.json, and
sbom_specification: CycloneDX 1.5. limitation is:
uv.lock records the project's cross-platform reference runtime; it is not a claim about every environment-specific consumer resolution.
The generator values include distribution: vexcalibur, the installed package
version, the wheel filename and digest, its exact clean source commit,
wheel_source_dirty: false, and the uv version. The validation record has
exactly these fields and values:
Field |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
This manifest binds one wheel and commit but does not claim that publication occurred.
Publication inventory: manifest schema 1¶
The release workflow transports a second schema-1 manifest before finalization.
It is a candidate-free oracle, not a local evidence manifest or a published
release asset. Its directory contains exactly findings.json, review.json,
runtime-constraints.txt, sbom.cdx.json, uv.lock, manifest.json, and
SHA256SUMS.
Its manifest has exactly artifacts, inventory, inventory_kind, release,
review, schema_version, source_tree_clean, and uv_version. The exact
constraints are:
schema_versionis1,inventory_kindispublication_oracle, andsource_tree_cleanistrue;releaseandreviewuse the shared record shapes;inventorycontains the same coverage, limitation, SBOM name and specification as the local manifest, pluslock: uv.lockand the digest of that bundled lock;artifactscontains sorted records for the five inventory payload files; anduv_versionis a nonempty string.
Only production reviewed inputs can create this inventory. The finalizer copies the five payload files into the publication bundle, then replaces this transient manifest and checksum inventory with the schema-2 records.
Publication bundle: manifest schema 2¶
The reusable release-validation workflow creates one flat asset directory. Every publication bundle contains:
File |
Contract |
|---|---|
|
Exact reviewed lock bytes |
|
Normalized CycloneDX 1.5 SBOM regenerated from that lock |
|
Strict runtime installation contract |
|
Exact reviewed inputs |
|
Byte-identical output from the installed wheel and pinned Action |
|
Exact checked wheel later eligible for PyPI |
|
Exact checked source distribution later eligible for PyPI |
|
Closed-world schema-2 publication record |
|
Sorted digest inventory for every other release asset |
vex.openvex.json and vexcalibur-vex.json are additionally present when the
review contains at least one assertion.
The schema-2 verifier rejects unknown fields. The top-level fields are exactly:
Field |
Exact contract |
|---|---|
|
Integer |
|
|
|
|
|
Boolean |
|
Shared release record; tag must equal |
|
|
|
Shared six-field review-summary record |
|
Exact distribution record below |
|
Exact generated or zero-assertion records described above |
|
Exact validation record below |
|
Exact publication and provenance record below |
|
Filename-sorted records for every asset except |
The inventory is the publication-inventory record, including lock: uv.lock.
The generator contains exactly distribution, sdist_filename,
sdist_sha256, uv_version, version, wheel_filename, wheel_sha256,
wheel_source_commit, and wheel_source_dirty. The distribution is
vexcalibur; the expected filenames are
vexcalibur-VERSION.tar.gz and
vexcalibur-VERSION-py3-none-any.whl; the source commit equals the release
commit; and wheel_source_dirty is false.
The schema-2 validation record contains the six schema-1 fields plus
action_local_wheel_equivalence: passed. All other values and the
zero-assertion cross-format exception are unchanged.
publication has exactly these fields:
Field |
Exact contract |
|---|---|
|
|
|
Exact |
|
|
|
Exactly one sdist and one wheel record, each containing |
|
|
|
|
|
|
|
Exact Action provenance record below |
The action record contains exactly:
Field |
Value |
|---|---|
|
|
|
Full pinned companion Action commit |
|
|
|
|
|
|
|
|
|
Canonical payload digest of the generated VEX files |
|
|
Schema-2 creation currently requires Action commit
cc570fb0ab80df3f4b1e31c0608b95c0707d5b66. Verification with an explicit
expected Action commit requires that exact value. Historical verification
without one accepts only a commit in the verifier’s compiled allowlist for
schema 2; the manifest cannot extend that allowlist.
For each producer, the finalizer sorts the relevant
{name, sha256, size} records by filename, serializes them with the repository’s
canonical JSON serializer, and records the SHA-256 as payload_sha256. The
inventory payload covers the five reviewed inventory files, the build payload
covers the wheel and source distribution, and the direct and Action payloads
cover the generated VEX files. The latter two digests must be equal.
GitHub Actions archive digests are checked while artifacts cross jobs. They are deliberately absent from the published manifest because the archive envelope is transport metadata and may differ on a recovery run.
Runtime-constraint grammar¶
Both local and publication bundles use the same strict header:
--require-hashes
--only-binary :all:
Every following logical requirement has an exact name==version pin and at
least one --hash=sha256:... continuation. Direct URLs, includes, index or
find-links directives, editable requirements, non-exact specifiers, and any
directive that weakens binary-only hash checking are rejected.
Archive limits¶
Candidate archives are bounded before metadata is trusted:
Limit |
Value |
|---|---|
Maximum evidence file |
32 MiB |
Maximum archive members |
10,000 |
Maximum total expanded archive size |
128 MiB |
Maximum metadata member |
1 MiB |
Maximum wheel SCM metadata |
64 KiB |
Absolute paths, parent traversal, duplicate members, links, devices, special files, encrypted wheel entries, ambiguous metadata, and version/source mismatches are errors.
Integrity files¶
SHA256SUMS uses the GNU sha256sum form:
LOWERCASE_SHA256__TWO_SPACES__FILENAME
Entries are filename-sorted. The checksum file includes manifest.json but not
itself. The manifest excludes itself and SHA256SUMS, avoiding a circular
digest while the checksum file binds the manifest to all other assets.
Verify a local schema-1 bundle:
uv run --frozen python scripts/release_evidence.py verify-bundle \
--bundle-dir build/release-evidence
Verify a schema-2 publication bundle against an exact tag and commit:
RELEASE_TAG=v0.4.0
git fetch origin "refs/tags/$RELEASE_TAG:refs/tags/$RELEASE_TAG"
RELEASE_SHA="$(git rev-parse --verify "$RELEASE_TAG^{commit}")"
uv run --frozen python scripts/release_evidence.py verify-publication \
--bundle-dir build/publication-assets \
--release-tag "$RELEASE_TAG" \
--release-sha "$RELEASE_SHA"
The schema-1 verify-bundle command checks that SHA256SUMS, manifest artifact
records, file sizes, and bundle bytes agree. It does not independently enforce
the generator’s expected local schema-1 file set, rerun format validation, or
prove the semantic correctness of that manifest; generation and CI provide
those gates. verify-publication-inventory separately enforces the transient
schema-1 oracle contract.
Publication verification is deliberately stricter. It enforces the closed-world schema-2 file and manifest contracts and rechecks reviewed inputs, bundled-lock/SBOM semantics, runtime constraints, distribution metadata and SCM identity, format decisions, stable payload digests, and production policy. The release workflow separately reproduces lock-derived exports, runs the pinned official OpenVEX and CSAF validators, and compares the GitHub-hosted asset bytes after publication.
Protected release-note tag payload¶
The release-note payload is not part of either evidence manifest. It is the message of the protected bot-authored annotated release tag. The publisher serializes one compact canonical JSON object with exactly these fields:
Field |
Constraint |
|---|---|
|
Integer |
|
Exact |
|
Exact secret-scanned release-note string |
|
SHA-256 of the UTF-8 release-note bytes as 64 lowercase hexadecimal characters |
The tag ref must point to an annotated tag object. That object must directly target the expected release commit and name the automation bot’s GitHub noreply identity as tagger. Creation and immediate pre-publication checks parse the closed JSON object and require its exact field values. JSON key order or trailing whitespace is not a trust input; the embedded note bytes and digest are.
Recovery reads the tag through GitHub’s API, enforces the ref, object, target,
tagger, closed-world payload schema, tag value, and notes digest, and writes the
recovered note bytes from release_notes. If a draft or immutable release
already exists, its body must match those bytes. The recovered notes then pass
through the ordinary digest comparison and secret scan again. A mutable release
body is never accepted as the recovery authority.
Repository CLI subcommands¶
scripts/release_evidence.py exposes these maintainer interfaces. Arguments in
brackets are optional; every other argument shown is required.
Subcommand and arguments |
Purpose |
|---|---|
|
Render a nonnegative epoch as the canonical UTC release timestamp |
|
Normalize one uv CycloneDX 1.5 export |
|
Validate the reviewed inputs, bindings, and evidence policy |
|
Verify clean, full-commit wheel SCM metadata |
|
Print an absolute file URI with a SHA-256 fragment |
|
Validate a CycloneDX document against the selected bundled schema |
|
Compare canonical assertions across all three VEX formats |
|
Write and integrity-check a local schema-1 manifest and checksum file in a prepared staging directory |
|
Verify generic schema-1 checksum and artifact-record integrity |
|
Create and verify the schema-1 publication oracle |
|
Revalidate the oracle against an expected release identity |
|
Assemble and verify the flat schema-2 asset set |
|
Verify a complete schema-2 publication bundle |
prepare-publication-inventory and finalize-publication require a new output
directory and remove a partially created one after failure. The higher-level
scripts/generate-release-evidence.sh also refuses to replace its requested
local bundle directory. Verification commands do not create output directories;
normalize-sbom and finalize are lower-level writers and must be used only
with an intentionally prepared target.