Goal
Ensure docs/schemas/release-bom.schema.json and
cli/python/base_release/release_bom.py::validate_bom cannot silently
diverge -- either by enforcing the schema at validation time or by a
conformance test that fails on disagreement.
Background
From the 2026-09-09 deep review of the release-BOM feature (Base 1.9.0):
docs/release-bom.md calls docs/schemas/release-bom.schema.json "the
contract", but nothing loads it. validate_bom is a separate hand-rolled
implementation, and the two already disagree:
| Rule |
Schema |
validate_bom |
combination.participants |
minItems: 1 |
>= 2 distinct (casefold) |
component tag required for non-moving / forbidden for moving |
not expressed |
enforced |
required: true with source_mode: moving |
allowed |
rejected |
required: true with result != passed |
allowed |
rejected |
| unknown keys |
additionalProperties: false |
not checked -- assemble will fold an extra key into the canonical digest |
release.version |
strict SemVer pattern (no leading zeros) |
any non-empty string |
There is no test that runs representative documents through both layers.
Scope
Pick one primary approach and implement it:
- Enforce the schema: add
jsonschema as a first pass inside
validate_bom (pin jsonschema in requirements-dev.txt), keeping the
semantic checks JSON Schema cannot express (tag == v<version>,
required/moving/result interactions, cross-references). Keep runtime schema
loading in dev/test paths only if shipping the dependency is a packaging
concern.
- Or add a conformance harness: a shared corpus of valid/invalid BOM
documents run through both the JSON Schema and validate_bom, asserting the
accept/reject verdict agrees (semantic-only rejections are annotated as
expected schema-passes).
In addition, regardless of approach:
- Tighten
validate_bom to reject unknown keys in release, each component,
and each combination (match additionalProperties: false).
- Align
combination.participants minimum and the release.version /
component version format between schema and validator.
cli/python/base_release/tests/test_release_bom.py: add the
conformance/round-trip cases.
docs/release-bom.md: state precisely which layer enforces what.
Acceptance Criteria
Validation
python -m pytest cli/python/base_release/tests/test_release_bom.py -q
bin/base-release-bom validate tests/fixtures/release-bom-valid.json \
--repository basefoundry/base-bash-libs --version 2.1.0
bin/base-test
Non-Goals
- No change to the BOM wire format or
schema_version (unless the tightening
concludes a bump is warranted, decided in this issue).
- Not adopting a schema library in shipped non-dev code paths if that
conflicts with packaging constraints.
Project Fields
- Status: Backlog
- Priority: P2
- Size: M
- Area: Packaging
- Initiative: Contract Hardening
- Milestone: v1.10.0
Agent Assignment
Human first. Needs a maintainer decision between "enforce schema at runtime"
and "conformance harness" before implementation.
Goal
Ensure
docs/schemas/release-bom.schema.jsonandcli/python/base_release/release_bom.py::validate_bomcannot silentlydiverge -- either by enforcing the schema at validation time or by a
conformance test that fails on disagreement.
Background
From the 2026-09-09 deep review of the release-BOM feature (Base 1.9.0):
docs/release-bom.mdcallsdocs/schemas/release-bom.schema.json"thecontract", but nothing loads it.
validate_bomis a separate hand-rolledimplementation, and the two already disagree:
validate_bomcombination.participantsminItems: 1tagrequired for non-moving / forbidden for movingrequired: truewithsource_mode: movingrequired: truewithresult != passedadditionalProperties: falseassemblewill fold an extra key into the canonical digestrelease.versionThere is no test that runs representative documents through both layers.
Scope
Pick one primary approach and implement it:
jsonschemaas a first pass insidevalidate_bom(pinjsonschemainrequirements-dev.txt), keeping thesemantic checks JSON Schema cannot express (tag ==
v<version>,required/moving/result interactions, cross-references). Keep runtime schema
loading in dev/test paths only if shipping the dependency is a packaging
concern.
documents run through both the JSON Schema and
validate_bom, asserting theaccept/reject verdict agrees (semantic-only rejections are annotated as
expected schema-passes).
In addition, regardless of approach:
validate_bomto reject unknown keys inrelease, each component,and each combination (match
additionalProperties: false).combination.participantsminimum and therelease.version/component
versionformat between schema and validator.cli/python/base_release/tests/test_release_bom.py: add theconformance/round-trip cases.
docs/release-bom.md: state precisely which layer enforces what.Acceptance Criteria
validate_bomdisagree on any documentin the shared corpus.
validate_bom.participantsminimum and onrelease.version/ componentversionformat.tests/fixtures/release-bom-valid.jsonand a CI-assembled BOM stillvalidate under both layers.
docs/release-bom.mdaccurately describes the split of enforcement.Validation
Non-Goals
schema_version(unless the tighteningconcludes a bump is warranted, decided in this issue).
conflicts with packaging constraints.
Project Fields
Agent Assignment
Human first. Needs a maintainer decision between "enforce schema at runtime"
and "conformance harness" before implementation.