Skip to content

[2.0] fixes on schema and test resources - #1001

Merged
jkowalleck merged 48 commits into
2.0-devfrom
2.0-tests-init-fixes
Aug 24, 2026
Merged

[2.0] fixes on schema and test resources#1001
jkowalleck merged 48 commits into
2.0-devfrom
2.0-tests-init-fixes

Conversation

@jkowalleck

@jkowalleck jkowalleck commented Aug 4, 2026

Copy link
Copy Markdown
Member

fixes or related to

see also:

besides those fixes above, this is in the PR:

  • made the refLinkType inherit explicit
  • fixes the array nesting of extensibleProerties
  • consolidated milisecond timestamp for JSS
  • adds $comments
  • enhanced some docs
  • added test cases
    • for extensibleProperties
  • fixed valid test data
    • all test data that was just carried over from CDX 1.x was transferred to CDX 2.0schema
  • fixed invalid test data
    • removed invalid-component-choice-missing-name-2.0.json - as the name was optional or did not exist.
      ❓ was this intentional/correct

tests for the things are based on:

@jkowalleck jkowalleck mentioned this pull request Aug 4, 2026
4 tasks
@jkowalleck jkowalleck changed the title 2.0 tests init fixes 2.0 fixes Aug 4, 2026
@jkowalleck jkowalleck added defect CDX 2.0 related to release v2.0 labels Aug 4, 2026
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck
jkowalleck force-pushed the 2.0-tests-init-fixes branch from a03e560 to 905e58a Compare August 4, 2026 15:36
jkowalleck added a commit that referenced this pull request Aug 4, 2026
- [x] Java tests - functional
- [x] JS tests - functional - WIP
- found some false-positives/false-negatives - due to errors in test
resources
- [x] JS tests - schema validate
  - includes #996
  - includes #992
- JS tests - semantics
  - [x] #998
  - [x] #995
- [x] PHP tests - functional

added tests only,
no schema/res fixes - they are prepared in 
- #997 
- #1001

---------

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
jkowalleck and others added 23 commits August 4, 2026 19:00
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck
jkowalleck marked this pull request as draft August 21, 2026 13:30
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck

jkowalleck commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

had Fable 5 analyze the state of the schema.

my query:

Analyze the JSON Schema structure under https://github.com/CycloneDX/specification/blob/2.0-tests-init-fixes/schema/2.0/cyclonedx-2.0.schema.json . Ignore all `-bundled` files.

Starting from the root schema , follow every $ref transitively through the files in  (e.g. cyclonedx-metadata, cyclonedx-component, cyclonedx-service, cyclonedx-dependency, cyclonedx-composition, cyclonedx-vulnerability, cyclonedx-annotation, cyclonedx-formulation, cyclonedx-declaration, cyclonedx-definition, cyclonedx-citation, cyclonedx-perspective, cyclonedx-common, cyclonedx-party, cyclonedx-license, cyclonedx-data, cyclonedx-cryptography, cyclonedx-ai-modelcard, cyclonedx-release-notes, cyclonedx-standard, cyclonedx-patent, cyclonedx-jss_X590_2023_10, cyclonedx-api) and check whether the schema makes sense in its current structure. Specifically verify:
Code

- Broken references: every `$ref` (relative file path + JSON pointer like `#/$defs/xyz`) resolves to an existing file and an existing $defs entry in that file. List any $ref that points to a missing file or missing definition.
- `$id` consistency: each file's $id matches its actual path/filename and the expected https://cyclonedx.org/schema/2.0/... convention.
Orphaned files/definitions: model files or $defs entries not reachable from the root schema (excluding the separate cyclonedx-api-2.0.schema.json entry point — check its refs too).
- Circular references that could be problematic, and duplicate definitions of the same concept in multiple files.
- Draft 2020-12 correctness: proper use of $defs, unevaluatedProperties interaction with allOf/$ref (note the root uses unevaluatedProperties: false together with allOf extensibleProperties — check whether this composition works as intended across files), missing $schema declarations, wrong keyword usage, invalid regex patterns, enum/const misuse.
- Naming/structural inconsistencies: inconsistent def naming, inconsistent title/description conventions, anything that looks off (e.g. typos in filenames like jss_X590 vs X.509).

Produce a report of concrete issues found, each with file path, JSON pointer location, and a suggested fix. Also state explicitly which aspects were checked and found to be fine.

I need the report in pastable markdown.

report:

CycloneDX 2.0 JSON Schema Structure Review

Scope: branch 2.0-tests-init-fixes, schema/2.0/cyclonedx-2.0.schema.json + schema/2.0/cyclonedx-api-2.0.schema.json + all 34 files in schema/2.0/model/, excluding *-bundled* files. All $refs followed transitively; every file metaschema-validated against JSON Schema draft 2020-12.


1. Broken / fragile references

All intra-schema/2.0 refs resolve correctly (file + #/$defs/... pointer) — 0 hard-broken refs among the 36 files. However, five refs escape the versioned tree via ../../ and two of them have a real identifier mismatch:

# File / JSON pointer Ref Issue Suggested fix
1.1 model/cyclonedx-cryptography-2.0.schema.json #/$defs/cryptoProperties/properties/algorithmProperties/properties/algorithmFamily ../../cryptography-defs.schema.json#/definitions/algorithmFamiliesEnum Target file exists and pointer exists, but the ref resolves (per RFC 3986 against the base $id) to https://cyclonedx.org/schema/cryptography-defs.schema.json, while that file declares "$id": "http://cyclonedx.org/schema/cryptography-defs.schema.json" (http vs https). $id-based resolvers/registries will fail to match. Also a draft-07 file (definitions, not $defs) referenced from a 2020-12 schema, and an unversioned dependency outside schema/2.0/. Update the external file's $id to https:// (or ref the http:// URI explicitly); long-term, snapshot a 2020-12 copy under schema/2.0/.
1.2 same file, .../properties/ellipticCurve ../../cryptography-defs.schema.json#/definitions/ellipticCurvesEnum Same as 1.1. Same as 1.1.
1.3 model/cyclonedx-license-2.0.schema.json #/$defs/license/properties/id ../../spdx.schema.json Target exists, but resolves to https://cyclonedx.org/schema/spdx.schema.json while the file declares "$id": "http://cyclonedx.org/schema/spdx.schema.json" — same http/https mismatch; draft-07 target. Same as 1.1.
1.4 model/cyclonedx-behavior-2.0.schema.json #/$defs/behaviorInstance/properties/behavior and #/$defs/behaviorNode/properties/behavior ../../behavior-taxonomy.schema.json Resolves cleanly ($id is https://…, draft 2020-12) ✅ — but it is an unversioned dependency outside schema/2.0/; future edits to the shared file silently change 2.0 semantics. Consider versioning it under schema/2.0/ or pinning.

2. $id consistency — ✅ (within 2.0)

Every one of the 36 files has $id exactly matching https://cyclonedx.org/schema/2.0/<path> and its actual path/filename, and $schema: https://json-schema.org/draft/2020-12/schema. The only $id problems are the external http/https mismatches in 1.1–1.3.

3. Orphaned files / definitions

  • Files: none orphaned — all 34 model files are transitively reachable from the root schema. ✅
  • cyclonedx-api-2.0.schema.json is an empty stub: {"type": "object", "$defs": {}} — no properties, no refs. The README describes it as "the normative API-focused schema [that] reuses CycloneDX models", which it currently does not.
    Fix: implement it or mark it as a placeholder in the README.
  • Orphaned $defs (referenced from nowhere, including their own file):
Location Issue Suggested fix
model/cyclonedx-common-2.0.schema.json#/$defs/organizationalEntityOrContact Literally {"$comment": "TODO"} — an unfinished stub. Implement or delete.
model/cyclonedx-common-2.0.schema.json#/$defs/timestamp Unused, while 48 places across the corpus inline "format": "date-time" without a pattern. In 2020-12, format is annotation-only by default, so those 48 timestamps are effectively unvalidated, and the one def that does validate (format + pattern) is dead. Ref common#/$defs/timestamp everywhere (or delete it and accept format-only).
model/cyclonedx-common-2.0.schema.json#/$defs/base64 Unused; common#/$defs/attachment declares encoding: enum ["base64"] but never validates content against this pattern. Wire it into attachment (e.g. via if/then on encoding) or delete.
model/cyclonedx-common-2.0.schema.json#/$defs/baseObject The "mixin base object for all CycloneDX entities" (composes extensibleProperties) is dead code — nothing refs it. Consequence: only the document root composes extensibleProperties; every other object is closed with additionalProperties: false, so the ext:<namespace>:<name> extension mechanism is unusable anywhere except the BOM top level. Either have entity defs compose baseObject/extensibleProperties + unevaluatedProperties: false, or delete baseObject and document that extensions are root-only.

4. Circular references & duplicate definitions

  • File-level cycle: cyclonedx-component-2.0.schema.jsoncyclonedx-ai-modelcard-2.0.schema.json (component → modelCard, graphicsCollection; ai-modelcard → componentData). Fully resolvable for validators — not problematic, but worth knowing for code generators. Self-recursive defs (nested components, dependency graph, etc.) are standard and fine.
  • Duplicate $defs names across files (14): dependency, flow, hashAlgorithm, identifier (×3), metadata, postalAddress, rating, requirement, requirements, risk, signatures, step, timestamp, trigger.
    • True concept duplicate: postalAddress in common vs party — the party version is a superset (adds isoCode, coordinates). Two competing address models. Fix: keep one (party's) and ref it; delete/alias the other.
    • Intentional but collision-prone: hashAlgorithm and timestamp in cyclonedx-jss_X590_2023_10 deliberately differ from common (IANA names / X.590 clause 6.1 millisecond rule). Fine semantically, but same-named defs across files will clash in naive bundlers/codegen. Fix: prefix jss defs (e.g. jssTimestamp) or namespace during bundling.
    • The rest (dependency in dependency vs requirement, flow, metadata, identifier, rating, risk, step, trigger, …) are genuinely different domain concepts sharing generic names — acceptable, same bundling caveat.

5. Draft 2020-12 correctness

  • Metaschema validation: 0 violations in all 36 files.
  • Regex patterns: all pattern/patternProperties compile.
  • Root composition (unevaluatedProperties: false + allOf: [$ref → common#/$defs/extensibleProperties]): works as intended. In 2020-12, unevaluatedProperties sees annotations from patternProperties inside schemas reached through allOf/$ref, so ext:… properties are correctly allowed at the root while unknown properties are rejected. ✅
  • additionalProperties: false + allOf combinations (e.g. component#/$defs/component, behavior#/$defs/behaviorGraph|behaviorNode, vulnerability#/$defs/presenceEvidence, threat categories): verified that no allOf branch introduces property names absent from the parent's properties — all branches are not/if-then constraints on declared properties, so nothing is falsely rejected. ✅ However, this closes those objects to ext: extensions (see §3 baseObject) and mixes two closure idioms (additionalProperties: false vs the root's unevaluatedProperties: false). Suggested fix: standardise on one idiom per the intended extensibility model.
  • $schema declarations: present and correct in every file. ✅ No legacy keywords (definitions, boolean exclusiveMinimum, additionalItems) anywhere. ✅ (cyclonedx-definition-2.0.schema.json#/$defs/definitions is a def named "definitions", not the keyword — legal, mildly confusing.)
  • specVersion is unconstrained: cyclonedx-2.0.schema.json#/properties/specVersion is required but has only examples: ["2.0"] — any string validates. 1.x schemas pinned it with enum. Fix: add "const": "2.0" (or an enum/pattern).
  • Single-value enums (prefer const): cyclonedx-2.0.schema.json#/properties/specFormat (["CycloneDX"]), ai-modelcard#/$defs/energyMeasure/properties/unit (["kWh"]), ai-modelcard#/$defs/co2Measure/properties/unit (["tCO2eq"]), common#/$defs/attachment/properties/encoding (["base64"]), evidence#/$defs/assessmentMethod/allOf/1/.../not (["filename"]). Cosmetic.
  • jss…#/$defs/signatureObject sets unevaluatedProperties: true: redundant (open is the default) but intentional and documented via $comment citing X.590 clause 6.2. OK as-is.
  • Non-standard meta:enum keyword: used consistently and every meta:enum key set exactly matches its sibling enum values ✅ (established CycloneDX 1.6/1.7 convention).

6. Naming / structural inconsistencies

Location Issue Suggested fix
model/cyclonedx-jss_X590_2023_10-2.0.schema.json Not a typo: ITU‑T X.590 (2023‑10) is the JSON Signature Scheme (JSS) — distinct from X.509; common#/$defs/signatures even links the ITU X.590 publication. Only the style is inconsistent: underscores + embedded date vs the hyphenated, undated names of every other file. Optionally rename to e.g. cyclonedx-jss-x590-2.0.schema.json for consistency.
jss signatureObject properties snake_case (hash_algorithm, public_key, cert_url, valid_from, …) vs camelCase everywhere else — intentional (X.590 wire format), but worth a $comment if not already obvious. Document; keep as-is.
Root container shape inconsistency components, dependencies, compositions, vulnerabilities, controls, annotations, formulation, blueprints, citations, perspectives are arrays, but threats, risks, declarations, definitions, profiles are objects wrapping same-named arrays (bom.threats.threats[], bom.risks.risks[]). Accept (matches 1.6 declarations precedent) or flatten for uniformity; at minimum document the convention.
26 of 307 $defs lack title e.g. common#/$defs/refType, refLinkType, component#/$defs/version, versionRange, componentData, composition#/$defs/aggregateType, formulation#/$defs/step, command, … Add titles for doc-generation consistency.
schema/2.0/README.md Table references cyclonedx-api-2.0-bundled.schema.json, which does not exist. Create it or remove the row.
schema/2.0/model/README.md Badly stale: lists 4 nonexistent files (cyclonedx-ai-model-parameters, cyclonedx-licensing, cyclonedx-patent-assertion, cyclonedx-patent-family) and omits ~16 real files (behavior, blueprint, business-objective, certification, citation, control, data, evidence, jss, party, perspective, physical, profile, requirement, risk, threat, usecase, weakness). Regenerate the model index.
component#/$defs/component/properties/mime-type Kebab-case like legacy bom-ref; everything else camelCase. Accept as 1.x-compat or rename (mimeType) since 2.0 is a breaking release.

7. Explicitly checked and found fine

  • ✅ All 36 files parse as valid JSON and validate against the draft 2020-12 metaschema (0 errors).
  • ✅ All intra-schema/2.0 $refs (file + #/$defs/... pointer) resolve; all pointers into external files (#/definitions/...) also exist.
  • $id ↔ path/filename convention correct in all 36 files; $schema present everywhere.
  • ✅ No orphaned model files — every model file is reachable from the root schema.
  • ✅ Root unevaluatedProperties: false + allOf → extensibleProperties composition behaves correctly under 2020-12 annotation rules.
  • ✅ No additionalProperties: false object is broken by its allOf branches (no branch declares undeclared property names).
  • ✅ All regexes compile; serialNumber urn:uuid pattern is correct; patternProperties ^ext:...$ anchored correctly.
  • ✅ No required entries missing from properties in closed objects; no duplicate required entries; no unknown format values; no $ref siblings that add conflicting constraints; meta:enum fully consistent with enum everywhere; $defs names uniformly lowerCamelCase.
  • jss_X590 filename is not an X.509 typo — it correctly references ITU-T X.590 (JSS), edition 2023-10.

Priority fixes (summary)

  1. Fix http vs https $id mismatch in schema/cryptography-defs.schema.json and schema/spdx.schema.json (breaks $id-based ref resolution from 2.0).
  2. Resolve the dead extensibility design: orphaned baseObject + closed objects means ext: properties only work at the BOM root.
  3. Implement or clearly stub cyclonedx-api-2.0.schema.json; add the missing cyclonedx-api-2.0-bundled.schema.json or fix the README.
  4. Finish or remove common#/$defs/organizationalEntityOrContact (TODO stub); wire up or remove orphaned timestamp/base64 defs (and add pattern to the 48 unvalidated date-time fields if strict validation is intended).
  5. Constrain specVersion (e.g. const: "2.0").
  6. Deduplicate postalAddress (common vs party); regenerate model/README.md.

actions taken:

  1. will not do. the schema has an existing and working and in-use ID
  2. might consider - not in the scope of this PR
  3. out of scope for this PR
  4. out of scope of this PR
  5. not planned. it is a free string that needs to stay like this for compatibility reasons with future/previous releases.

@jkowalleck
jkowalleck marked this pull request as ready for review August 21, 2026 16:00
@taleodor

This comment was marked as off-topic.

@jkowalleck

This comment was marked as off-topic.

@jkowalleck

This comment was marked as outdated.

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck jkowalleck added test-data related to test-resources and -data format: JSON and removed chore A chore labels Aug 24, 2026
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CDX 2.0 related to release v2.0 defect format: JSON ready for review test-data related to test-resources and -data

Projects

None yet

3 participants