From be626a971dac652728d3c08a272c1c0419e67a6b Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Thu, 1 May 2025 14:46:01 -0500 Subject: [PATCH 01/15] Added citation support and test cases. Signed-off-by: Steve Springett --- schema/bom-1.7.proto | 17 ++++ schema/bom-1.7.schema.json | 63 +++++++++++++++ schema/bom-1.7.xsd | 54 +++++++++++++ .../resources/1.7/valid-citations-1.7.json | 77 +++++++++++++++++++ .../1.7/valid-citations-1.7.textproto | 75 ++++++++++++++++++ .../resources/1.7/valid-citations-1.7.xml | 71 +++++++++++++++++ 6 files changed, 357 insertions(+) create mode 100644 tools/src/test/resources/1.7/valid-citations-1.7.json create mode 100644 tools/src/test/resources/1.7/valid-citations-1.7.textproto create mode 100644 tools/src/test/resources/1.7/valid-citations-1.7.xml diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index 999dccba..f2c8adf7 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -43,6 +43,8 @@ message Bom { repeated Declarations declarations = 14; // A collection of reusable objects that are defined and may be used elsewhere in the BOM. repeated Definition definitions = 15; + // Details a specific attribution of data within the BOM to a contributing entity or process. + repeated Citation citations = 16; } enum Classification { @@ -2393,3 +2395,18 @@ message CryptoProperties { // The object identifier (OID) of the cryptographic asset. optional string oid = 6; } + +message Citation { + // Optional unique identifier for the citation + optional string bom_ref = 1; + // Field reference using JSON Pointer format + string pointer = 2; + // Timestamp when the citation occurred + google.protobuf.Timestamp timestamp = 3; + // The entity (component, service, org, or person) that supplied the data (optional) + optional string attributed_to = 4; + // The process (workflow/formula/task) that generated the data (optional) + optional string process = 5; + // Optional human-readable note + optional string note = 6; +} diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json index 60459495..1e4b5f8a 100644 --- a/schema/bom-1.7.schema.json +++ b/schema/bom-1.7.schema.json @@ -517,6 +517,14 @@ } } }, + "citations": { + "type": "array", + "additionalItems": false, + "items": {"$ref": "#/definitions/citation"}, + "uniqueItems": true, + "title": "Citations", + "description": "A list of attributions indicating which entity supplied information for specific fields within the BOM." + }, "properties": { "type": "array", "title": "Properties", @@ -5725,6 +5733,61 @@ "translation", "object-detection" ] + }, + "citation": { + "type": "object", + "title": "Citation", + "description": "Details a specific attribution of data within the BOM to a contributing entity or process.", + "additionalProperties": false, + "properties": { + "bom-ref": { + "$ref": "#/definitions/refType", + "title": "BOM Reference" + }, + "attributedTo": { + "$ref": "#/definitions/refLinkType", + "title": "Attributed To", + "description": "The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information." + }, + "pointers": { + "type": "array", + "additionalItems": false, + "items": { + "type": "string", + "title": "Field Reference", + "description": "A [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations." + }, + "minItems": 1, + "title": "Field References", + "description": "One or more [JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies." + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp", + "description": "The date and time when the attribution was made or the information was supplied." + }, + "process": { + "$ref": "#/definitions/refLinkType", + "title": "Process Reference", + "description": "An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data." + }, + "note": { + "type": "string", + "title": "Note", + "description": "An optional description or comment about the context or quality of the data attribution." + }, + "signature": { + "$ref": "#/definitions/signature", + "title": "Signature", + "description": "An optional digital signature verifying the authenticity or integrity of the attribution." + } + }, + "required": ["pointers", "timestamp"], + "anyOf": [ + { "required": ["attributedTo"] }, + { "required": ["process"] } + ] } } } diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index dfc9eaa5..3c3ddf0f 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8349,6 +8349,55 @@ limitations under the License. + + + + + + Details a specific attribution of data within the BOM to a contributing entity or process. + + + + + + + + + + + + + + + + + + + + + + + Allows any undeclared elements as long as the elements are placed in a different namespace. + + + + + + + + An optional identifier which can be used to reference the object elsewhere in the BOM. + Uniqueness is enforced within all elements and children of the root-level bom element. + + + + + + User-defined attributes may be used on this element as long as they + do not have the same name as an existing attribute used by the schema. + + + + @@ -8430,6 +8479,11 @@ limitations under the License. + + + A list of attributions indicating which entity supplied information for specific fields within the BOM. + + diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.json b/tools/src/test/resources/1.7/valid-citations-1.7.json new file mode 100644 index 00000000..e3e53e54 --- /dev/null +++ b/tools/src/test/resources/1.7/valid-citations-1.7.json @@ -0,0 +1,77 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.7", + "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79", + "version": 1, + "metadata": { + "timestamp": "2025-05-01T14:23:00Z", + "authors": [ + { + "bom-ref": "person-1", + "name": "Alice Example", + "email": "alice@example.com" + } + ] + }, + "components": [ + { + "type": "library", + "bom-ref": "component-1", + "name": "example-lib", + "version": "1.2.3", + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ] + } + ], + "citations": [ + { + "bom-ref": "citation-1", + "pointers": [ "/components/0/name" ], + "timestamp": "2025-05-01T14:00:00Z", + "attributedTo": "person-1", + "note": "Manually entered by Alice Example" + }, + { + "bom-ref": "citation-2", + "pointers": [ "/components/0/licenses/0/license/id" ], + "timestamp": "2025-05-01T14:05:00Z", + "attributedTo": "scan-tool-1", + "process": "task-license-scan", + "note": "Auto-detected by license scanner tool" + } + ], + "formulation": [ + { + "components": [ + { + "bom-ref": "scan-tool-1", + "type": "application", + "name": "My Scan Tool" + } + ], + "bom-ref": "workflow-1", + "workflows": [ + { + "bom-ref": "workflow-1", + "uid": "259bae74-5ec4-4de8-9386-c91b1f7719b8", + "name": "My workflow", + "tasks": [ + { + "bom-ref": "task-license-scan", + "uid": "6d75f8d6-a008-41cf-8b65-c4129fc249f9", + "taskTypes": [ "scan" ], + "description": "License scan of the source files using OpenSourceScanner v2.1" + } + ], + "taskTypes": [ "scan" ] + } + ] + } + ] +} diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.textproto b/tools/src/test/resources/1.7/valid-citations-1.7.textproto new file mode 100644 index 00000000..7062652a --- /dev/null +++ b/tools/src/test/resources/1.7/valid-citations-1.7.textproto @@ -0,0 +1,75 @@ +# proto-file: schema/bom-1.7.proto +# proto-message: Bom + +spec_version: "1.7" +version: 1 +serial_number: "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" + +metadata { + timestamp { + seconds: 1746118980 + nanos: 0 + } + authors { + bom_ref: "person-1" + name: "Alice Example" + email: "alice@example.com" + } +} + +components { + bom_ref: "component-1" + type: CLASSIFICATION_LIBRARY + name: "example-lib" + version: "1.2.3" + licenses { + license { + id: "Apache-2.0" + } + } +} + +citations [ + { + bom_ref: "citation-1" + pointer: "/components/0/name" + timestamp: { + seconds: 1746108000 + nanos: 0 + } + attributed_to: "person-1" + note: "Manually entered by Alice Example" + }, + { + bom_ref: "citation-2" + pointer: "/components/0/licenses/0/license/id" + timestamp: { + seconds: 1746108000 + nanos: 0 + } + attributed_to: "scan-tool-1" + process: "task-license-scan" + note: "Auto-detected by license scanner tool" + } +] + +formulation { + bom_ref: "workflow-1" + components { + bom_ref: "scan-tool-1" + type: CLASSIFICATION_APPLICATION + name: "My Scan Tool" + } + workflows { + bom_ref: "workflow-1" + uid: "259bae74-5ec4-4de8-9386-c91b1f7719b8" + name: "My workflow" + taskTypes: TASK_TYPE_SCAN + tasks { + bom_ref: "task-license-scan" + uid: "6d75f8d6-a008-41cf-8b65-c4129fc249f9" + taskTypes: TASK_TYPE_SCAN + description: "License scan of the source files using OpenSourceScanner v2.1" + } + } +} diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.xml b/tools/src/test/resources/1.7/valid-citations-1.7.xml new file mode 100644 index 00000000..8536b51c --- /dev/null +++ b/tools/src/test/resources/1.7/valid-citations-1.7.xml @@ -0,0 +1,71 @@ + + + + 2025-05-01T14:23:00Z + + + Alice Example + alice@example.com + + + + + + example-lib + 1.2.3 + + + Apache-2.0 + + + + + + + + + My Scan Tool + + + + + 259bae74-5ec4-4de8-9386-c91b1f7719b8 + My workflow + + + 6d75f8d6-a008-41cf-8b65-c4129fc249f9 + License scan of the source files using OpenSourceScanner v2.1 + + scan + + + + + scan + + + + + + + + + /components/0/name + + 2025-05-01T14:00:00Z + person-1 + Manually entered by Alice Example + + + + /components/0/licenses/0/license/id + + 2025-05-01T14:05:00Z + scan-tool-1 + task-license-scan + Auto-detected by license scanner tool + + + From 84f8e2e75fbabe50cebc4596c9bfcaf97afbad22 Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Thu, 1 May 2025 15:26:08 -0500 Subject: [PATCH 02/15] Corrected tests Signed-off-by: Steve Springett --- schema/bom-1.7.schema.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json index 1e4b5f8a..943288bc 100644 --- a/schema/bom-1.7.schema.json +++ b/schema/bom-1.7.schema.json @@ -519,7 +519,6 @@ }, "citations": { "type": "array", - "additionalItems": false, "items": {"$ref": "#/definitions/citation"}, "uniqueItems": true, "title": "Citations", @@ -5751,7 +5750,6 @@ }, "pointers": { "type": "array", - "additionalItems": false, "items": { "type": "string", "title": "Field Reference", From ec18e41d46d98e93cce47cc3323e8c1b77ad336f Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Thu, 1 May 2025 15:32:44 -0500 Subject: [PATCH 03/15] corrected pointer repeating Signed-off-by: Steve Springett --- schema/bom-1.7.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index f2c8adf7..38af0c72 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -2400,7 +2400,7 @@ message Citation { // Optional unique identifier for the citation optional string bom_ref = 1; // Field reference using JSON Pointer format - string pointer = 2; + repeated string pointer = 2; // Timestamp when the citation occurred google.protobuf.Timestamp timestamp = 3; // The entity (component, service, org, or person) that supplied the data (optional) From ddc4842f90fd23e98ca60496b11f63b3cee6b92c Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Thu, 1 May 2025 16:23:01 -0500 Subject: [PATCH 04/15] Added external ref for citation Signed-off-by: Steve Springett --- schema/bom-1.7.proto | 2 ++ schema/bom-1.7.schema.json | 2 ++ schema/bom-1.7.xsd | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index 38af0c72..f660498d 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -322,6 +322,8 @@ enum ExternalReferenceType { EXTERNAL_REFERENCE_TYPE_RFC_9116 = 41; // Reference to release notes EXTERNAL_REFERENCE_TYPE_RELEASE_NOTES = 42; + // A reference to external citations applicable to the object identified by this BOM entry or the BOM itself. When used with a BOM-Link, this allows offloading citations into a separate CycloneDX BOM. + EXTERNAL_REFERENCE_TYPE_CITATION = 43; } enum HashAlg { diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json index 943288bc..d5667bf5 100644 --- a/schema/bom-1.7.schema.json +++ b/schema/bom-1.7.schema.json @@ -1812,6 +1812,7 @@ "electronic-signature", "digital-signature", "rfc-9116", + "citation", "other" ], "meta:enum": { @@ -1857,6 +1858,7 @@ "electronic-signature": "An e-signature is commonly a scanned representation of a written signature or a stylized script of the person's name.", "digital-signature": "A signature that leverages cryptography, typically public/private key pairs, which provides strong authenticity verification.", "rfc-9116": "Document that complies with [RFC 9116](https://www.ietf.org/rfc/rfc9116.html) (A File Format to Aid in Security Vulnerability Disclosure)", + "citation": "A reference to external citations applicable to the object identified by this BOM entry or the BOM itself. When used with a BOM-Link, this allows offloading citations into a separate CycloneDX BOM.", "other": "Use this if no other types accurately describe the purpose of the external reference." } }, diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 3c3ddf0f..1a565916 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -1578,6 +1578,11 @@ limitations under the License. Document that complies with RFC-9116 (A File Format to Aid in Security Vulnerability Disclosure) + + + A reference to external citations applicable to the object identified by this BOM entry or the BOM itself. When used with a BOM-Link, this allows offloading citations into a separate CycloneDX BOM. + + Use this if no other types accurately describe the purpose of the external reference From 7dba14f42db5634178777226fc2c33fffa57d10e Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Tue, 20 May 2025 11:30:55 +0200 Subject: [PATCH 05/15] docs: annotations Signed-off-by: Jan Kowalleck --- schema/bom-1.7.proto | 10 +++++----- schema/bom-1.7.xsd | 45 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index f660498d..9af2dcb9 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -2401,14 +2401,14 @@ message CryptoProperties { message Citation { // Optional unique identifier for the citation optional string bom_ref = 1; - // Field reference using JSON Pointer format + // One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. repeated string pointer = 2; - // Timestamp when the citation occurred + // Timestamp when the attribution was made or the information was supplied. google.protobuf.Timestamp timestamp = 3; - // The entity (component, service, org, or person) that supplied the data (optional) + // The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. optional string attributed_to = 4; - // The process (workflow/formula/task) that generated the data (optional) + // An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. optional string process = 5; - // Optional human-readable note + // An optional description or comment about the context or quality of the data attribution. optional string note = 6; } diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 1a565916..6ec52e46 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8369,16 +8369,51 @@ limitations under the License. + + + One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. + + - + + + + A JSON Pointer(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations. + + + - - - - + + + + The date and time when the attribution was made or the information was supplied. + + + + + + + The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. + + + + + + + An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + + + + + + + An optional description or comment about the context or quality of the data attribution. + + + From a3d7d0164c37842ab7f2a200dc2eb92a8c8b586b Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Tue, 1 Jul 2025 22:13:58 -0500 Subject: [PATCH 06/15] Added explicit documentation in XSD and Proto that either attributedTo or process (or both) are required. Added invalid JSON test case. Signed-off-by: Steve Springett --- schema/bom-1.7.proto | 5 ++- schema/bom-1.7.xsd | 7 ++++ .../resources/1.7/invalid-citations-1.7.json | 39 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tools/src/test/resources/1.7/invalid-citations-1.7.json diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index 9af2dcb9..39ccecb5 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -2398,6 +2398,7 @@ message CryptoProperties { optional string oid = 6; } +// At least one of the "attributedTo" or "process" elements must be present. This is equivalent to the "anyOf" constraint in the JSON schema. message Citation { // Optional unique identifier for the citation optional string bom_ref = 1; @@ -2407,8 +2408,8 @@ message Citation { google.protobuf.Timestamp timestamp = 3; // The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. optional string attributed_to = 4; - // An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + // An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. At least one of the "attributedTo" or "process" elements must be present. optional string process = 5; - // An optional description or comment about the context or quality of the data attribution. + // An optional description or comment about the context or quality of the data attribution. At least one of the "attributedTo" or "process" elements must be present. optional string note = 6; } diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 6ec52e46..5de026e6 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8367,6 +8367,11 @@ limitations under the License. + + + At least one of the "attributedTo" or "process" elements must be present. This is equivalent to the "anyOf" constraint in the JSON schema. + + @@ -8397,6 +8402,7 @@ limitations under the License. The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. + At least one of "attributedTo" or "process" must be present. @@ -8404,6 +8410,7 @@ limitations under the License. An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + At least one of "attributedTo" or "process" must be present. diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.json b/tools/src/test/resources/1.7/invalid-citations-1.7.json new file mode 100644 index 00000000..3da52604 --- /dev/null +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.7", + "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79", + "version": 1, + "metadata": { + "timestamp": "2025-05-01T14:23:00Z" + }, + "components": [ + { + "type": "library", + "bom-ref": "component-1", + "name": "example-lib", + "version": "1.2.3", + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ] + } + ], + "citations": [ + { + "bom-ref": "citation-1", + "pointers": [ "/components/0/name" ], + "timestamp": "2025-05-01T14:00:00Z", + "note": "Manually entered by Alice Example" + }, + { + "bom-ref": "citation-2", + "pointers": [ "/components/0/licenses/0/license/id" ], + "timestamp": "2025-05-01T14:05:00Z", + "note": "Auto-detected by license scanner tool" + } + ] +} From abcc29d4581bc762b51aaffbd58b5953a1cf2909 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 3 Jul 2025 14:24:01 +0200 Subject: [PATCH 07/15] added additional test cases, and adjusted the XSD to detect them Signed-off-by: Jan Kowalleck --- schema/bom-1.7.xsd | 37 +++++--- .../resources/1.7/invalid-citations-1.7.json | 8 +- .../resources/1.7/invalid-citations-1.7.xml | 86 +++++++++++++++++++ .../resources/1.7/valid-citations-1.7.json | 11 ++- .../1.7/valid-citations-1.7.textproto | 12 ++- .../resources/1.7/valid-citations-1.7.xml | 12 ++- 6 files changed, 142 insertions(+), 24 deletions(-) create mode 100644 tools/src/test/resources/1.7/invalid-citations-1.7.xml diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 61f86a5f..32b4a225 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8905,22 +8905,35 @@ limitations under the License. - - - - The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. - At least one of "attributedTo" or "process" must be present. - - - - + - An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. - At least one of "attributedTo" or "process" must be present. + At least one of the "attributedTo" or "process" elements must be present. - + + + The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. + + + + + The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + + + + + + The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. + + + + + The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + + + + diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.json b/tools/src/test/resources/1.7/invalid-citations-1.7.json index 3da52604..f0f42f25 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.json +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.json @@ -27,13 +27,7 @@ "bom-ref": "citation-1", "pointers": [ "/components/0/name" ], "timestamp": "2025-05-01T14:00:00Z", - "note": "Manually entered by Alice Example" - }, - { - "bom-ref": "citation-2", - "pointers": [ "/components/0/licenses/0/license/id" ], - "timestamp": "2025-05-01T14:05:00Z", - "note": "Auto-detected by license scanner tool" + "note": "Should have at least one of the following property sets: property 'attributedTo' or property 'process'" } ] } diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.xml b/tools/src/test/resources/1.7/invalid-citations-1.7.xml new file mode 100644 index 00000000..1af9b2ab --- /dev/null +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.xml @@ -0,0 +1,86 @@ + + + + 2025-05-01T14:23:00Z + + + Alice Example + alice@example.com + + + + + + example-lib + 1.2.3 + + + Apache-2.0 + + + + + + + + + My Scan Tool + + + + + 259bae74-5ec4-4de8-9386-c91b1f7719b8 + My workflow + + + 6d75f8d6-a008-41cf-8b65-c4129fc249f9 + License scan of the source files using OpenSourceScanner v2.1 + + scan + + + + dfc0268a-89cb-4823-bb88-84115a06b64d + License scan of the source files using [REDACTED] + + scan + + + + + scan + + + + + + + + + /components/0/name + + 2025-05-01T14:00:00Z + Should have at least one of the following children 'attributedTo' or 'process' + + + + /components/0/licenses/0/license/id + + 2025-05-01T14:05:00Z + person-1 + scan-tool-1 + Should have at max one 'attributedTo' + + + + /components/0/licenses/0/license/id + + 2025-05-01T14:05:00Z + task-license-scan + task-license-scan-2 + Should have at max one 'process' + + + diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.json b/tools/src/test/resources/1.7/valid-citations-1.7.json index e3e53e54..03bd4451 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.json +++ b/tools/src/test/resources/1.7/valid-citations-1.7.json @@ -35,15 +35,22 @@ "pointers": [ "/components/0/name" ], "timestamp": "2025-05-01T14:00:00Z", "attributedTo": "person-1", - "note": "Manually entered by Alice Example" + "note": "Manually entered by Alice Example - with `attributedTo`" }, { "bom-ref": "citation-2", + "pointers": [ "/components/0/name" ], + "timestamp": "2025-05-01T14:00:00Z", + "process": "task-license-scan", + "note": "Semi-manually entered by Alice Example - with `process`" + }, + { + "bom-ref": "citation-3", "pointers": [ "/components/0/licenses/0/license/id" ], "timestamp": "2025-05-01T14:05:00Z", "attributedTo": "scan-tool-1", "process": "task-license-scan", - "note": "Auto-detected by license scanner tool" + "note": "Auto-detected by license scanner tool - with both, 'attributedTo' and 'process'" } ], "formulation": [ diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.textproto b/tools/src/test/resources/1.7/valid-citations-1.7.textproto index 7062652a..5a837aa4 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.textproto +++ b/tools/src/test/resources/1.7/valid-citations-1.7.textproto @@ -41,7 +41,17 @@ citations [ note: "Manually entered by Alice Example" }, { - bom_ref: "citation-2" + bom_ref: "citation-1" + pointer: "/components/0/name" + timestamp: { + seconds: 1746108000 + nanos: 0 + } + process: "task-license-scan" + note: "Semi-manually entered by Alice Example - with `process`" + }, + { + bom_ref: "citation-3" pointer: "/components/0/licenses/0/license/id" timestamp: { seconds: 1746108000 diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.xml b/tools/src/test/resources/1.7/valid-citations-1.7.xml index 8536b51c..de624716 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.xml +++ b/tools/src/test/resources/1.7/valid-citations-1.7.xml @@ -56,16 +56,24 @@ 2025-05-01T14:00:00Z person-1 - Manually entered by Alice Example + Manually entered by Alice Example - with `attributedTo` + + /components/0/name + + 2025-05-01T14:00:00Z + person-1 + Semi-manually entered by Alice Example - with `process` + + /components/0/licenses/0/license/id 2025-05-01T14:05:00Z scan-tool-1 task-license-scan - Auto-detected by license scanner tool + Auto-detected by license scanner tool - with both, 'attributedTo' and 'process' From 4a24b0756e61a8d7646c7185effe907225203129 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 3 Jul 2025 15:06:10 +0200 Subject: [PATCH 08/15] revert XSD improvements Signed-off-by: Jan Kowalleck --- schema/bom-1.7.xsd | 45 +++++++++---------- .../resources/1.7/invalid-citations-1.7.xml | 2 + 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 32b4a225..135b81ce 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8876,7 +8876,7 @@ limitations under the License. - At least one of the "attributedTo" or "process" elements must be present. This is equivalent to the "anyOf" constraint in the JSON schema. + At least one of the "attributedTo" or "process" elements must be present. @@ -8905,35 +8905,22 @@ limitations under the License. - + + The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. At least one of the "attributedTo" or "process" elements must be present. - - - The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. - - - - - The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. - - - - - - The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. - - - - - The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. - - - - + + + + + The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + At least one of the "attributedTo" or "process" elements must be present. + + + @@ -8949,6 +8936,14 @@ limitations under the License. + diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.xml b/tools/src/test/resources/1.7/invalid-citations-1.7.xml index 1af9b2ab..e628addd 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.xml +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.xml @@ -57,6 +57,7 @@ + /components/0/licenses/0/license/id From c486d31a20403641c0e5e16eb26cbd8585e77d8a Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 3 Jul 2025 15:08:15 +0200 Subject: [PATCH 09/15] docs Signed-off-by: Jan Kowalleck --- schema/bom-1.7.xsd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 135b81ce..03103591 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8939,8 +8939,8 @@ limitations under the License. From 0f225ad485bb4545d5ab6d6f6be487e331e55c4f Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 3 Jul 2025 15:10:18 +0200 Subject: [PATCH 10/15] docs Signed-off-by: Jan Kowalleck --- schema/bom-1.7.xsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 03103591..d39715f1 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8876,7 +8876,7 @@ limitations under the License. - At least one of the "attributedTo" or "process" elements must be present. + At least one of the "attributedTo" or "process" elements must be present. This is equivalent to the "anyOf" constraint in the JSON schema. From f315e00ccc4b370414aec4fc6cf6dc86cdd354d6 Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Mon, 4 Aug 2025 21:48:52 -0500 Subject: [PATCH 11/15] Added expressions - JSONPath and XPath as an alternative to JSON Pointer. Updated formulation description. Updated test cases. Signed-off-by: Steve Springett --- schema/bom-1.7.proto | 14 ++-- schema/bom-1.7.schema.json | 21 ++++- schema/bom-1.7.xsd | 79 +++++++++++++------ .../resources/1.7/invalid-citations-1.7.json | 7 ++ .../resources/1.7/invalid-citations-1.7.xml | 11 +++ .../resources/1.7/valid-citations-1.7.json | 2 +- .../1.7/valid-citations-1.7.textproto | 2 +- .../resources/1.7/valid-citations-1.7.xml | 6 +- 8 files changed, 102 insertions(+), 40 deletions(-) diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index 1730dc6b..908a7cbe 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -37,7 +37,7 @@ message Bom { repeated Annotation annotations = 11; // Specifies optional, custom, properties repeated Property properties = 12; - // Describes how a component or service was manufactured or deployed. This is achieved through the use of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the observed formulas describing the steps which transpired in the manufacturing process. + // Describes the formulation of any referencable object within the BOM, including components, services, metadata, declarations, or the BOM itself. This may encompass how the object was created, assembled, deployed, tested, certified, or otherwise brought into its present form. Common examples include software build pipelines, deployment processes, AI/ML model training, cryptographic key generation or certification, and third-party audits. Processes are modeled using declared and observed formulas, composed of workflows, tasks, and individual steps. repeated Formula formulation = 13; // The list of declarations which describe the conformance to standards. Each declaration may include attestations, claims, and evidence. repeated Declarations declarations = 14; @@ -315,7 +315,7 @@ enum ExternalReferenceType { EXTERNAL_REFERENCE_TYPE_CONFIGURATION = 35; // Information used to substantiate a claim. EXTERNAL_REFERENCE_TYPE_EVIDENCE = 36; - // Describes how a component or service was manufactured or deployed. + // Describes the formulation of any referencable object within the BOM, including components, services, metadata, declarations, or the BOM itself. EXTERNAL_REFERENCE_TYPE_FORMULATION = 37; // The location where the source code distributable can be obtained. This is often an archive format such as zip or tar.gz. The source-distribution type complements the use of the version control (vcs) type. EXTERNAL_REFERENCE_TYPE_SOURCE_DISTRIBUTION = 38; @@ -2624,12 +2624,14 @@ message Citation { optional string bom_ref = 1; // One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. repeated string pointer = 2; + // Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. Implementers shall ensure the expression is valid within the context of the applicable serialisation format. Use either "pointer" or "expression" but not both in this object. + repeated string expression = 3; // Timestamp when the attribution was made or the information was supplied. - google.protobuf.Timestamp timestamp = 3; + google.protobuf.Timestamp timestamp = 4; // The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. - optional string attributed_to = 4; + optional string attributed_to = 5; // An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. At least one of the "attributedTo" or "process" elements must be present. - optional string process = 5; + optional string process = 6; // An optional description or comment about the context or quality of the data attribution. At least one of the "attributedTo" or "process" elements must be present. - optional string note = 6; + optional string note = 7; } diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json index 3085013a..3045bb55 100644 --- a/schema/bom-1.7.schema.json +++ b/schema/bom-1.7.schema.json @@ -100,7 +100,7 @@ "items": {"$ref": "#/definitions/formula"}, "uniqueItems": true, "title": "Formulation", - "description": "Describes how a component or service was manufactured or deployed. This is achieved through the use of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the observed formulas describing the steps which transpired in the manufacturing process." + "description": "Describes the formulation of any referencable object within the BOM, including components, services, metadata, declarations, or the BOM itself. This may encompass how the object was created, assembled, deployed, tested, certified, or otherwise brought into its present form. Common examples include software build pipelines, deployment processes, AI/ML model training, cryptographic key generation or certification, and third-party audits. Processes are modeled using declared and observed formulas, composed of workflows, tasks, and individual steps." }, "declarations": { "type": "object", @@ -1932,7 +1932,7 @@ "log": "A record of events that occurred in a computer system or application, such as problems, errors, or information on current operations.", "configuration": "Parameters or settings that may be used by other components or services.", "evidence": "Information used to substantiate a claim.", - "formulation": "Describes how a component or service was manufactured or deployed.", + "formulation": "Describes the formulation of any referencable object within the BOM, including components, services, metadata, declarations, or the BOM itself.", "attestation": "Human or machine-readable statements containing facts, evidence, or testimony.", "threat-model": "An enumeration of identified weaknesses, threats, and countermeasures, dataflow diagram (DFD), attack tree, and other supporting documentation in human-readable or machine-readable format.", "adversary-model": "The defined assumptions, goals, and capabilities of an adversary.", @@ -6140,6 +6140,17 @@ "title": "Field References", "description": "One or more [JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies." }, + "expressions": { + "type": "array", + "items": { + "type": "string", + "title": "Path Expression", + "description": "Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. Implementers shall ensure the expression is valid within the context of the applicable serialisation format." + }, + "minItems": 1, + "title": "Path Expressions", + "description": "One or more path expressions used to locate values within a BOM." + }, "timestamp": { "type": "string", "format": "date-time", @@ -6162,10 +6173,14 @@ "description": "An optional digital signature verifying the authenticity or integrity of the attribution." } }, - "required": ["pointers", "timestamp"], + "required": ["timestamp"], "anyOf": [ { "required": ["attributedTo"] }, { "required": ["process"] } + ], + "oneOf": [ + { "required": ["pointers"] }, + { "required": ["expressions"] } ] } } diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index d39715f1..360df96e 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -1669,7 +1669,7 @@ limitations under the License. - Describes how a component or service was manufactured or deployed. + Describes the formulation of any referencable object within the BOM, including components, services, metadata, declarations, or the BOM itself. @@ -5218,9 +5218,13 @@ limitations under the License. - Describes how a component or service was manufactured or deployed. This is achieved through the use - of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the - observed formulas describing the steps which transpired in the manufacturing process. + Describes the formulation of any referencable object within the BOM, + including components, services, metadata, declarations, or the BOM itself. This may + encompass how the object was created, assembled, deployed, tested, certified, or otherwise + brought into its present form. Common examples include software build pipelines, + deployment processes, AI/ML model training, cryptographic key generation or certification, + and third-party audits. Processes are modeled using declared and observed formulas, + composed of workflows, tasks, and individual steps. @@ -8880,24 +8884,44 @@ limitations under the License. - - - - One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. - - - - - - - - A JSON Pointer(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations. - - - - - - + + + + + One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. + + + + + + + + A JSON Pointer(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations. + + + + + + + + + + One or more path expressions used to locate values within a BOM. + + + + + + + + Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. Implementers shall ensure the expression is valid within the context of the applicable serialisation format. + + + + + + + @@ -9020,10 +9044,13 @@ limitations under the License. - Describes how a component or service was manufactured or deployed. This is - achieved through the use of formulas, workflows, tasks, and steps, which declare the precise - steps to reproduce along with the observed formulas describing the steps which transpired - in the manufacturing process. + Describes the formulation of any referencable object within the BOM, + including components, services, metadata, declarations, or the BOM itself. This may + encompass how the object was created, assembled, deployed, tested, certified, or otherwise + brought into its present form. Common examples include software build pipelines, + deployment processes, AI/ML model training, cryptographic key generation or certification, + and third-party audits. Processes are modeled using declared and observed formulas, + composed of workflows, tasks, and individual steps. diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.json b/tools/src/test/resources/1.7/invalid-citations-1.7.json index f0f42f25..3ab39c44 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.json +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.json @@ -28,6 +28,13 @@ "pointers": [ "/components/0/name" ], "timestamp": "2025-05-01T14:00:00Z", "note": "Should have at least one of the following property sets: property 'attributedTo' or property 'process'" + }, + { + "bom-ref": "citation-1", + "pointers": [ "/components/0/name" ], + "expressions": [ "expression here" ], + "timestamp": "2025-05-01T14:00:00Z", + "note": "Should not have both a pointer and expression." } ] } diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.xml b/tools/src/test/resources/1.7/invalid-citations-1.7.xml index e628addd..cd09406d 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.xml +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.xml @@ -84,5 +84,16 @@ task-license-scan-2 Should have at max one 'process' + + + /components/0/licenses/0/license/id + + + expression here + + 2025-05-01T14:05:00Z + task-license-scan + Should not have both a pointer and expression. + diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.json b/tools/src/test/resources/1.7/valid-citations-1.7.json index 03bd4451..d46185b9 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.json +++ b/tools/src/test/resources/1.7/valid-citations-1.7.json @@ -46,7 +46,7 @@ }, { "bom-ref": "citation-3", - "pointers": [ "/components/0/licenses/0/license/id" ], + "expressions": [ "$.components[*].licenses[*].license.id" ], "timestamp": "2025-05-01T14:05:00Z", "attributedTo": "scan-tool-1", "process": "task-license-scan", diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.textproto b/tools/src/test/resources/1.7/valid-citations-1.7.textproto index 5a837aa4..24b2f9c7 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.textproto +++ b/tools/src/test/resources/1.7/valid-citations-1.7.textproto @@ -52,7 +52,7 @@ citations [ }, { bom_ref: "citation-3" - pointer: "/components/0/licenses/0/license/id" + expression: "$.components[*].licenses[*].license.id" timestamp: { seconds: 1746108000 nanos: 0 diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.xml b/tools/src/test/resources/1.7/valid-citations-1.7.xml index de624716..addc8190 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.xml +++ b/tools/src/test/resources/1.7/valid-citations-1.7.xml @@ -67,9 +67,9 @@ Semi-manually entered by Alice Example - with `process` - - /components/0/licenses/0/license/id - + + /components/component/licenses/license/id + 2025-05-01T14:05:00Z scan-tool-1 task-license-scan From 22f8b639b909a66582da3892c99da911fde7b8c0 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Tue, 5 Aug 2025 21:14:40 +0200 Subject: [PATCH 12/15] streamlined some docs Signed-off-by: Jan Kowalleck --- schema/bom-1.7.proto | 2 +- schema/bom-1.7.schema.json | 2 +- schema/bom-1.7.xsd | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index b84f2be5..ad2699f5 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -43,7 +43,7 @@ message Bom { repeated Declarations declarations = 14; // A collection of reusable objects that are defined and may be used elsewhere in the BOM. repeated Definition definitions = 15; - // Details a specific attribution of data within the BOM to a contributing entity or process. + // A collection of attributions indicating which entity supplied information for specific fields within the BOM. repeated Citation citations = 16; } diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json index 50742f25..fb34e2ad 100644 --- a/schema/bom-1.7.schema.json +++ b/schema/bom-1.7.schema.json @@ -532,7 +532,7 @@ "items": {"$ref": "#/definitions/citation"}, "uniqueItems": true, "title": "Citations", - "description": "A list of attributions indicating which entity supplied information for specific fields within the BOM." + "description": "A collection of attributions indicating which entity supplied information for specific fields within the BOM." }, "properties": { "type": "array", diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index b93dc949..6f734e13 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -9073,7 +9073,7 @@ limitations under the License. - A list of attributions indicating which entity supplied information for specific fields within the BOM. + A collection of attributions indicating which entity supplied information for specific fields within the BOM. From efbbbf411762d0bd8147cd4ef59f292470715060 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Tue, 5 Aug 2025 22:22:10 +0200 Subject: [PATCH 13/15] wip Signed-off-by: Jan Kowalleck --- schema/bom-1.7.proto | 34 ++++++++++++++----- schema/bom-1.7.schema.json | 20 +++++------ schema/bom-1.7.xsd | 16 ++++++--- .../1.7/invalid-citations-1.7.textproto | 23 +++++++++++++ .../1.7/valid-citations-1.7.textproto | 6 ++-- 5 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 tools/src/test/resources/1.7/invalid-citations-1.7.textproto diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto index ad2699f5..44d2ea74 100644 --- a/schema/bom-1.7.proto +++ b/schema/bom-1.7.proto @@ -2618,20 +2618,38 @@ enum PatentAssertionType { PATENT_ASSERTION_TYPE_RESEARCH_OR_EVALUATION = 8; } -// At least one of the "attributedTo" or "process" elements must be present. This is equivalent to the "anyOf" constraint in the JSON schema. +// Details a specific attribution of data within the BOM to a contributing entity or process. message Citation { + message Pointers { + // Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations. + // Must contain at least 1 item. + repeated string pointer = 1; + } + message Expressions { + // Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. + // Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. + // Implementers shall ensure the expression is valid within the context of the applicable serialisation format. Use either "pointer" or "expression" but not both in this object. + // Must contain at least 1 item. + repeated string expression = 1; + } + // Optional unique identifier for the citation optional string bom_ref = 1; - // One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. - repeated string pointer = 2; - // Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. Implementers shall ensure the expression is valid within the context of the applicable serialisation format. Use either "pointer" or "expression" but not both in this object. - repeated string expression = 3; + // Exactly one of the "pointers" or "expressions" elements must be present. + oneof target { + // One or more JSON Pointers(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies. + Pointers pointers = 2; + // One or more path expressions used to locate values within a BOM. + Expressions expressions = 3; + } // Timestamp when the attribution was made or the information was supplied. google.protobuf.Timestamp timestamp = 4; - // The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. + // The `bom-ref` of an object, such as a component, service, tool, organisational entity, or person that supplied the cited information. + // At least one of the "attributed_to" or "process" elements must be present. optional string attributed_to = 5; - // An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. At least one of the "attributedTo" or "process" elements must be present. + // The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data. + // At least one of the "attributed_to" or "process" elements must be present. optional string process = 6; - // An optional description or comment about the context or quality of the data attribution. At least one of the "attributedTo" or "process" elements must be present. + // An optional description or comment about the context or quality of the data attribution. optional string note = 7; } diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json index fb34e2ad..a682e76c 100644 --- a/schema/bom-1.7.schema.json +++ b/schema/bom-1.7.schema.json @@ -6125,32 +6125,27 @@ "$ref": "#/definitions/refType", "title": "BOM Reference" }, - "attributedTo": { - "$ref": "#/definitions/refLinkType", - "title": "Attributed To", - "description": "The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information." - }, "pointers": { "type": "array", "items": { "type": "string", "title": "Field Reference", - "description": "A [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations." + "description": "A [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies.\nUsers of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations." }, "minItems": 1, "title": "Field References", - "description": "One or more [JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies." + "description": "One or more [JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM fields to which the attribution applies.\nExactly one of the \"pointers\" or \"expressions\" elements must be present." }, "expressions": { "type": "array", "items": { "type": "string", "title": "Path Expression", - "description": "Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. Implementers shall ensure the expression is valid within the context of the applicable serialisation format." + "description": "Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation.\nUse [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified.\nImplementers shall ensure the expression is valid within the context of the applicable serialisation format." }, "minItems": 1, "title": "Path Expressions", - "description": "One or more path expressions used to locate values within a BOM." + "description": "One or more path expressions used to locate values within a BOM.\nExactly one of the \"pointers\" or \"expressions\" elements must be present." }, "timestamp": { "type": "string", @@ -6158,10 +6153,15 @@ "title": "Timestamp", "description": "The date and time when the attribution was made or the information was supplied." }, + "attributedTo": { + "$ref": "#/definitions/refLinkType", + "title": "Attributed To", + "description": "The `bom-ref` of an object, such as a component, service, tool, organisational entity, or person that supplied the cited information.\nAt least one of the \"attributedTo\" or \"process\" elements must be present." + }, "process": { "$ref": "#/definitions/refLinkType", "title": "Process Reference", - "description": "An optional `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data." + "description": "The `bom-ref` to a process (such as a formula, workflow, task, or step) defined in the `formulation` section that executed or generated the attributed data.\nAt least one of the \"attributedTo\" or \"process\" elements must be present." }, "note": { "type": "string", diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd index 6f734e13..9f8682c9 100644 --- a/schema/bom-1.7.xsd +++ b/schema/bom-1.7.xsd @@ -8883,10 +8883,15 @@ limitations under the License. - At least one of the "attributedTo" or "process" elements must be present. This is equivalent to the "anyOf" constraint in the JSON schema. + Details a specific attribution of data within the BOM to a contributing entity or process. + + + Exactly one of the "pointers" or "expressions" elements must be present. + + @@ -8899,7 +8904,8 @@ limitations under the License. - A JSON Pointer(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations. + A JSON Pointer(https://datatracker.ietf.org/doc/html/rfc6901) identifying the BOM field to which the attribution applies. + Users of other serialisation formats (e.g. XML) shall use the JSON Pointer format to ensure consistent field referencing across representations. @@ -8917,7 +8923,9 @@ limitations under the License. - Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. Implementers shall ensure the expression is valid within the context of the applicable serialisation format. + Specifies a path expression used to locate a value within a BOM. The expression syntax shall conform to the format of the BOM's serialisation. + Use [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) for JSON, [XPath](https://www.w3.org/TR/xpath/) for XML, and default to JSONPath for Protocol Buffers unless otherwise specified. + Implementers shall ensure the expression is valid within the context of the applicable serialisation format. @@ -8935,7 +8943,7 @@ limitations under the License. - The `bom-ref` of an object, such as a component, service, organisational entity, or person that supplied the cited information. + The `bom-ref` of an object, such as a component, service, tool, organisational entity, or person that supplied the cited information. At least one of the "attributedTo" or "process" elements must be present. diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.textproto b/tools/src/test/resources/1.7/invalid-citations-1.7.textproto new file mode 100644 index 00000000..29af5b98 --- /dev/null +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.textproto @@ -0,0 +1,23 @@ +# proto-file: schema/bom-1.7.proto +# proto-message: Bom + +spec_version: "1.7" +serial_number: "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" +version: 1 + +metadata { + timestamp { + seconds: 1754424907 + nanos: 0 + } +} + +components { + type: CLASSIFICATION_LIBRARY + bom_ref: "component-1" + name: "example-lib" + version: "1.2.3" + +} + +// continue here diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.textproto b/tools/src/test/resources/1.7/valid-citations-1.7.textproto index 24b2f9c7..65eaea36 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.textproto +++ b/tools/src/test/resources/1.7/valid-citations-1.7.textproto @@ -32,7 +32,7 @@ components { citations [ { bom_ref: "citation-1" - pointer: "/components/0/name" + pointers: { pointer: "/components/0/name" } timestamp: { seconds: 1746108000 nanos: 0 @@ -42,7 +42,7 @@ citations [ }, { bom_ref: "citation-1" - pointer: "/components/0/name" + pointers: { pointer: "/components/0/name" } timestamp: { seconds: 1746108000 nanos: 0 @@ -52,7 +52,7 @@ citations [ }, { bom_ref: "citation-3" - expression: "$.components[*].licenses[*].license.id" + expressions: { expression: "$.components[*].licenses[*].license.id" } timestamp: { seconds: 1746108000 nanos: 0 From 2bf3edc7a6b7a3ae613c1c0848f4b1d0105f26c4 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Wed, 6 Aug 2025 09:37:28 +0200 Subject: [PATCH 14/15] wip Signed-off-by: Jan Kowalleck --- .../resources/1.7/invalid-citations-1.7.json | 2 +- .../1.7/invalid-citations-1.7.textproto | 29 +++++++++++++++++-- .../resources/1.7/invalid-citations-1.7.xml | 2 +- .../resources/1.7/valid-citations-1.7.json | 7 +++++ .../1.7/valid-citations-1.7.textproto | 12 +++++++- .../resources/1.7/valid-citations-1.7.xml | 8 +++++ 6 files changed, 55 insertions(+), 5 deletions(-) diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.json b/tools/src/test/resources/1.7/invalid-citations-1.7.json index 3ab39c44..d93cb908 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.json +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.json @@ -32,7 +32,7 @@ { "bom-ref": "citation-1", "pointers": [ "/components/0/name" ], - "expressions": [ "expression here" ], + "expressions": [ "$..[?(@.bom-ref=='component-1')].version" ], "timestamp": "2025-05-01T14:00:00Z", "note": "Should not have both a pointer and expression." } diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.textproto b/tools/src/test/resources/1.7/invalid-citations-1.7.textproto index 29af5b98..4617b8f0 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.textproto +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.textproto @@ -17,7 +17,32 @@ components { bom_ref: "component-1" name: "example-lib" version: "1.2.3" - + licenses { + license { + id: "Apache-2.0" + } + } } -// continue here +## !! NO formal check possible +#citations { +# bom_ref: "citation-1" +# pointers: { pointer: "/components/0/name" } +# timestamp { +# seconds: 1746108000 +# nanos: 0 +# } +# note: "Should have at least one of the following property sets: property 'attributedTo' or property 'process'" +#} + + +citations { + bom_ref: "citation-1" + pointers: { pointer: "/components/0/name" } + expressions: { expression: "$..[?(bom_ref=='component-1')].version" } + timestamp { + seconds: 1746108000 + nanos: 0 + } + note: "Should not have both a pointer and expression." +} diff --git a/tools/src/test/resources/1.7/invalid-citations-1.7.xml b/tools/src/test/resources/1.7/invalid-citations-1.7.xml index cd09406d..55962ab3 100644 --- a/tools/src/test/resources/1.7/invalid-citations-1.7.xml +++ b/tools/src/test/resources/1.7/invalid-citations-1.7.xml @@ -89,7 +89,7 @@ /components/0/licenses/0/license/id - expression here + //*[@bom-ref='component-1']/version 2025-05-01T14:05:00Z task-license-scan diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.json b/tools/src/test/resources/1.7/valid-citations-1.7.json index d46185b9..010150d3 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.json +++ b/tools/src/test/resources/1.7/valid-citations-1.7.json @@ -46,6 +46,13 @@ }, { "bom-ref": "citation-3", + "expression": "$..[?(@.bom-ref=='component-1')].version", + "timestamp": "2025-05-01T14:00:00Z", + "process": "task-license-scan", + "note": "Semi-manually entered by Alice Example - with `process`" + }, + { + "bom-ref": "citation-4", "expressions": [ "$.components[*].licenses[*].license.id" ], "timestamp": "2025-05-01T14:05:00Z", "attributedTo": "scan-tool-1", diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.textproto b/tools/src/test/resources/1.7/valid-citations-1.7.textproto index 65eaea36..09d7c072 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.textproto +++ b/tools/src/test/resources/1.7/valid-citations-1.7.textproto @@ -41,7 +41,7 @@ citations [ note: "Manually entered by Alice Example" }, { - bom_ref: "citation-1" + bom_ref: "citation-2" pointers: { pointer: "/components/0/name" } timestamp: { seconds: 1746108000 @@ -52,6 +52,16 @@ citations [ }, { bom_ref: "citation-3" + expressions: { expression: "$..[?(bom_ref=='component-1')].version" } + timestamp: { + seconds: 1746108000 + nanos: 0 + } + process: "task-license-scan" + note: "Semi-manually entered by Alice Example - with `process`" + }, + { + bom_ref: "citation-4" expressions: { expression: "$.components[*].licenses[*].license.id" } timestamp: { seconds: 1746108000 diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.xml b/tools/src/test/resources/1.7/valid-citations-1.7.xml index addc8190..599784ba 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.xml +++ b/tools/src/test/resources/1.7/valid-citations-1.7.xml @@ -67,6 +67,14 @@ Semi-manually entered by Alice Example - with `process` + + //*[@bom-ref='component-1']/version + + 2025-05-01T14:00:00Z + person-1 + Semi-manually entered by Alice Example - with `process` + + /components/component/licenses/license/id From fd1a034bf36baa6b587ade5872fe7e3085eb1b1f Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Wed, 6 Aug 2025 10:16:11 +0200 Subject: [PATCH 15/15] tests Signed-off-by: Jan Kowalleck --- tools/src/test/resources/1.7/valid-citations-1.7.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/test/resources/1.7/valid-citations-1.7.json b/tools/src/test/resources/1.7/valid-citations-1.7.json index 010150d3..50a1dddf 100644 --- a/tools/src/test/resources/1.7/valid-citations-1.7.json +++ b/tools/src/test/resources/1.7/valid-citations-1.7.json @@ -46,7 +46,7 @@ }, { "bom-ref": "citation-3", - "expression": "$..[?(@.bom-ref=='component-1')].version", + "expressions": [ "$..[?(@.bom-ref=='component-1')].version" ], "timestamp": "2025-05-01T14:00:00Z", "process": "task-license-scan", "note": "Semi-manually entered by Alice Example - with `process`"