Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 74 additions & 17 deletions schema/2.0/model/cyclonedx-component-2.0.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -250,20 +250,6 @@
"title": "Release notes",
"description": "Specifies release notes."
},
"modelCard": {
"$ref": "cyclonedx-ai-modelcard-2.0.schema.json#/$defs/modelCard",
"title": "AI/ML Model Card"
},
"data": {
"type": "array",
"items": {"$ref": "#/$defs/componentData"},
"title": "Data",
"description": "This object SHOULD be specified for any component of type `data` and must not be specified for other component types."
},
"cryptoProperties": {
"$ref": "cyclonedx-cryptography-2.0.schema.json#/$defs/cryptoProperties",
"title": "Cryptographic Properties"
},
"tags": {
"$ref": "cyclonedx-common-2.0.schema.json#/$defs/tags",
"title": "Tags"
Expand All @@ -282,20 +268,91 @@
},
"allOf": [
{
"title": "Versioning Requirement",
"description": "Requirement: ensure that `version` and `versionRange` are not present simultaneously.",
"not": {
"required": ["version", "versionRange"]
}
},
{
"title": "Version Range Requirement",
"description": "Requirement: 'versionRange' must not be present when 'isExternal' is `false`.",
"if": {
"properties": { "isExternal": { "const": false } }
"required": ["versionRange"]

@jkowalleck jkowalleck Aug 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intention:
? Requirement: 'versionRange' must not be present when 'isExternal' is false.

before change:
if isExternal is set to false, then versionRange must not be present.
-or- only if isExternal is true, then versionRange may be set.

isExternal versionRange present result/valid per rule
0 0 1
0 1 0
1 0 1
1 1 1

after change:
if versionRange is set, then isExternal must be true
-or- only if isExternal is true, then versionRange may be set.

isExternal versionRange present result/valid per rule
0 0 1
0 1 0
1 0 1
1 1 1

while technically the "before" and "after" work the same, i find the "bnefore" better since it is more on the actual textuial description>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that "before" and "after" are logically equivalent as truth tables — that part isn't in question. My preference for "after" (versionRange present → isExternal must be true) is really about consistency: the versionRange field description already says "May only be used if isExternal is true," which is that same direction. Wording the rule description the other way just means a reader has to mentally contrapose one against the other to confirm they agree.

Both truth tables treat isExternal as strictly binary (true/false), but in the schema it can also be absent. The current if block keys on "isExternal": {"const": false}, which won't match a missing property — so an object with versionRange set and isExternal omitted entirely still passes validation today. That's the actual defect I was pointing at originally, not just the wording. Whichever phrasing we land on, I think the spec text and the schema logic both need to explicitly account for the "isExternal omitted" case, not just true/false.

},
"then": {
"not": { "required": ["versionRange"] }
"properties": { "isExternal": { "enum": [true] } }
}
},
{
"title": "Hardware Requirement",
"description": "Requirement: Hardware components MUST NOT specify a swid or purl.",
Comment thread
stevespringett marked this conversation as resolved.
"if": {
"properties": { "type": { "enum": ["device"] } }
},
"else": true
"then": {
"not": {
"anyOf": [
{ "required": ["swid"] },
{ "required": ["purl"] }
]
}
}
},
{
"title": "Cryptography Requirement",
"description": "Requirement: cryptoProperties may only be used for cryptographic-asset.",
"if": {
"properties": { "type": { "enum": ["cryptographic-asset"] } }
},
"then": {
"properties": {
"cryptoProperties": {
"$ref": "cyclonedx-cryptography-2.0.schema.json#/$defs/cryptoProperties",
"title": "Cryptographic Properties"
}
}
},
"else": {
"not": { "required": ["cryptoProperties"] }
}
},
{
"title": "AI/ML Requirement",
"description": "Requirement: modelCard may only be used for machine-learning-model.",
"if": {
"properties": { "type": { "enum": ["machine-learning-model"] } }
},
"then": {
"properties": {
"modelCard": {
"$ref": "cyclonedx-ai-modelcard-2.0.schema.json#/$defs/modelCard",
"title": "AI/ML Model Card"
}
}
},
"else": {
"not": { "required": ["modelCard"] }
}
},
{
"title": "Data Requirement",
"description": "Requirement: data may only be used for components of type data.",
"if": {
"properties": { "type": { "enum": ["data"] } }
},
"then": {
"properties": {
"data": {
"type": "array",
"items": {"$ref": "#/$defs/componentData"},
"title": "Data Properties"
Comment thread
stevespringett marked this conversation as resolved.
}
}
},
"else": {
"not": { "required": ["data"] }
}
}
]
},
Expand Down