CycloneDX::VersionGate
Spec-version field and enum gating.
CycloneDX grew over successive spec versions in two different ways, and both have to be gated:
- fields were added — a BOM declared as
specVersion1.4 must NEVER contain a field that only exists from 1.5 on; - enum values were added —
component/@typewent from 8 permitted values in 1.4 to 13 in 1.6, andexternalReference/@typefrom 16 to 47. A structurally-correct document whosetypeiscryptographic-assetstill fails 1.4 validation.
VersionGate is the single source of truth for "what was introduced when".
It drives:
- a post-serialization JSON filter (
filter_json_any), - an equivalent XML filter (
filter_xml), - the
Validator, which reports whatever the filter had to change.
The last point matters: violations does not re-implement the rules, it
runs the JSON filter and collects what it did. The validator therefore
cannot fall out of sync with the serializers.
What the gate does about an out-of-range value
Too-new fields are stripped. Too-new enum values are downgraded to the
enum's designated catch-all where the spec defines one (other for
externalReferenceType, not_specified for aggregateType). Where there is
no catch-all the value is left alone, because inventing a substitute would
misrepresent the component — Validator reports it instead, and the CLI
validates before writing so it can never emit such a document. The one
exception is hash/@alg, which is required and has no catch-all: there the
whole hash entry is dropped, since an optional hash is better lost than
invalid.
The field map is keyed by context (the kind of object a field lives in)
rather than by bare field name, because some names are ambiguous (e.g. tags
exists on component only from 1.6 but on releaseNotes since 1.4, and
bom-ref is core on a component but 1.5-only on a license).
Constants
aggregateType (composition/aggregate).
{parent context, json key} => the context to filter the value under.
externalReferences and hashes are matched by key alone (see
child_context) because they hang off many different parents and the key
name is unambiguous across the whole schema.
classification (component/@type).
The catch-all each enum designates for "a type this document cannot express". Enums with no catch-all are absent, which is what makes a value non-downgradeable.
externalReferenceType (externalReference/@type).
Context => { json_key => minimum_spec_version }.
The contexts identify which kind of object the gated keys live in; see
CHILD_CONTEXT for how the JSON filter descends into them and
XML_CONTEXT for the XML equivalent.
Only fields the object model can actually produce are listed. 1.7 added
bom.citations, metadata.distributionConstraints,
component.isExternal/patentAssertions/versionRange,
service.patentAssertions and externalReference.properties; none are
modelled yet, so none appear here.
Context => { json_key => value-version table }.
Fields the JSON schema gained later than the XSD did, so they must be
stripped from JSON but kept in XML. bom.properties is the only one: the
1.4 XSD lists properties among the bom element's children, but the 1.4
JSON schema does not allow it at the document root.
hashAlg (hash/@alg).
Ordering of the supported spec versions, oldest first.
The XML filter reuses GATED: every gated JSON key maps to an XML element
of the same name, and the gating context is identified by the parent
element's name. GATED_JSON_ONLY is deliberately not consulted here.
Catch-alls for XML_ENUM_ATTRS, mirroring ENUM_FALLBACK.
Enum-valued attributes, by element name.
Elements whose text content is an enum value, with their catch-all.
Fields that are attributes in XML rather than elements, by element name.
Class methods
Yields a Violation for everything the gate has to strip, drop or rewrite
to make bom valid at its declared specVersion. Used by Validator.
String-in/string-out convenience wrapper around filter_json_any.
Returns a copy of json (a serialized CycloneDX BOM document) filtered
down to what spec_version permits. When violations is given, every
edit the filter makes is appended to it.
Returns a copy of xml with elements, attributes and enum values newer
than spec_version removed or downgraded.
Returns true when field_version is newer than the declared
spec_version (i.e. the field must be stripped / flagged).
Collects all spec-version violations on bom.
This runs the JSON filter over the pre-gate document and reports what it changed, rather than re-deriving the rules. Anything the filter learns to handle is therefore reported automatically, and the two can never disagree.