From d6d01f6b50b09a0f67d1ebf693a6b93313a3f4c7 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Sat, 10 May 2025 22:08:35 +1000 Subject: [PATCH 01/10] updated publisher spec Signed-off-by: Chris Langton --- contributors.md | 2 +- spec/publisher/openapi.json | 1266 ++++++++++++++++++++--------------- spec/publisher/openapi.yaml | 1121 +++++++++++++++++++++++++++++++ 3 files changed, 1842 insertions(+), 547 deletions(-) create mode 100644 spec/publisher/openapi.yaml diff --git a/contributors.md b/contributors.md index 5327a8b..4b6e8e2 100644 --- a/contributors.md +++ b/contributors.md @@ -9,6 +9,7 @@ work during our meetings and workshops. They are noted here in alphabetic order: * Anthony Harrison, APH10, United Kingdom * Olle E. Johansson, Project lead, Edvina AB, Sweden, oej@edvina.net +* Christopher Langton * Mark Symons * Paul Horton * Pavel Shukhman, Reliza, Canada, pavel@reliza.io @@ -16,4 +17,3 @@ work during our meetings and workshops. They are noted here in alphabetic order: * Steve Springett * Valerio Mulas * Viktor Peterson - diff --git a/spec/publisher/openapi.json b/spec/publisher/openapi.json index 261986d..3a06822 100644 --- a/spec/publisher/openapi.json +++ b/spec/publisher/openapi.json @@ -4,7 +4,7 @@ "info": { "title": "Transparency Exchange API", "summary": "Transparency Exchange API specification for consumers and publishers", - "description": "TBC", + "description": "The Transparency Exchange API (TEA) provides standardized access to software transparency artifacts such as SBOMs, VEX, VDR, and other attestations.", "contact": { "name": "TEA Working Group", "email": "TBC", @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://github.com/CycloneDX/transparency-exchange-api/blob/main/LICENSE" }, - "version": "0.0.2" + "version": "0.0.3" }, "servers": [ { @@ -25,7 +25,7 @@ "paths": { "/product/{tei_urn}": { "get": { - "description": "Returns the corresponding leafs for a given TEI URN", + "description": "Returns the corresponding releases for a given TEI URN", "operationId": "getTeaProduct", "parameters": [ { @@ -43,11 +43,9 @@ } } }, - "404": { "$ref": "#/components/responses/404-object-by-id-not-found" } - }, "tags": [ "TEA Product" @@ -158,7 +156,22 @@ "operationId": "listTeaProducts", "parameters": [ { - "$ref": "#/components/parameters/standard_pagination" + "$ref": "#/components/parameters/page-offset" + }, + { + "$ref": "#/components/parameters/page-size" + }, + { + "$ref": "#/components/parameters/purl" + }, + { + "$ref": "#/components/parameters/barcode" + }, + { + "$ref": "#/components/parameters/sku" + }, + { + "$ref": "#/components/parameters/vendor_uuid" } ], "responses": { @@ -172,8 +185,20 @@ } } }, - "$ref": "#/components/responses/standard_errors" - } + "400": { + "description": "Invalid request body", + "content": { + "application/json": {} + } + }, + "401": { "$ref": "#/components/responses/401-unauthorized" }, + "404": { + "$ref": "#/components/responses/404-object-by-id-not-found" + } + }, + "tags": [ + "TEA Product" + ] }, "post": { "description": "Create TEA Product entry for the supplied product identifier", @@ -203,6 +228,15 @@ "purl": { "type": "string", "description": "Package URL (PURL)" + }, + "tei_urns": { + "type": "array", + "items": { + "type": "string", + "description": "Transparency Exchange Identifier URN", + "pattern": "^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\\.-]+:.+$" + }, + "description": "List of TEI URNs associated with this product" } }, "required": [ @@ -223,7 +257,10 @@ "barcode": "123456789012", "sku": "PROD-001", "vendor_uuid": "123e4567-e89b-12d3-a456-426614174000", - "purl": "pkg:generic/example@1.0.0" + "purl": "pkg:generic/example@1.0.0", + "tei_urns": [ + "urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1" + ] } } } @@ -255,6 +292,12 @@ }, "purl": { "type": "string" + }, + "tei_urns": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -289,10 +332,10 @@ ] } }, - "/leaf": { + "/component": { "post": { - "description": "Create a new TEA Leaf entry", - "operationId": "createTeaLeaf", + "description": "Create a new TEA Component entry", + "operationId": "createTeaComponent", "requestBody": { "required": true, "content": { @@ -301,35 +344,37 @@ "type": "object", "properties": { "tea_product_identifier": { - "type": "string" - }, - "product_version": { - "type": "string" + "$ref": "#/components/schemas/type_uuid" }, - "release_date": { + "name": { "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" + "description": "Component name" }, - "pre_release": { - "type": "boolean" + "identifiers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/identifier" + }, + "description": "List of identifiers for the component" } }, "required": [ "tea_product_identifier", - "product_version", - "release_date", - "pre_release" + "name" ] }, "examples": { "basic": { - "summary": "Basic leaf creation", + "summary": "Basic component creation", "value": { "tea_product_identifier": "123e4567-e89b-12d3-a456-426614174000", - "product_version": "1.0.0", - "release_date": "2024-03-20T15:30:00Z", - "pre_release": false + "name": "Example Component", + "identifiers": [ + { + "idType": "purl", + "idValue": "pkg:maven/org.example/component@1.0.0" + } + ] } } } @@ -338,11 +383,11 @@ }, "responses": { "201": { - "description": "TEA Leaf created successfully", + "description": "TEA Component created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/tea_leaf" + "$ref": "#/components/schemas/tea_component" } } } @@ -359,7 +404,7 @@ } }, "tags": [ - "TEA Leaf" + "TEA Component" ], "security": [ { @@ -368,25 +413,32 @@ { "basicAuth": [] } - ] +] } }, - "/leaf/{tea_leaf_identifier}": { + "/component/{component_identifier}": { "get": { - "description": "Get the TEA Leaf that describes the Version of a Product", - "operationId": "getTeaLeaf", + "description": "Get information about a TEA Component", + "operationId": "getTeaComponent", "parameters": [ { - "$ref": "#/components/parameters/tea_leaf_identifier" + "name": "component_identifier", + "in": "path", + "required": true, + "description": "UUID of TEA Component in the TEA server", + "schema": { + "type": "string", + "format": "uuid" + } } ], "responses": { "200": { - "description": "Requested TEA Leaf found and returned", + "description": "Requested TEA Component found and returned", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/tea_leaf" + "$ref": "#/components/schemas/tea_component" } } } @@ -396,15 +448,22 @@ } }, "tags": [ - "TEA Leaf" + "TEA Component" ] }, "patch": { - "description": "Update an existing TEA Leaf entry", - "operationId": "updateTeaLeaf", + "description": "Update an existing TEA Component entry", + "operationId": "updateTeaComponent", "parameters": [ { - "$ref": "#/components/parameters/tea_leaf_identifier" + "name": "component_identifier", + "in": "path", + "required": true, + "description": "UUID of TEA Component in the TEA server", + "schema": { + "type": "string", + "format": "uuid" + } } ], "requestBody": { @@ -414,19 +473,16 @@ "schema": { "type": "object", "properties": { - "product_name": { - "type": "string" - }, - "product_version": { - "type": "string" - }, - "release_date": { + "name": { "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" + "description": "Component name" }, - "pre_release": { - "type": "boolean" + "identifiers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/identifier" + }, + "description": "List of identifiers for the component" } } } @@ -435,11 +491,11 @@ }, "responses": { "200": { - "description": "TEA Leaf updated successfully", + "description": "TEA Component updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/tea_leaf" + "$ref": "#/components/schemas/tea_component" } } } @@ -456,7 +512,7 @@ } }, "tags": [ - "TEA Leaf" + "TEA Component" ], "security": [ { @@ -468,23 +524,30 @@ ] }, "delete": { - "description": "Delete a TEA Leaf entry", - "operationId": "deleteTeaLeaf", + "description": "Delete a TEA Component entry", + "operationId": "deleteTeaComponent", "parameters": [ { - "$ref": "#/components/parameters/tea_leaf_identifier" + "name": "component_identifier", + "in": "path", + "required": true, + "description": "UUID of TEA Component in the TEA server", + "schema": { + "type": "string", + "format": "uuid" + } } ], "$ref": "#/components/operations/standard_delete", "tags": [ - "TEA Leaf" + "TEA Component" ] } }, - "/collection": { + "/release": { "post": { - "description": "Create a new TEA Collection", - "operationId": "createTeaCollection", + "description": "Create a new TEA Release", + "operationId": "createTeaRelease", "requestBody": { "required": true, "content": { @@ -492,146 +555,50 @@ "schema": { "type": "object", "properties": { - "tea_leaf_identifier": { - "$ref": "#/components/schemas/type_uuid" - }, - "product_name": { - "type": "string" + "component_identifier": { + "$ref": "#/components/schemas/type_uuid", + "description": "UUID of the TEA Component" }, - "product_version": { - "type": "string" + "version": { + "type": "string", + "description": "Version number" }, "release_date": { "type": "string", "format": "date-time", - "example": "2024-03-20T15:30:00Z" - }, - "author": { - "$ref": "#/components/schemas/type_author" + "example": "2024-03-20T15:30:00Z", + "description": "Timestamp of the release" }, - "reason": { - "$ref": "#/components/schemas/type_collection_reason" + "pre_release": { + "type": "boolean", + "description": "Flag indicating pre-release status" }, - "artifacts": { + "identifiers": { "type": "array", "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/type_tea_collection_artifact_type" - }, - "author": { - "$ref": "#/components/schemas/type_author" - }, - "objects": { - "type": "array", - "items": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "mime_type": { - "type": "string" - }, - "artifact_url": { - "type": "string", - "format": "uri" - }, - "artifact_size_in_bytes": { - "type": "integer", - "format": "int64" - }, - "artifact_checksum": { - "type": "string", - "description": "The checksum value" - }, - "artifact_checksum_type": { - "type": "string", - "description": "The algorithm used to generate the checksum", - "enum": [ - "SHA512", - "SHA384", - "SHA256", - "SHA224", - "SHA1", - "MD5", - "BLAKE2b-512", - "BLAKE2s-256", - "BLAKE3" - ], - "default": "SHA256" - }, - "signature_url": { - "type": "string", - "format": "uri" - } - }, - "required": [ - "description", - "mime_type", - "artifact_url", - "artifact_size_in_bytes", - "artifact_checksum", - "artifact_checksum_type" - ] - } - } - }, - "required": [ - "name", - "type", - "author", - "objects" - ] - } + "$ref": "#/components/schemas/identifier" + }, + "description": "List of identifiers for the release" } }, "required": [ - "tea_leaf_identifier", - "product_name", - "product_version", - "release_date", - "author", - "reason" + "component_identifier", + "version", + "release_date" ] }, "examples": { "basic": { - "summary": "Basic collection creation", + "summary": "Basic release creation", "value": { - "tea_leaf_identifier": "123e4567-e89b-12d3-a456-426614174000", - "product_name": "Example Product", - "product_version": "1.0.0", + "component_identifier": "123e4567-e89b-12d3-a456-426614174000", + "version": "1.0.0", "release_date": "2024-03-20T15:30:00Z", - "author": { - "name": "John Doe", - "email": "john.doe@example.com", - "organization": "Example Org" - }, - "reason": "New Product Release", - "artifacts": [ + "pre_release": false, + "identifiers": [ { - "name": "Example Artifact", - "type": "bom", - "author": { - "name": "John Doe", - "email": "john.doe@example.com", - "organization": "Example Org" - }, - "objects": [ - { - "description": "Example SBOM", - "mime_type": "application/json", - "artifact_url": "https://example.com/sbom.json", - "artifact_size_in_bytes": 1024, - "artifact_checksum": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "artifact_checksum_type": "SHA256" - } - ] + "idType": "purl", + "idValue": "pkg:maven/org.example/component@1.0.0" } ] } @@ -642,17 +609,17 @@ }, "responses": { "201": { - "description": "TEA Collection created successfully", + "description": "TEA Release created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/tea_collection" + "$ref": "#/components/schemas/tea_release" } } } }, "400": { - "description": "Invalid request body", + "description": "Invalid parameters", "content": { "application/json": {} } @@ -663,7 +630,7 @@ } }, "tags": [ - "TEA Collection" + "TEA Release" ], "security": [ { @@ -675,22 +642,29 @@ ] } }, - "/collection/{tea_collection_identifier}": { + "/release/{release_identifier}": { "get": { - "description": "Get a TEA Collection by it's Identifier", - "operationId": "getTeaCollection", + "description": "Get information about a TEA Release", + "operationId": "getTeaRelease", "parameters": [ { - "$ref": "#/components/parameters/tea_collection_identifier" + "name": "release_identifier", + "in": "path", + "required": true, + "description": "UUID of TEA Release in the TEA server", + "schema": { + "type": "string", + "format": "uuid" + } } ], "responses": { "200": { - "description": "Requested TEA Collection found and returned", + "description": "Requested TEA Release found and returned", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/tea_collection" + "$ref": "#/components/schemas/tea_release" } } } @@ -700,15 +674,22 @@ } }, "tags": [ - "TEA Collection" + "TEA Release" ] }, "patch": { - "description": "Update an existing TEA Collection", - "operationId": "updateTeaCollection", + "description": "Update an existing TEA Release entry", + "operationId": "updateTeaRelease", "parameters": [ { - "$ref": "#/components/parameters/tea_collection_identifier" + "name": "release_identifier", + "in": "path", + "required": true, + "description": "UUID of TEA Release in the TEA server", + "schema": { + "type": "string", + "format": "uuid" + } } ], "requestBody": { @@ -718,22 +699,103 @@ "schema": { "type": "object", "properties": { - "product_name": { - "type": "string" - }, - "product_version": { - "type": "string" + "version": { + "type": "string", + "description": "Version number" }, "release_date": { "type": "string", "format": "date-time", "example": "2024-03-20T15:30:00Z" }, - "author": { - "$ref": "#/components/schemas/type_author" + "pre_release": { + "type": "boolean", + "description": "May only be set to false if previously true" + }, + "identifiers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/identifier" + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "TEA Release updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/tea_release" + } + } + } + }, + "400": { + "description": "Invalid request body", + "content": { + "application/json": {} + } + }, + "401": { "$ref": "#/components/responses/401-unauthorized" }, + "404": { + "$ref": "#/components/responses/404-object-by-id-not-found" + } + }, + "tags": [ + "TEA Release" + ], + "security": [ + { + "bearerAuth": [] + }, + { + "basicAuth": [] + } + ] + }, + "delete": { + "description": "Delete a TEA Release entry", + "operationId": "deleteTeaRelease", + "parameters": [ + { + "name": "release_identifier", + "in": "path", + "required": true, + "description": "UUID of TEA Release in the TEA server", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "$ref": "#/components/operations/standard_delete", + "tags": [ + "TEA Release" + ] + } + }, + "/collection": { + "post": { + "description": "Create a new TEA Collection", + "operationId": "createTeaCollection", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "release_identifier": { + "$ref": "#/components/schemas/type_uuid", + "description": "UUID of the TEA Release" }, - "reason": { - "$ref": "#/components/schemas/type_collection_reason" + "update_reason": { + "$ref": "#/components/schemas/collection_update_reason", + "description": "Reason for collection creation or update" }, "artifacts": { "type": "array", @@ -741,56 +803,51 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Artifact name" }, "type": { - "$ref": "#/components/schemas/type_tea_collection_artifact_type" + "$ref": "#/components/schemas/type_tea_collection_artifact_type", + "description": "Type of artifact" }, "author": { - "$ref": "#/components/schemas/type_author" + "$ref": "#/components/schemas/type_author", + "description": "Author of the artifact" }, - "objects": { + "formats": { "type": "array", "items": { "type": "object", "properties": { "description": { - "type": "string" + "type": "string", + "description": "A free text describing the artifact" }, "mime_type": { - "type": "string" + "type": "string", + "description": "The MIME type of the document" }, "artifact_url": { "type": "string", - "format": "uri" + "format": "uri", + "description": "Direct download URL for the artifact" }, "artifact_size_in_bytes": { "type": "integer", - "format": "int64" - }, - "artifact_checksum": { - "type": "string", - "description": "The checksum value" + "format": "int64", + "description": "Size of the artifact in bytes" }, - "artifact_checksum_type": { - "type": "string", - "description": "The algorithm used to generate the checksum", - "enum": [ - "SHA512", - "SHA384", - "SHA256", - "SHA224", - "SHA1", - "MD5", - "BLAKE2b-512", - "BLAKE2s-256", - "BLAKE3" - ], - "default": "SHA256" + "artifact_checksums": { + "type": "array", + "items": { + "$ref": "#/components/schemas/artifact_checksum" + }, + "description": "List of checksums for the artifact" }, "signature_url": { "type": "string", - "format": "uri" + "format": "uri", + "description": "URL for an external signature of the artifact" } }, "required": [ @@ -798,8 +855,7 @@ "mime_type", "artifact_url", "artifact_size_in_bytes", - "artifact_checksum", - "artifact_checksum_type" + "artifact_checksums" ] } } @@ -808,25 +864,60 @@ "name", "type", "author", - "objects" + "formats" ] } } }, "required": [ - "product_name", - "product_version", - "release_date", - "author", - "reason" + "release_identifier", + "update_reason" ] + }, + "examples": { + "basic": { + "summary": "Basic collection creation", + "value": { + "release_identifier": "123e4567-e89b-12d3-a456-426614174000", + "update_reason": { + "type": "INITIAL_RELEASE", + "comment": "Initial release of collection" + }, + "artifacts": [ + { + "name": "Example SBOM", + "type": "bom", + "author": { + "name": "John Doe", + "email": "john.doe@example.com", + "organization": "Example Org" + }, + "formats": [ + { + "description": "CycloneDX SBOM (XML)", + "mime_type": "application/vnd.cyclonedx+xml", + "artifact_url": "https://example.com/sbom.xml", + "artifact_size_in_bytes": 1024, + "artifact_checksums": [ + { + "algType": "SHA-256", + "algValue": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3" + } + ], + "signature_url": "https://example.com/sbom.xml.sig" + } + ] + } + ] + } + } } } } }, "responses": { - "200": { - "description": "TEA Collection updated successfully", + "201": { + "description": "TEA Collection created successfully", "content": { "application/json": { "schema": { @@ -857,11 +948,40 @@ "basicAuth": [] } ] - }, - "delete": { - "description": "Delete a TEA Collection entry", - "operationId": "deleteTeaCollection", - "parameters": [ + } + }, + "/collection/{collection_identifier}": { + "get": { + "description": "Get a TEA Collection by its Identifier", + "operationId": "getTeaCollection", + "parameters": [ + { + "$ref": "#/components/parameters/tea_collection_identifier" + } + ], + "responses": { + "200": { + "description": "Requested TEA Collection found and returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/tea_collection" + } + } + } + }, + "404": { + "$ref": "#/components/responses/404-object-by-id-not-found" + } + }, + "tags": [ + "TEA Collection" + ] + }, + "delete": { + "description": "Delete a TEA Collection entry", + "operationId": "deleteTeaCollection", + "parameters": [ { "$ref": "#/components/parameters/tea_collection_identifier" } @@ -871,275 +991,380 @@ "TEA Collection" ] } + }, + "/collection/{collection_identifier}/{version}": { + "get": { + "description": "Get a specific version of a TEA Collection", + "operationId": "getTeaCollectionVersion", + "parameters": [ + { + "$ref": "#/components/parameters/tea_collection_identifier" + }, + { + "name": "version", + "in": "path", + "required": true, + "description": "Version of the TEA Collection", + "schema": { + "type": "integer", + "minimum": 1 + } + } + ], + "responses": { + "200": { + "description": "Requested TEA Collection version found and returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/tea_collection" + } + } + } + }, + "404": { + "$ref": "#/components/responses/404-object-by-id-not-found" + } + }, + "tags": [ + "TEA Collection" + ] + } } }, - "webhooks": {}, "components": { "schemas": { - "base_product_fields": { + "identifier": { "type": "object", + "description": "An identifier with a specified type", "properties": { - "product_name": { - "type": "string" - }, - "barcode": { + "idType": { + "description": "Type of identifier, e.g. `tei`, `purl`, `cpe`", "type": "string", - "description": "Barcode" + "enum": [ + "cpe", + "tei", + "purl" + ] }, - "sku": { + "idValue": { + "description": "Identifier value", + "type": "string" + } + }, + "required": [ + "idType", + "idValue" + ] + }, + "artifact_checksum": { + "type": "object", + "properties": { + "algType": { + "description": "Checksum algorithm", "type": "string", - "description": "Product SKU" + "enum": [ + "MD5", + "SHA-1", + "SHA-256", + "SHA-384", + "SHA-512", + "SHA3-256", + "SHA3-384", + "SHA3-512", + "BLAKE2b-256", + "BLAKE2b-384", + "BLAKE2b-512", + "BLAKE3" + ] }, - "vendor_uuid": { + "algValue": { + "type": "string", + "description": "Checksum value" + } + }, + "required": [ + "algType", + "algValue" + ] + }, + "tea_product": { + "type": "object", + "properties": { + "identifier": { "$ref": "#/components/schemas/type_uuid", - "description": "Vendor UUID" + "description": "A unique identifier for the TEA product" }, - "purl": { + "name": { "type": "string", - "description": "Package URL (PURL)" + "description": "Product name" + }, + "identifiers": { + "type": "array", + "description": "List of identifiers for the product", + "items": { + "$ref": "#/components/schemas/identifier" + } + }, + "components": { + "type": "array", + "description": "List of TEA component UUIDs", + "items": { + "$ref": "#/components/schemas/type_uuid" + } + }, + "tei_urns": { + "type": "array", + "items": { + "type": "string", + "description": "Transparency Exchange Identifier URN", + "pattern": "^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\\.-]+:.+$" + }, + "description": "List of TEI URNs associated with this product" } - } + }, + "required": [ + "identifier", + "name", + "identifiers", + "components" + ] }, - "base_versioned_product": { + "paginated_product_list": { "allOf": [ - { "$ref": "#/components/schemas/base_product_fields" }, + { + "$ref": "#/components/schemas/pagination_details" + }, { "type": "object", "properties": { - "product_version": { - "type": "string" - }, - "release_date": { - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tea_product" + } } } } ] }, - "base_artifact_object": { + "tea_component": { "type": "object", + "description": "A TEA component", "properties": { - "identifier": { + "uuid": { + "description": "A unique identifier for the TEA component", "$ref": "#/components/schemas/type_uuid" }, - "description": { - "type": "string" - }, - "mime_type": { - "type": "string" - }, - "artifact_url": { + "name": { "type": "string", - "format": "uri" + "description": "Component name" }, - "artifact_size_in_bytes": { - "type": "integer", - "format": "int64" + "identifiers": { + "type": "array", + "description": "List of identifiers for the component", + "items": { + "$ref": "#/components/schemas/identifier" + } + }, + "releases": { + "type": "array", + "description": "List of UUIDs referencing TEA Release entries", + "items": { + "$ref": "#/components/schemas/type_uuid" + } + } + }, + "required": [ + "uuid", + "name", + "identifiers" + ] + }, + "tea_release": { + "type": "object", + "description": "A TEA release", + "properties": { + "uuid": { + "description": "A unique identifier for the TEA Component Release", + "$ref": "#/components/schemas/type_uuid" }, - "artifact_checksum": { + "version": { + "description": "Version number", "type": "string", - "description": "The checksum value" + "example": "1.2.3" }, - "artifact_checksum_type": { + "releaseDate": { + "description": "Timestamp of the release (for sorting purposes)", "type": "string", - "description": "The algorithm used to generate the checksum", - "enum": [ - "SHA512", - "SHA384", - "SHA256", - "SHA224", - "SHA1", - "MD5", - "BLAKE2b-512", - "BLAKE2s-256", - "BLAKE3" - ], - "default": "SHA256" - } - } - }, - "tea_product": { - "allOf": [ - { "$ref": "#/components/schemas/base_product_fields" }, - { - "type": "object", - "properties": { - "identifier": { - "$ref": "#/components/schemas/type_uuid" - }, - "leaf_references": { - "type": "array", - "items": { - "$ref": "#/components/schemas/type_uuid" - }, - "description": "Array of UUIDs referencing TEA Leaf entries" - } + "format": "date-time", + "example": "2024-03-20T15:30:00Z" + }, + "preRelease": { + "type": "boolean", + "description": "A flag indicating pre-release (or beta) status" + }, + "identifiers": { + "type": "array", + "description": "List of identifiers for the component", + "items": { + "$ref": "#/components/schemas/identifier" + } + }, + "collection_references": { + "type": "array", + "items": { + "$ref": "#/components/schemas/type_uuid" }, - "required": ["identifier", "product_name"] + "description": "Array of UUIDs referencing TEA Collection entries", + "default": [] } + }, + "required": [ + "uuid", + "version", + "releaseDate" ] }, - "tea_leaf": { - "allOf": [ - { "$ref": "#/components/schemas/base_versioned_product" }, - { - "type": "object", - "properties": { - "identifier": { - "$ref": "#/components/schemas/type_uuid" - }, - "pre_release": { - "type": "boolean" - }, - "end_of_life": { - "type": "string", - "format": "date-time" - }, - "collection_references": { - "type": "array", - "items": { - "$ref": "#/components/schemas/type_uuid" - }, - "description": "Array of UUIDs referencing TEA Collection entries", - "default": [] - } - }, - "required": [ - "identifier", - "product_name", - "product_version", - "release_date", - "pre_release" + "collection_update_reason": { + "type": "object", + "description": "Reason for the update to the TEA collection", + "properties": { + "type": { + "description": "Type of update reason", + "type": "string", + "enum": [ + "INITIAL_RELEASE", + "VEX_UPDATED", + "ARTIFACT_UPDATED", + "ARTIFACT_ADDED", + "ARTIFACT_REMOVED" ] + }, + "comment": { + "type": "string", + "description": "Free text description" } + }, + "required": [ + "type" ] }, "tea_collection": { "type": "object", + "description": "A collection of security-related documents", "properties": { - "identifier": { + "uuid": { + "description": "UUID of the TEA Collection object. Note that this is equal to the UUID of the associated TEA Release object.", "$ref": "#/components/schemas/type_uuid" }, - "product_name": { - "type": "string" - }, - "product_version": { - "type": "string" + "version": { + "type": "integer", + "description": "TEA Collection version, incremented each time its content changes. Versions start with 1.", + "minimum": 1 }, - "release_date": { + "releaseDate": { + "description": "The date when the TEA Collection version was created.", "type": "string", "format": "date-time", "example": "2024-03-20T15:30:00Z" }, - "author": { - "$ref": "#/components/schemas/type_author" - }, - "reason": { - "$ref": "#/components/schemas/type_collection_reason" + "updateReason": { + "description": "Reason for the update/release of the TEA Collection object.", + "$ref": "#/components/schemas/collection_update_reason" }, "artifacts": { "type": "array", + "description": "List of TEA artifact objects.", "items": { - "$ref": "#/components/schemas/tea_collection_artifact" - }, - "default": [] + "$ref": "#/components/schemas/tea_artifact" + } } }, "required": [ - "identifier", - "product_name", - "product_version", - "release_date", - "author", - "reason" + "uuid", + "version", + "releaseDate", + "updateReason" ] }, - "tea_collection_artifact": { + "tea_artifact": { "type": "object", + "description": "A security-related document", "properties": { - "identifier": { + "uuid": { + "description": "UUID of the TEA Artifact object.", "$ref": "#/components/schemas/type_uuid" }, "name": { - "type": "string" + "type": "string", + "description": "Artifact name" }, "type": { + "description": "Type of artifact", "$ref": "#/components/schemas/type_tea_collection_artifact_type" }, "author": { - "$ref": "#/components/schemas/type_author" + "$ref": "#/components/schemas/type_author", + "description": "Author of the artifact" }, - "objects": { + "formats": { "type": "array", + "description": "List of objects with the same content, but in different formats.", "items": { - "$ref": "#/components/schemas/tea_collection_artifact_object" - }, - "minItems": 1 + "$ref": "#/components/schemas/artifact_format" + } } }, "required": [ - "identifier", + "uuid", "name", "type", "author", - "objects" + "formats" ] }, - "tea_collection_artifact_object": { + "artifact_format": { "type": "object", + "description": "A security-related document in a specific format", "properties": { - "identifier": { - "$ref": "#/components/schemas/type_uuid" + "mime_type": { + "type": "string", + "description": "The MIME type of the document" }, "description": { - "type": "string" - }, - "mime_type": { - "type": "string" + "type": "string", + "description": "A free text describing the artifact" }, "artifact_url": { "type": "string", - "format": "uri" + "format": "uri", + "description": "Direct download URL for the artifact" }, "artifact_size_in_bytes": { "type": "integer", - "format": "int64" - }, - "artifact_checksum": { - "type": "string", - "description": "The checksum value" + "format": "int64", + "description": "Size of the artifact in bytes" }, - "artifact_checksum_type": { - "type": "string", - "description": "The algorithm used to generate the checksum", - "enum": [ - "SHA512", - "SHA384", - "SHA256", - "SHA224", - "SHA1", - "MD5", - "BLAKE2b-512", - "BLAKE2s-256", - "BLAKE3" - ], - "default": "SHA256" + "artifact_checksums": { + "type": "array", + "items": { + "$ref": "#/components/schemas/artifact_checksum" + }, + "description": "List of checksums for the artifact" }, "signature_url": { "type": "string", - "format": "uri" + "format": "uri", + "description": "Direct download URL for an external signature of the artifact" } }, "required": [ - "identifier", - "description", "mime_type", + "description", "artifact_url", "artifact_size_in_bytes", - "artifact_checksum", - "artifact_checksum_type" + "artifact_checksums" ] }, "type_author": { @@ -1162,46 +1387,6 @@ "organization" ] }, - "type_collection_reason": { - "type": "string", - "description": "Event requiring this TEA Collection was published", - "enum": [ - "New Product Release", - "BOM Updated", - "Attestation Added", - "Attestation Updated" - ] - }, - "type_pagination_details": { - "type": "object", - "properties": { - "timestamp": { - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" - }, - "page_start_index": { - "type": "number", - "format": "int64", - "default": 0 - }, - "page_size": { - "type": "number", - "format": "int64", - "default": 100 - }, - "total_results": { - "type": "number", - "format": "int64" - } - }, - "required": [ - "timestamp", - "page_start_index", - "page_size", - "total_results" - ] - }, "type_tea_collection_artifact_type": { "type": "string", "title": "Type", @@ -1302,28 +1487,47 @@ "type_uuid": { "type": "string", "format": "uuid" - } - }, - "responses": { - "base_error": { + }, + "pagination_details": { "type": "object", "properties": { - "error": { - "type": "string" + "timestamp": { + "type": "string", + "format": "date-time", + "example": "2024-03-20T15:30:00Z" }, - "message": { - "type": "string" + "pageStartIndex": { + "type": "integer", + "format": "int64", + "default": 0 + }, + "pageSize": { + "type": "integer", + "format": "int64", + "default": 100 + }, + "totalResults": { + "type": "integer", + "format": "int64" } - } - }, - "404-object-by-id-not-found": { - "description": "Object requested by identifier not found", + }, + "required": [ + "timestamp", + "pageStartIndex", + "pageSize", + "totalResults" + ] + } + }, + "responses": { + "401-unauthorized": { + "description": "Authentication required", "content": { "application/json": {} } }, - "401-unauthorized": { - "description": "Authentication required", + "404-object-by-id-not-found": { + "description": "Object requested by identifier not found", "content": { "application/json": {} } @@ -1331,23 +1535,23 @@ }, "parameters": { "page-offset": { - "name": "page-offset", + "name": "pageOffset", "description": "Pagination offset", "in": "query", "required": false, "schema": { - "type": "number", + "type": "integer", "format": "int64", "default": 0 } }, "page-size": { - "name": "page-size", - "description": "Pagination offset", + "name": "pageSize", + "description": "Pagination size", "in": "query", "required": false, "schema": { - "type": "number", + "type": "integer", "format": "int64", "default": 100 } @@ -1358,7 +1562,8 @@ "in": "path", "required": true, "schema": { - "type": "string" + "type": "string", + "pattern": "^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\\.-]+:.+$" } }, "tea_product_identifier": { @@ -1367,34 +1572,18 @@ "in": "path", "required": true, "schema": { - "type": "string" - } - }, - "product_version": { - "name": "product_version", - "description": "Product Version string", - "in": "path", - "required": true, - "schema": { - "type": "string" + "type": "string", + "format": "uuid" } }, "tea_collection_identifier": { - "name": "tea_collection_identifier", + "name": "collection_identifier", "description": "TEA Collection Identifier", "in": "path", "required": true, "schema": { - "type": "string" - } - }, - "tea_leaf_identifier": { - "name": "tea_leaf_identifier", - "description": "TEA Leaf Identifier", - "in": "path", - "required": true, - "schema": { - "type": "string" + "type": "string", + "format": "uuid" } }, "purl": { @@ -1444,55 +1633,27 @@ "scheme": "basic" } }, - "security_requirements": { - "standard_auth": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - }, - "responses": { - "standard_errors": { - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { - "$ref": "#/components/responses/401-unauthorized" - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "standard_delete": { - "204": { - "description": "Resource successfully deleted" - } - } - }, - "parameters": { - "standard_pagination": { - "page_offset": { - "$ref": "#/components/parameters/page-offset" - }, - "page_size": { - "$ref": "#/components/parameters/page-size" - } - } - }, "operations": { "standard_delete": { "responses": { - "$ref": "#/components/responses/standard_delete" + "204": { + "description": "Resource successfully deleted" + }, + "401": { + "$ref": "#/components/responses/401-unauthorized" + }, + "404": { + "$ref": "#/components/responses/404-object-by-id-not-found" + } }, - "security": { - "$ref": "#/components/security_requirements/standard_auth" - } + "security": [ + { + "bearerAuth": [] + }, + { + "basicAuth": [] + } + ] } } }, @@ -1505,9 +1666,22 @@ } ], "tags": [ - "TEA Collection", - "TEA Product", - "TEA Leaf" + { + "name": "TEA Product", + "description": "Operations related to TEA Products" + }, + { + "name": "TEA Component", + "description": "Operations related to TEA Components" + }, + { + "name": "TEA Release", + "description": "Operations related to TEA Releases" + }, + { + "name": "TEA Collection", + "description": "Operations related to TEA Collections" + } ], "externalDocs": { "description": "Transparency Exchange API specification", diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml new file mode 100644 index 0000000..f31ffdd --- /dev/null +++ b/spec/publisher/openapi.yaml @@ -0,0 +1,1121 @@ +jsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base +openapi: 3.1.1 +info: + title: Transparency Exchange API + summary: Transparency Exchange API specification for consumers and publishers + description: The Transparency Exchange API (TEA) provides standardized access to software transparency artifacts such as SBOMs, VEX, VDR, and other attestations. + contact: + name: TEA Working Group + email: TBC + url: https://github.com/CycloneDX/transparency-exchange-api + license: + name: Apache 2.0 + url: https://github.com/CycloneDX/transparency-exchange-api/blob/main/LICENSE + version: 0.0.3 +servers: + - url: http://localhost/tea/v1 + description: Local development +paths: + /product/{tei_urn}: + get: + description: Returns the corresponding releases for a given TEI URN + operationId: getTeaProduct + parameters: + - $ref: '#/components/parameters/tei_urn' + responses: + '200': + description: Requested TEA Product found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_product' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Product + patch: + description: Update an existing TEA Product entry + operationId: updateTeaProduct + parameters: + - $ref: '#/components/parameters/tea_product_identifier' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + product_name: + type: string + barcode: + type: string + description: Barcode + sku: + type: string + description: Product SKU + vendor_uuid: + $ref: '#/components/schemas/type_uuid' + description: Vendor UUID + purl: + type: string + description: Package URL (PURL) + examples: + basic: + summary: Basic product update + value: + product_name: Updated Product Name + barcode: '123456789012' + sku: PROD-001 + vendor_uuid: 123e4567-e89b-12d3-a456-426614174000 + purl: pkg:generic/example@1.0.0 + responses: + '200': + description: TEA Product updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/tea_product' + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Product + security: + - bearerAuth: [] + - basicAuth: [] + delete: + description: Delete a TEA Product entry + operationId: deleteTeaProduct + parameters: + - $ref: '#/components/parameters/tea_product_identifier' + $ref: '#/components/operations/standard_delete' + tags: + - TEA Product + /product: + get: + description: Returns a list of TEA Products + operationId: listTeaProducts + parameters: + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-size' + - $ref: '#/components/parameters/purl' + - $ref: '#/components/parameters/barcode' + - $ref: '#/components/parameters/sku' + - $ref: '#/components/parameters/vendor_uuid' + responses: + '200': + description: List retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/paginated_product_list' + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Product + post: + description: Create TEA Product entry for the supplied product identifier + operationId: createTeaProduct + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + product_name: + type: string + barcode: + type: string + description: Barcode + sku: + type: string + description: Product SKU + vendor_uuid: + $ref: '#/components/schemas/type_uuid' + description: Vendor UUID + purl: + type: string + description: Package URL (PURL) + tei_urns: + type: array + items: + type: string + description: Transparency Exchange Identifier URN + pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ + description: List of TEI URNs associated with this product + required: + - product_name + examples: + basic: + summary: Basic product creation + value: + product_name: Example Product + full: + summary: Full product creation with all fields + value: + product_name: Complete Product Example + barcode: '123456789012' + sku: PROD-001 + vendor_uuid: 123e4567-e89b-12d3-a456-426614174000 + purl: pkg:generic/example@1.0.0 + tei_urns: + - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 + responses: + '201': + description: TEA Product created successfully + content: + application/json: + schema: + type: object + properties: + identifier: + $ref: '#/components/schemas/type_uuid' + product_name: + type: string + barcode: + type: string + sku: + type: string + vendor_uuid: + $ref: '#/components/schemas/type_uuid' + purl: + type: string + tei_urns: + type: array + items: + type: string + required: + - identifier + - product_name + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Product + security: + - bearerAuth: [] + - basicAuth: [] + /component: + post: + description: Create a new TEA Component entry + operationId: createTeaComponent + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tea_product_identifier: + $ref: '#/components/schemas/type_uuid' + name: + type: string + description: Component name + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the component + required: + - tea_product_identifier + - name + examples: + basic: + summary: Basic component creation + value: + tea_product_identifier: 123e4567-e89b-12d3-a456-426614174000 + name: Example Component + identifiers: + - idType: purl + idValue: pkg:maven/org.example/component@1.0.0 + responses: + '201': + description: TEA Component created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/tea_component' + '400': + description: Invalid parameters + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Component + security: + - bearerAuth: [] + - basicAuth: [] + /component/{component_identifier}: + get: + description: Get information about a TEA Component + operationId: getTeaComponent + parameters: + - name: component_identifier + in: path + required: true + description: UUID of TEA Component in the TEA server + schema: + type: string + format: uuid + responses: + '200': + description: Requested TEA Component found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_component' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Component + patch: + description: Update an existing TEA Component entry + operationId: updateTeaComponent + parameters: + - name: component_identifier + in: path + required: true + description: UUID of TEA Component in the TEA server + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Component name + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the component + responses: + '200': + description: TEA Component updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/tea_component' + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Component + security: + - bearerAuth: [] + - basicAuth: [] + delete: + description: Delete a TEA Component entry + operationId: deleteTeaComponent + parameters: + - name: component_identifier + in: path + required: true + description: UUID of TEA Component in the TEA server + schema: + type: string + format: uuid + $ref: '#/components/operations/standard_delete' + tags: + - TEA Component + /release: + post: + description: Create a new TEA Release + operationId: createTeaRelease + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + component_identifier: + $ref: '#/components/schemas/type_uuid' + description: UUID of the TEA Component + version: + type: string + description: Version number + release_date: + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + description: Timestamp of the release + pre_release: + type: boolean + description: Flag indicating pre-release status + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the release + required: + - component_identifier + - version + - release_date + examples: + basic: + summary: Basic release creation + value: + component_identifier: 123e4567-e89b-12d3-a456-426614174000 + version: 1.0.0 + release_date: '2024-03-20T15:30:00Z' + pre_release: false + identifiers: + - idType: purl + idValue: pkg:maven/org.example/component@1.0.0 + responses: + '201': + description: TEA Release created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/tea_release' + '400': + description: Invalid parameters + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Release + security: + - bearerAuth: [] + - basicAuth: [] + /release/{release_identifier}: + get: + description: Get information about a TEA Release + operationId: getTeaRelease + parameters: + - name: release_identifier + in: path + required: true + description: UUID of TEA Release in the TEA server + schema: + type: string + format: uuid + responses: + '200': + description: Requested TEA Release found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_release' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Release + patch: + description: Update an existing TEA Release entry + operationId: updateTeaRelease + parameters: + - name: release_identifier + in: path + required: true + description: UUID of TEA Release in the TEA server + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + version: + type: string + description: Version number + release_date: + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + pre_release: + type: boolean + description: May only be set to false if previously true + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + responses: + '200': + description: TEA Release updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/tea_release' + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Release + security: + - bearerAuth: [] + - basicAuth: [] + delete: + description: Delete a TEA Release entry + operationId: deleteTeaRelease + parameters: + - name: release_identifier + in: path + required: true + description: UUID of TEA Release in the TEA server + schema: + type: string + format: uuid + $ref: '#/components/operations/standard_delete' + tags: + - TEA Release + /collection: + post: + description: Create a new TEA Collection + operationId: createTeaCollection + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + release_identifier: + $ref: '#/components/schemas/type_uuid' + description: UUID of the TEA Release + update_reason: + $ref: '#/components/schemas/collection_update_reason' + description: Reason for collection creation or update + artifacts: + type: array + items: + type: object + properties: + name: + type: string + description: Artifact name + type: + $ref: '#/components/schemas/type_tea_collection_artifact_type' + description: Type of artifact + author: + $ref: '#/components/schemas/type_author' + description: Author of the artifact + formats: + type: array + items: + type: object + properties: + description: + type: string + description: A free text describing the artifact + mime_type: + type: string + description: The MIME type of the document + artifact_url: + type: string + format: uri + description: Direct download URL for the artifact + artifact_size_in_bytes: + type: integer + format: int64 + description: Size of the artifact in bytes + artifact_checksums: + type: array + items: + $ref: '#/components/schemas/artifact_checksum' + description: List of checksums for the artifact + signature_url: + type: string + format: uri + description: URL for an external signature of the artifact + required: + - description + - mime_type + - artifact_url + - artifact_size_in_bytes + - artifact_checksums + required: + - name + - type + - author + - formats + required: + - release_identifier + - update_reason + examples: + basic: + summary: Basic collection creation + value: + release_identifier: 123e4567-e89b-12d3-a456-426614174000 + update_reason: + type: INITIAL_RELEASE + comment: Initial release of collection + artifacts: + - name: Example SBOM + type: bom + author: + name: John Doe + email: john.doe@example.com + organization: Example Org + formats: + - description: CycloneDX SBOM (XML) + mime_type: application/vnd.cyclonedx+xml + artifact_url: https://example.com/sbom.xml + artifact_size_in_bytes: 1024 + artifact_checksums: + - algType: SHA-256 + algValue: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 + signature_url: https://example.com/sbom.xml.sig + responses: + '201': + description: TEA Collection created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/tea_collection' + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Collection + security: + - bearerAuth: [] + - basicAuth: [] + /collection/{collection_identifier}: + get: + description: Get a TEA Collection by its Identifier + operationId: getTeaCollection + parameters: + - $ref: '#/components/parameters/tea_collection_identifier' + responses: + '200': + description: Requested TEA Collection found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_collection' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Collection + delete: + description: Delete a TEA Collection entry + operationId: deleteTeaCollection + parameters: + - $ref: '#/components/parameters/tea_collection_identifier' + $ref: '#/components/operations/standard_delete' + tags: + - TEA Collection + /collection/{collection_identifier}/{version}: + get: + description: Get a specific version of a TEA Collection + operationId: getTeaCollectionVersion + parameters: + - $ref: '#/components/parameters/tea_collection_identifier' + - name: version + in: path + required: true + description: Version of the TEA Collection + schema: + type: integer + minimum: 1 + responses: + '200': + description: Requested TEA Collection version found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_collection' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Collection +components: + schemas: + identifier: + type: object + description: An identifier with a specified type + properties: + idType: + description: Type of identifier, e.g. `tei`, `purl`, `cpe` + type: string + enum: + - cpe + - tei + - purl + idValue: + description: Identifier value + type: string + required: + - idType + - idValue + artifact_checksum: + type: object + properties: + algType: + description: Checksum algorithm + type: string + enum: + - MD5 + - SHA-1 + - SHA-256 + - SHA-384 + - SHA-512 + - SHA3-256 + - SHA3-384 + - SHA3-512 + - BLAKE2b-256 + - BLAKE2b-384 + - BLAKE2b-512 + - BLAKE3 + algValue: + type: string + description: Checksum value + required: + - algType + - algValue + tea_product: + type: object + properties: + identifier: + $ref: '#/components/schemas/type_uuid' + description: A unique identifier for the TEA product + name: + type: string + description: Product name + identifiers: + type: array + description: List of identifiers for the product + items: + $ref: '#/components/schemas/identifier' + components: + type: array + description: List of TEA component UUIDs + items: + $ref: '#/components/schemas/type_uuid' + tei_urns: + type: array + items: + type: string + description: Transparency Exchange Identifier URN + pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ + description: List of TEI URNs associated with this product + required: + - identifier + - name + - identifiers + - components + paginated_product_list: + allOf: + - $ref: '#/components/schemas/pagination_details' + - type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/tea_product' + tea_component: + type: object + description: A TEA component + properties: + uuid: + description: A unique identifier for the TEA component + $ref: '#/components/schemas/type_uuid' + name: + type: string + description: Component name + identifiers: + type: array + description: List of identifiers for the component + items: + $ref: '#/components/schemas/identifier' + releases: + type: array + description: List of UUIDs referencing TEA Release entries + items: + $ref: '#/components/schemas/type_uuid' + required: + - uuid + - name + - identifiers + tea_release: + type: object + description: A TEA release + properties: + uuid: + description: A unique identifier for the TEA Component Release + $ref: '#/components/schemas/type_uuid' + version: + description: Version number + type: string + example: 1.2.3 + releaseDate: + description: Timestamp of the release (for sorting purposes) + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + preRelease: + type: boolean + description: A flag indicating pre-release (or beta) status + identifiers: + type: array + description: List of identifiers for the component + items: + $ref: '#/components/schemas/identifier' + collection_references: + type: array + items: + $ref: '#/components/schemas/type_uuid' + description: Array of UUIDs referencing TEA Collection entries + default: [] + required: + - uuid + - version + - releaseDate + collection_update_reason: + type: object + description: Reason for the update to the TEA collection + properties: + type: + description: Type of update reason + type: string + enum: + - INITIAL_RELEASE + - VEX_UPDATED + - ARTIFACT_UPDATED + - ARTIFACT_ADDED + - ARTIFACT_REMOVED + comment: + type: string + description: Free text description + required: + - type + tea_collection: + type: object + description: A collection of security-related documents + properties: + uuid: + description: UUID of the TEA Collection object. Note that this is equal to the UUID of the associated TEA Release object. + $ref: '#/components/schemas/type_uuid' + version: + type: integer + description: TEA Collection version, incremented each time its content changes. Versions start with 1. + minimum: 1 + releaseDate: + description: The date when the TEA Collection version was created. + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + updateReason: + description: Reason for the update/release of the TEA Collection object. + $ref: '#/components/schemas/collection_update_reason' + artifacts: + type: array + description: List of TEA artifact objects. + items: + $ref: '#/components/schemas/tea_artifact' + required: + - uuid + - version + - releaseDate + - updateReason + tea_artifact: + type: object + description: A security-related document + properties: + uuid: + description: UUID of the TEA Artifact object. + $ref: '#/components/schemas/type_uuid' + name: + type: string + description: Artifact name + type: + description: Type of artifact + $ref: '#/components/schemas/type_tea_collection_artifact_type' + author: + $ref: '#/components/schemas/type_author' + description: Author of the artifact + formats: + type: array + description: List of objects with the same content, but in different formats. + items: + $ref: '#/components/schemas/artifact_format' + required: + - uuid + - name + - type + - author + - formats + artifact_format: + type: object + description: A security-related document in a specific format + properties: + mime_type: + type: string + description: The MIME type of the document + description: + type: string + description: A free text describing the artifact + artifact_url: + type: string + format: uri + description: Direct download URL for the artifact + artifact_size_in_bytes: + type: integer + format: int64 + description: Size of the artifact in bytes + artifact_checksums: + type: array + items: + $ref: '#/components/schemas/artifact_checksum' + description: List of checksums for the artifact + signature_url: + type: string + format: uri + description: Direct download URL for an external signature of the artifact + required: + - mime_type + - description + - artifact_url + - artifact_size_in_bytes + - artifact_checksums + type_author: + type: object + properties: + name: + type: string + email: + type: string + format: email + organization: + type: string + required: + - name + - email + - organization + type_tea_collection_artifact_type: + type: string + title: Type + description: Specifies the type of external reference. + enum: + - vcs + - issue-tracker + - website + - advisories + - bom + - mailing-list + - social + - chat + - documentation + - support + - source-distribution + - distribution + - distribution-intake + - license + - build-meta + - build-system + - release-notes + - security-contact + - model-card + - log + - configuration + - evidence + - formulation + - attestation + - threat-model + - adversary-model + - risk-assessment + - vulnerability-assertion + - exploitability-statement + - pentest-report + - static-analysis-report + - dynamic-analysis-report + - runtime-analysis-report + - component-analysis-report + - maturity-report + - certification-report + - codified-infrastructure + - quality-metrics + - poam + - electronic-signature + - digital-signature + - rfc-9116 + - other + type_uuid: + type: string + format: uuid + pagination_details: + type: object + properties: + timestamp: + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + pageStartIndex: + type: integer + format: int64 + default: 0 + pageSize: + type: integer + format: int64 + default: 100 + totalResults: + type: integer + format: int64 + required: + - timestamp + - pageStartIndex + - pageSize + - totalResults + responses: + 401-unauthorized: + description: Authentication required + content: + application/json: {} + 404-object-by-id-not-found: + description: Object requested by identifier not found + content: + application/json: {} + parameters: + page-offset: + name: pageOffset + description: Pagination offset + in: query + required: false + schema: + type: integer + format: int64 + default: 0 + page-size: + name: pageSize + description: Pagination size + in: query + required: false + schema: + type: integer + format: int64 + default: 100 + tei_urn: + name: tei_urn + description: Transparency Exchange Identifier (URN) + in: path + required: true + schema: + type: string + pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ + tea_product_identifier: + name: tea_product_identifier + description: TEA Product Identifier + in: path + required: true + schema: + type: string + format: uuid + tea_collection_identifier: + name: collection_identifier + description: TEA Collection Identifier + in: path + required: true + schema: + type: string + format: uuid + purl: + name: purl + description: Package URL (PURL) + in: query + required: false + schema: + type: string + barcode: + name: barcode + description: Barcode + in: query + required: false + schema: + type: string + sku: + name: sku + description: Product SKU + in: query + required: false + schema: + type: string + vendor_uuid: + name: vendor_uuid + description: Vendor UUID + in: query + required: false + schema: + $ref: '#/components/schemas/type_uuid' + securitySchemes: + bearerAuth: + type: http + scheme: bearer + basicAuth: + type: http + scheme: basic + operations: + standard_delete: + responses: + '204': + description: Resource successfully deleted + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + security: + - bearerAuth: [] + - basicAuth: [] +security: + - bearerAuth: [] + - basicAuth: [] +tags: + - name: TEA Product + description: Operations related to TEA Products + - name: TEA Component + description: Operations related to TEA Components + - name: TEA Release + description: Operations related to TEA Releases + - name: TEA Collection + description: Operations related to TEA Collections +externalDocs: + description: Transparency Exchange API specification + url: https://github.com/CycloneDX/transparency-exchange-api From 84781b1ccb8c0568c8e202a916d26dee1d37d81e Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Sat, 10 May 2025 22:31:33 +1000 Subject: [PATCH 02/10] more inconsistencies from consumer that needed updates Signed-off-by: Chris Langton --- spec/publisher/openapi.json | 1690 ----------------------------------- spec/publisher/openapi.yaml | 126 ++- 2 files changed, 112 insertions(+), 1704 deletions(-) delete mode 100644 spec/publisher/openapi.json diff --git a/spec/publisher/openapi.json b/spec/publisher/openapi.json deleted file mode 100644 index 3a06822..0000000 --- a/spec/publisher/openapi.json +++ /dev/null @@ -1,1690 +0,0 @@ -{ - "jsonSchemaDialect": "https://spec.openapis.org/oas/3.1/dialect/base", - "openapi": "3.1.1", - "info": { - "title": "Transparency Exchange API", - "summary": "Transparency Exchange API specification for consumers and publishers", - "description": "The Transparency Exchange API (TEA) provides standardized access to software transparency artifacts such as SBOMs, VEX, VDR, and other attestations.", - "contact": { - "name": "TEA Working Group", - "email": "TBC", - "url": "https://github.com/CycloneDX/transparency-exchange-api" - }, - "license": { - "name": "Apache 2.0", - "url": "https://github.com/CycloneDX/transparency-exchange-api/blob/main/LICENSE" - }, - "version": "0.0.3" - }, - "servers": [ - { - "url": "http://localhost/tea/v1", - "description": "Local development" - } - ], - "paths": { - "/product/{tei_urn}": { - "get": { - "description": "Returns the corresponding releases for a given TEI URN", - "operationId": "getTeaProduct", - "parameters": [ - { - "$ref": "#/components/parameters/tei_urn" - } - ], - "responses": { - "200": { - "description": "Requested TEA Product found and returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_product" - } - } - } - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Product" - ] - }, - "patch": { - "description": "Update an existing TEA Product entry", - "operationId": "updateTeaProduct", - "parameters": [ - { - "$ref": "#/components/parameters/tea_product_identifier" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "product_name": { - "type": "string" - }, - "barcode": { - "type": "string", - "description": "Barcode" - }, - "sku": { - "type": "string", - "description": "Product SKU" - }, - "vendor_uuid": { - "$ref": "#/components/schemas/type_uuid", - "description": "Vendor UUID" - }, - "purl": { - "type": "string", - "description": "Package URL (PURL)" - } - } - }, - "examples": { - "basic": { - "summary": "Basic product update", - "value": { - "product_name": "Updated Product Name", - "barcode": "123456789012", - "sku": "PROD-001", - "vendor_uuid": "123e4567-e89b-12d3-a456-426614174000", - "purl": "pkg:generic/example@1.0.0" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "TEA Product updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_product" - } - } - } - }, - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Product" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - }, - "delete": { - "description": "Delete a TEA Product entry", - "operationId": "deleteTeaProduct", - "parameters": [ - { - "$ref": "#/components/parameters/tea_product_identifier" - } - ], - "$ref": "#/components/operations/standard_delete", - "tags": [ - "TEA Product" - ] - } - }, - "/product": { - "get": { - "description": "Returns a list of TEA Products", - "operationId": "listTeaProducts", - "parameters": [ - { - "$ref": "#/components/parameters/page-offset" - }, - { - "$ref": "#/components/parameters/page-size" - }, - { - "$ref": "#/components/parameters/purl" - }, - { - "$ref": "#/components/parameters/barcode" - }, - { - "$ref": "#/components/parameters/sku" - }, - { - "$ref": "#/components/parameters/vendor_uuid" - } - ], - "responses": { - "200": { - "description": "List retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/paginated_product_list" - } - } - } - }, - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Product" - ] - }, - "post": { - "description": "Create TEA Product entry for the supplied product identifier", - "operationId": "createTeaProduct", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "product_name": { - "type": "string" - }, - "barcode": { - "type": "string", - "description": "Barcode" - }, - "sku": { - "type": "string", - "description": "Product SKU" - }, - "vendor_uuid": { - "$ref": "#/components/schemas/type_uuid", - "description": "Vendor UUID" - }, - "purl": { - "type": "string", - "description": "Package URL (PURL)" - }, - "tei_urns": { - "type": "array", - "items": { - "type": "string", - "description": "Transparency Exchange Identifier URN", - "pattern": "^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\\.-]+:.+$" - }, - "description": "List of TEI URNs associated with this product" - } - }, - "required": [ - "product_name" - ] - }, - "examples": { - "basic": { - "summary": "Basic product creation", - "value": { - "product_name": "Example Product" - } - }, - "full": { - "summary": "Full product creation with all fields", - "value": { - "product_name": "Complete Product Example", - "barcode": "123456789012", - "sku": "PROD-001", - "vendor_uuid": "123e4567-e89b-12d3-a456-426614174000", - "purl": "pkg:generic/example@1.0.0", - "tei_urns": [ - "urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1" - ] - } - } - } - } - } - }, - "responses": { - "201": { - "description": "TEA Product created successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identifier": { - "$ref": "#/components/schemas/type_uuid" - }, - "product_name": { - "type": "string" - }, - "barcode": { - "type": "string" - }, - "sku": { - "type": "string" - }, - "vendor_uuid": { - "$ref": "#/components/schemas/type_uuid" - }, - "purl": { - "type": "string" - }, - "tei_urns": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "identifier", - "product_name" - ] - } - } - } - }, - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Product" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - } - }, - "/component": { - "post": { - "description": "Create a new TEA Component entry", - "operationId": "createTeaComponent", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tea_product_identifier": { - "$ref": "#/components/schemas/type_uuid" - }, - "name": { - "type": "string", - "description": "Component name" - }, - "identifiers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/identifier" - }, - "description": "List of identifiers for the component" - } - }, - "required": [ - "tea_product_identifier", - "name" - ] - }, - "examples": { - "basic": { - "summary": "Basic component creation", - "value": { - "tea_product_identifier": "123e4567-e89b-12d3-a456-426614174000", - "name": "Example Component", - "identifiers": [ - { - "idType": "purl", - "idValue": "pkg:maven/org.example/component@1.0.0" - } - ] - } - } - } - } - } - }, - "responses": { - "201": { - "description": "TEA Component created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_component" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Component" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } -] - } - }, - "/component/{component_identifier}": { - "get": { - "description": "Get information about a TEA Component", - "operationId": "getTeaComponent", - "parameters": [ - { - "name": "component_identifier", - "in": "path", - "required": true, - "description": "UUID of TEA Component in the TEA server", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Requested TEA Component found and returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_component" - } - } - } - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Component" - ] - }, - "patch": { - "description": "Update an existing TEA Component entry", - "operationId": "updateTeaComponent", - "parameters": [ - { - "name": "component_identifier", - "in": "path", - "required": true, - "description": "UUID of TEA Component in the TEA server", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Component name" - }, - "identifiers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/identifier" - }, - "description": "List of identifiers for the component" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "TEA Component updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_component" - } - } - } - }, - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Component" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - }, - "delete": { - "description": "Delete a TEA Component entry", - "operationId": "deleteTeaComponent", - "parameters": [ - { - "name": "component_identifier", - "in": "path", - "required": true, - "description": "UUID of TEA Component in the TEA server", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "$ref": "#/components/operations/standard_delete", - "tags": [ - "TEA Component" - ] - } - }, - "/release": { - "post": { - "description": "Create a new TEA Release", - "operationId": "createTeaRelease", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "component_identifier": { - "$ref": "#/components/schemas/type_uuid", - "description": "UUID of the TEA Component" - }, - "version": { - "type": "string", - "description": "Version number" - }, - "release_date": { - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z", - "description": "Timestamp of the release" - }, - "pre_release": { - "type": "boolean", - "description": "Flag indicating pre-release status" - }, - "identifiers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/identifier" - }, - "description": "List of identifiers for the release" - } - }, - "required": [ - "component_identifier", - "version", - "release_date" - ] - }, - "examples": { - "basic": { - "summary": "Basic release creation", - "value": { - "component_identifier": "123e4567-e89b-12d3-a456-426614174000", - "version": "1.0.0", - "release_date": "2024-03-20T15:30:00Z", - "pre_release": false, - "identifiers": [ - { - "idType": "purl", - "idValue": "pkg:maven/org.example/component@1.0.0" - } - ] - } - } - } - } - } - }, - "responses": { - "201": { - "description": "TEA Release created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_release" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Release" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - } - }, - "/release/{release_identifier}": { - "get": { - "description": "Get information about a TEA Release", - "operationId": "getTeaRelease", - "parameters": [ - { - "name": "release_identifier", - "in": "path", - "required": true, - "description": "UUID of TEA Release in the TEA server", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Requested TEA Release found and returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_release" - } - } - } - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Release" - ] - }, - "patch": { - "description": "Update an existing TEA Release entry", - "operationId": "updateTeaRelease", - "parameters": [ - { - "name": "release_identifier", - "in": "path", - "required": true, - "description": "UUID of TEA Release in the TEA server", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "version": { - "type": "string", - "description": "Version number" - }, - "release_date": { - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" - }, - "pre_release": { - "type": "boolean", - "description": "May only be set to false if previously true" - }, - "identifiers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/identifier" - } - } - } - } - } - } - }, - "responses": { - "200": { - "description": "TEA Release updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_release" - } - } - } - }, - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Release" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - }, - "delete": { - "description": "Delete a TEA Release entry", - "operationId": "deleteTeaRelease", - "parameters": [ - { - "name": "release_identifier", - "in": "path", - "required": true, - "description": "UUID of TEA Release in the TEA server", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "$ref": "#/components/operations/standard_delete", - "tags": [ - "TEA Release" - ] - } - }, - "/collection": { - "post": { - "description": "Create a new TEA Collection", - "operationId": "createTeaCollection", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "release_identifier": { - "$ref": "#/components/schemas/type_uuid", - "description": "UUID of the TEA Release" - }, - "update_reason": { - "$ref": "#/components/schemas/collection_update_reason", - "description": "Reason for collection creation or update" - }, - "artifacts": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Artifact name" - }, - "type": { - "$ref": "#/components/schemas/type_tea_collection_artifact_type", - "description": "Type of artifact" - }, - "author": { - "$ref": "#/components/schemas/type_author", - "description": "Author of the artifact" - }, - "formats": { - "type": "array", - "items": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "A free text describing the artifact" - }, - "mime_type": { - "type": "string", - "description": "The MIME type of the document" - }, - "artifact_url": { - "type": "string", - "format": "uri", - "description": "Direct download URL for the artifact" - }, - "artifact_size_in_bytes": { - "type": "integer", - "format": "int64", - "description": "Size of the artifact in bytes" - }, - "artifact_checksums": { - "type": "array", - "items": { - "$ref": "#/components/schemas/artifact_checksum" - }, - "description": "List of checksums for the artifact" - }, - "signature_url": { - "type": "string", - "format": "uri", - "description": "URL for an external signature of the artifact" - } - }, - "required": [ - "description", - "mime_type", - "artifact_url", - "artifact_size_in_bytes", - "artifact_checksums" - ] - } - } - }, - "required": [ - "name", - "type", - "author", - "formats" - ] - } - } - }, - "required": [ - "release_identifier", - "update_reason" - ] - }, - "examples": { - "basic": { - "summary": "Basic collection creation", - "value": { - "release_identifier": "123e4567-e89b-12d3-a456-426614174000", - "update_reason": { - "type": "INITIAL_RELEASE", - "comment": "Initial release of collection" - }, - "artifacts": [ - { - "name": "Example SBOM", - "type": "bom", - "author": { - "name": "John Doe", - "email": "john.doe@example.com", - "organization": "Example Org" - }, - "formats": [ - { - "description": "CycloneDX SBOM (XML)", - "mime_type": "application/vnd.cyclonedx+xml", - "artifact_url": "https://example.com/sbom.xml", - "artifact_size_in_bytes": 1024, - "artifact_checksums": [ - { - "algType": "SHA-256", - "algValue": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3" - } - ], - "signature_url": "https://example.com/sbom.xml.sig" - } - ] - } - ] - } - } - } - } - } - }, - "responses": { - "201": { - "description": "TEA Collection created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_collection" - } - } - } - }, - "400": { - "description": "Invalid request body", - "content": { - "application/json": {} - } - }, - "401": { "$ref": "#/components/responses/401-unauthorized" }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Collection" - ], - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - } - }, - "/collection/{collection_identifier}": { - "get": { - "description": "Get a TEA Collection by its Identifier", - "operationId": "getTeaCollection", - "parameters": [ - { - "$ref": "#/components/parameters/tea_collection_identifier" - } - ], - "responses": { - "200": { - "description": "Requested TEA Collection found and returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_collection" - } - } - } - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Collection" - ] - }, - "delete": { - "description": "Delete a TEA Collection entry", - "operationId": "deleteTeaCollection", - "parameters": [ - { - "$ref": "#/components/parameters/tea_collection_identifier" - } - ], - "$ref": "#/components/operations/standard_delete", - "tags": [ - "TEA Collection" - ] - } - }, - "/collection/{collection_identifier}/{version}": { - "get": { - "description": "Get a specific version of a TEA Collection", - "operationId": "getTeaCollectionVersion", - "parameters": [ - { - "$ref": "#/components/parameters/tea_collection_identifier" - }, - { - "name": "version", - "in": "path", - "required": true, - "description": "Version of the TEA Collection", - "schema": { - "type": "integer", - "minimum": 1 - } - } - ], - "responses": { - "200": { - "description": "Requested TEA Collection version found and returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/tea_collection" - } - } - } - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "tags": [ - "TEA Collection" - ] - } - } - }, - "components": { - "schemas": { - "identifier": { - "type": "object", - "description": "An identifier with a specified type", - "properties": { - "idType": { - "description": "Type of identifier, e.g. `tei`, `purl`, `cpe`", - "type": "string", - "enum": [ - "cpe", - "tei", - "purl" - ] - }, - "idValue": { - "description": "Identifier value", - "type": "string" - } - }, - "required": [ - "idType", - "idValue" - ] - }, - "artifact_checksum": { - "type": "object", - "properties": { - "algType": { - "description": "Checksum algorithm", - "type": "string", - "enum": [ - "MD5", - "SHA-1", - "SHA-256", - "SHA-384", - "SHA-512", - "SHA3-256", - "SHA3-384", - "SHA3-512", - "BLAKE2b-256", - "BLAKE2b-384", - "BLAKE2b-512", - "BLAKE3" - ] - }, - "algValue": { - "type": "string", - "description": "Checksum value" - } - }, - "required": [ - "algType", - "algValue" - ] - }, - "tea_product": { - "type": "object", - "properties": { - "identifier": { - "$ref": "#/components/schemas/type_uuid", - "description": "A unique identifier for the TEA product" - }, - "name": { - "type": "string", - "description": "Product name" - }, - "identifiers": { - "type": "array", - "description": "List of identifiers for the product", - "items": { - "$ref": "#/components/schemas/identifier" - } - }, - "components": { - "type": "array", - "description": "List of TEA component UUIDs", - "items": { - "$ref": "#/components/schemas/type_uuid" - } - }, - "tei_urns": { - "type": "array", - "items": { - "type": "string", - "description": "Transparency Exchange Identifier URN", - "pattern": "^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\\.-]+:.+$" - }, - "description": "List of TEI URNs associated with this product" - } - }, - "required": [ - "identifier", - "name", - "identifiers", - "components" - ] - }, - "paginated_product_list": { - "allOf": [ - { - "$ref": "#/components/schemas/pagination_details" - }, - { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/tea_product" - } - } - } - } - ] - }, - "tea_component": { - "type": "object", - "description": "A TEA component", - "properties": { - "uuid": { - "description": "A unique identifier for the TEA component", - "$ref": "#/components/schemas/type_uuid" - }, - "name": { - "type": "string", - "description": "Component name" - }, - "identifiers": { - "type": "array", - "description": "List of identifiers for the component", - "items": { - "$ref": "#/components/schemas/identifier" - } - }, - "releases": { - "type": "array", - "description": "List of UUIDs referencing TEA Release entries", - "items": { - "$ref": "#/components/schemas/type_uuid" - } - } - }, - "required": [ - "uuid", - "name", - "identifiers" - ] - }, - "tea_release": { - "type": "object", - "description": "A TEA release", - "properties": { - "uuid": { - "description": "A unique identifier for the TEA Component Release", - "$ref": "#/components/schemas/type_uuid" - }, - "version": { - "description": "Version number", - "type": "string", - "example": "1.2.3" - }, - "releaseDate": { - "description": "Timestamp of the release (for sorting purposes)", - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" - }, - "preRelease": { - "type": "boolean", - "description": "A flag indicating pre-release (or beta) status" - }, - "identifiers": { - "type": "array", - "description": "List of identifiers for the component", - "items": { - "$ref": "#/components/schemas/identifier" - } - }, - "collection_references": { - "type": "array", - "items": { - "$ref": "#/components/schemas/type_uuid" - }, - "description": "Array of UUIDs referencing TEA Collection entries", - "default": [] - } - }, - "required": [ - "uuid", - "version", - "releaseDate" - ] - }, - "collection_update_reason": { - "type": "object", - "description": "Reason for the update to the TEA collection", - "properties": { - "type": { - "description": "Type of update reason", - "type": "string", - "enum": [ - "INITIAL_RELEASE", - "VEX_UPDATED", - "ARTIFACT_UPDATED", - "ARTIFACT_ADDED", - "ARTIFACT_REMOVED" - ] - }, - "comment": { - "type": "string", - "description": "Free text description" - } - }, - "required": [ - "type" - ] - }, - "tea_collection": { - "type": "object", - "description": "A collection of security-related documents", - "properties": { - "uuid": { - "description": "UUID of the TEA Collection object. Note that this is equal to the UUID of the associated TEA Release object.", - "$ref": "#/components/schemas/type_uuid" - }, - "version": { - "type": "integer", - "description": "TEA Collection version, incremented each time its content changes. Versions start with 1.", - "minimum": 1 - }, - "releaseDate": { - "description": "The date when the TEA Collection version was created.", - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" - }, - "updateReason": { - "description": "Reason for the update/release of the TEA Collection object.", - "$ref": "#/components/schemas/collection_update_reason" - }, - "artifacts": { - "type": "array", - "description": "List of TEA artifact objects.", - "items": { - "$ref": "#/components/schemas/tea_artifact" - } - } - }, - "required": [ - "uuid", - "version", - "releaseDate", - "updateReason" - ] - }, - "tea_artifact": { - "type": "object", - "description": "A security-related document", - "properties": { - "uuid": { - "description": "UUID of the TEA Artifact object.", - "$ref": "#/components/schemas/type_uuid" - }, - "name": { - "type": "string", - "description": "Artifact name" - }, - "type": { - "description": "Type of artifact", - "$ref": "#/components/schemas/type_tea_collection_artifact_type" - }, - "author": { - "$ref": "#/components/schemas/type_author", - "description": "Author of the artifact" - }, - "formats": { - "type": "array", - "description": "List of objects with the same content, but in different formats.", - "items": { - "$ref": "#/components/schemas/artifact_format" - } - } - }, - "required": [ - "uuid", - "name", - "type", - "author", - "formats" - ] - }, - "artifact_format": { - "type": "object", - "description": "A security-related document in a specific format", - "properties": { - "mime_type": { - "type": "string", - "description": "The MIME type of the document" - }, - "description": { - "type": "string", - "description": "A free text describing the artifact" - }, - "artifact_url": { - "type": "string", - "format": "uri", - "description": "Direct download URL for the artifact" - }, - "artifact_size_in_bytes": { - "type": "integer", - "format": "int64", - "description": "Size of the artifact in bytes" - }, - "artifact_checksums": { - "type": "array", - "items": { - "$ref": "#/components/schemas/artifact_checksum" - }, - "description": "List of checksums for the artifact" - }, - "signature_url": { - "type": "string", - "format": "uri", - "description": "Direct download URL for an external signature of the artifact" - } - }, - "required": [ - "mime_type", - "description", - "artifact_url", - "artifact_size_in_bytes", - "artifact_checksums" - ] - }, - "type_author": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "email": { - "type": "string", - "format": "email" - }, - "organization": { - "type": "string" - } - }, - "required": [ - "name", - "email", - "organization" - ] - }, - "type_tea_collection_artifact_type": { - "type": "string", - "title": "Type", - "description": "Specifies the type of external reference.", - "enum": [ - "vcs", - "issue-tracker", - "website", - "advisories", - "bom", - "mailing-list", - "social", - "chat", - "documentation", - "support", - "source-distribution", - "distribution", - "distribution-intake", - "license", - "build-meta", - "build-system", - "release-notes", - "security-contact", - "model-card", - "log", - "configuration", - "evidence", - "formulation", - "attestation", - "threat-model", - "adversary-model", - "risk-assessment", - "vulnerability-assertion", - "exploitability-statement", - "pentest-report", - "static-analysis-report", - "dynamic-analysis-report", - "runtime-analysis-report", - "component-analysis-report", - "maturity-report", - "certification-report", - "codified-infrastructure", - "quality-metrics", - "poam", - "electronic-signature", - "digital-signature", - "rfc-9116", - "other" - ], - "meta:enum": { - "vcs": "Version Control System", - "issue-tracker": "Issue or defect tracking system, or an Application Lifecycle Management (ALM) system", - "website": "Website", - "advisories": "Security advisories", - "bom": "Bill of Materials (SBOM, OBOM, HBOM, SaaSBOM, etc)", - "mailing-list": "Mailing list or discussion group", - "social": "Social media account", - "chat": "Real-time chat platform", - "documentation": "Documentation, guides, or how-to instructions", - "support": "Community or commercial support", - "source-distribution": { - "description": "The location where the source code distributable can be obtained. This is often an archive format such as zip or tgz. The source-distribution type complements use of the version control (vcs) type." - }, - "distribution": "Direct or repository download location", - "distribution-intake": "The location where a component was published to. This is often the same as \"distribution\" but may also include specialized publishing processes that act as an intermediary.", - "license": "The reference to the license file. If a license URL has been defined in the license node, it should also be defined as an external reference for completeness.", - "build-meta": "Build-system specific meta file (i.e. pom.xml, package.json, .nuspec, etc)", - "build-system": "Reference to an automated build system", - "release-notes": "Reference to release notes", - "security-contact": "Specifies a way to contact the maintainer, supplier, or provider in the event of a security incident. Common URIs include links to a disclosure procedure, a mailto (RFC-2368) that specifies an email address, a tel (RFC-3966) that specifies a phone number, or dns (RFC-4501) that specifies the records containing DNS Security TXT.", - "model-card": "A model card describes the intended uses of a machine learning model, potential limitations, biases, ethical considerations, training parameters, datasets used to train the model, performance metrics, and other relevant data useful for ML transparency.", - "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.", - "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.", - "risk-assessment": "Identifies and analyzes the potential of future events that may negatively impact individuals, assets, and/or the environment. Risk assessments may also include judgments on the tolerability of each risk.", - "vulnerability-assertion": "A Vulnerability Disclosure Report (VDR) which asserts the known and previously unknown vulnerabilities that affect a component, service, or product including the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on a component, service, or product.", - "exploitability-statement": "A Vulnerability Exploitability eXchange (VEX) which asserts the known vulnerabilities that do not affect a product, product family, or organization, and optionally the ones that do. The VEX should include the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on the product, product family, or organization.", - "pentest-report": "Results from an authorized simulated cyberattack on a component or service, otherwise known as a penetration test.", - "static-analysis-report": "SARIF or proprietary machine or human-readable report for which static analysis has identified code quality, security, and other potential issues with the source code.", - "dynamic-analysis-report": "Dynamic analysis report that has identified issues such as vulnerabilities and misconfigurations.", - "runtime-analysis-report": "Report generated by analyzing the call stack of a running application.", - "component-analysis-report": "Report generated by Software Composition Analysis (SCA), container analysis, or other forms of component analysis.", - "maturity-report": "Report containing a formal assessment of an organization, business unit, or team against a maturity model.", - "certification-report": "Industry, regulatory, or other certification from an accredited (if applicable) certification body.", - "codified-infrastructure": "Code or configuration that defines and provisions virtualized infrastructure, commonly referred to as Infrastructure as Code (IaC).", - "quality-metrics": "Report or system in which quality metrics can be obtained.", - "poam": "Plans of Action and Milestones (POAM) complement an \"attestation\" external reference. POAM is defined by NIST as a \"document that identifies tasks needing to be accomplished. It details resources required to accomplish the elements of the plan, any milestones in meeting the tasks and scheduled completion dates for the milestones\".", - "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 (A File Format to Aid in Security Vulnerability Disclosure)", - "other": "Use this if no other types accurately describe the purpose of the external reference." - } - }, - "type_uuid": { - "type": "string", - "format": "uuid" - }, - "pagination_details": { - "type": "object", - "properties": { - "timestamp": { - "type": "string", - "format": "date-time", - "example": "2024-03-20T15:30:00Z" - }, - "pageStartIndex": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "pageSize": { - "type": "integer", - "format": "int64", - "default": 100 - }, - "totalResults": { - "type": "integer", - "format": "int64" - } - }, - "required": [ - "timestamp", - "pageStartIndex", - "pageSize", - "totalResults" - ] - } - }, - "responses": { - "401-unauthorized": { - "description": "Authentication required", - "content": { - "application/json": {} - } - }, - "404-object-by-id-not-found": { - "description": "Object requested by identifier not found", - "content": { - "application/json": {} - } - } - }, - "parameters": { - "page-offset": { - "name": "pageOffset", - "description": "Pagination offset", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "default": 0 - } - }, - "page-size": { - "name": "pageSize", - "description": "Pagination size", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "default": 100 - } - }, - "tei_urn": { - "name": "tei_urn", - "description": "Transparency Exchange Identifier (URN)", - "in": "path", - "required": true, - "schema": { - "type": "string", - "pattern": "^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\\.-]+:.+$" - } - }, - "tea_product_identifier": { - "name": "tea_product_identifier", - "description": "TEA Product Identifier", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - "tea_collection_identifier": { - "name": "collection_identifier", - "description": "TEA Collection Identifier", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - "purl": { - "name": "purl", - "description": "Package URL (PURL)", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - "barcode": { - "name": "barcode", - "description": "Barcode", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - "sku": { - "name": "sku", - "description": "Product SKU", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - "vendor_uuid": { - "name": "vendor_uuid", - "description": "Vendor UUID", - "in": "query", - "required": false, - "schema": { - "$ref": "#/components/schemas/type_uuid" - } - } - }, - "securitySchemes": { - "bearerAuth": { - "type": "http", - "scheme": "bearer" - }, - "basicAuth": { - "type": "http", - "scheme": "basic" - } - }, - "operations": { - "standard_delete": { - "responses": { - "204": { - "description": "Resource successfully deleted" - }, - "401": { - "$ref": "#/components/responses/401-unauthorized" - }, - "404": { - "$ref": "#/components/responses/404-object-by-id-not-found" - } - }, - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ] - } - } - }, - "security": [ - { - "bearerAuth": [] - }, - { - "basicAuth": [] - } - ], - "tags": [ - { - "name": "TEA Product", - "description": "Operations related to TEA Products" - }, - { - "name": "TEA Component", - "description": "Operations related to TEA Components" - }, - { - "name": "TEA Release", - "description": "Operations related to TEA Releases" - }, - { - "name": "TEA Collection", - "description": "Operations related to TEA Collections" - } - ], - "externalDocs": { - "description": "Transparency Exchange API specification", - "url": "https://github.com/CycloneDX/transparency-exchange-api" - } -} \ No newline at end of file diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index f31ffdd..31d3aa4 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -6,7 +6,6 @@ info: description: The Transparency Exchange API (TEA) provides standardized access to software transparency artifacts such as SBOMs, VEX, VDR, and other attestations. contact: name: TEA Working Group - email: TBC url: https://github.com/CycloneDX/transparency-exchange-api license: name: Apache 2.0 @@ -619,6 +618,88 @@ paths: security: - bearerAuth: [] - basicAuth: [] + /release/{release_identifier}/collection: + get: + description: Get the latest TEA Collection belonging to the TEA Release + operationId: getLatestCollectionByReleaseId + parameters: + - name: release_identifier + in: path + required: true + description: UUID of TEA Release in the TEA server + schema: + type: string + format: uuid + responses: + '200': + description: Requested TEA Collection found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_collection' + '400': + description: Invalid request + content: + application/json: {} + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Release + /release/{release_identifier}/collections: + get: + description: Get all TEA Collections belonging to the TEA Release + operationId: getCollectionsByReleaseId + parameters: + - name: release_identifier + in: path + required: true + description: UUID of TEA Release in the TEA server + schema: + type: string + format: uuid + responses: + '200': + description: Requested TEA Collections found and returned + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/tea_collection' + '400': + description: Invalid request + content: + application/json: {} + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Release + /artifact/{artifact_identifier}: + get: + description: Get metadata for specific TEA artifact + operationId: getArtifact + parameters: + - name: artifact_identifier + in: path + required: true + description: UUID of TEA Artifact in the TEA server + schema: + $ref: '#/components/schemas/type_uuid' + responses: + '200': + description: Requested TEA Artifact metadata found and returned + content: + application/json: + schema: + $ref: '#/components/schemas/tea_artifact' + '400': + description: Invalid request + content: + application/json: {} + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Artifact /collection/{collection_identifier}: get: description: Get a TEA Collection by its Identifier @@ -767,6 +848,11 @@ components: description: List of identifiers for the component items: $ref: '#/components/schemas/identifier' + versions: # Added to match consumer schema requirements + type: array + description: List of available versions for this component + items: + type: string releases: type: array description: List of UUIDs referencing TEA Release entries @@ -776,6 +862,7 @@ components: - uuid - name - identifiers + - versions tea_release: type: object description: A TEA release @@ -894,29 +981,24 @@ components: description: type: string description: A free text describing the artifact - artifact_url: + url: # Changed from artifact_url to match consumer type: string format: uri description: Direct download URL for the artifact - artifact_size_in_bytes: - type: integer - format: int64 - description: Size of the artifact in bytes - artifact_checksums: + signature_url: # Already matches consumer + type: string + format: uri + description: Direct download URL for an external signature of the artifact + checksums: # Changed from artifact_checksums to match consumer type: array items: $ref: '#/components/schemas/artifact_checksum' description: List of checksums for the artifact - signature_url: - type: string - format: uri - description: Direct download URL for an external signature of the artifact required: - mime_type - description - - artifact_url - - artifact_size_in_bytes - - artifact_checksums + - url + - checksums type_author: type: object properties: @@ -1085,6 +1167,22 @@ components: required: false schema: $ref: '#/components/schemas/type_uuid' + id-type: + name: idType + description: Type of identifier specified in the `idValue` parameter + in: query + schema: + type: string + enum: + - cpe + - tei + - purl + id-value: + name: idValue + description: If present, only the objects with the given identifier value will be returned + in: query + schema: + type: string securitySchemes: bearerAuth: type: http From c0378b3cc75f05f9e24f069d6dc4cfa010ce84d6 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Sat, 10 May 2025 23:14:16 +1000 Subject: [PATCH 03/10] feat(openapi): align consumer/publisher APIs and implement TEI discovery - Add authentication schemes - Create discovery endpoints (/.well-known/tea/{id}) - Standardise property naming between consumer/publisher APIs - Implement advanced filtering for components and artifacts - Add lifecycle status endpoints Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 151 ++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index 31d3aa4..8c88f99 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -15,6 +15,15 @@ servers: - url: http://localhost/tea/v1 description: Local development paths: + /.well-known/tea/{tei_identifier}: + get: + description: TEI discovery endpoint that redirects to appropriate API endpoint + parameters: + - name: tei_identifier + in: path + required: true + schema: + type: string /product/{tei_urn}: get: description: Returns the corresponding releases for a given TEI URN @@ -264,6 +273,123 @@ paths: security: - bearerAuth: [] - basicAuth: [] + /components: # Add advanced search capabilities + get: + description: Returns a list of TEA Components + operationId: listTeaComponents + parameters: + - $ref: '#/components/parameters/page-offset' + - $ref: '#/components/parameters/page-size' + - name: tea_product_identifier + in: query + required: false + description: TEA Product UUID + schema: + type: string + format: uuid + - name: purl + in: query + required: false + description: Package URL (PURL) + schema: + type: string + - name: barcode + in: query + required: false + description: Barcode + schema: + type: string + - name: sku + in: query + required: false + description: SKU of the product + schema: + type: string + - name: version + in: query + schema: + type: string + - name: preRelease + in: query + schema: + type: boolean + - name: releaseDate + in: query + schema: + type: string + format: date-time + - name: vendor_uuid + in: query + required: false + description: Vendor UUID + schema: + type: string + format: uuid + - name: component_uuid + in: query + required: false + description: TEA Component UUID + schema: + type: string + format: uuid + - name: component_name + in: query + required: false + description: TEA Component name + schema: + type: string + - name: identifiers + in: query + required: false + description: TEA Component identifiers + schema: + type: array + items: + $ref: '#/components/schemas/identifier' + responses: + '200': + description: List retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/paginated_product_list' + '400': + description: Invalid request body + content: + application/json: {} + '401': + $ref: '#/components/responses/401-unauthorized' + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Component + /component/{component_id}/lifecycle: + get: + description: Get the lifecycle of a TEA Component + operationId: getTeaComponentLifecycle + parameters: + - name: component_id + in: path + required: true + description: UUID of TEA Component in the TEA server + schema: + type: string + format: uuid + responses: + '200': + description: Requested TEA Component lifecycle found and returned + content: + application/json: + schema: + type: object + properties: + lifecycle: + type: string + description: Lifecycle status of the component + '404': + $ref: '#/components/responses/404-object-by-id-not-found' + tags: + - TEA Component Lifecycle /component/{component_identifier}: get: description: Get information about a TEA Component @@ -1187,9 +1313,30 @@ components: bearerAuth: type: http scheme: bearer + bearerFormat: JWT + description: Bearer token authentication is a stateless authentication scheme where the client sends a token in the HTTP Authorization header. The server validates the token and grants access to the requested resource to anyone with the token without needing to authenticate again, and stolen tokens can be used by anyone. basicAuth: type: http scheme: basic + description: Basic authentication is a plaintext scheme built into the HTTP protocol and has been deemed insecure because headers are commonly logged in plaintext. + mutualTLS: + type: mutualTLS + description: Client certificate authentication is a secure authentication scheme where the client presents a valid certificate to the server for authentication. The server validates the certificate and grants access to the requested resource, but stolen certificates can be used by anyone. + pasetoAuth: + type: http + scheme: bearer + bearerFormat: PASETO + description: Platform-Agnostic Security Tokens (PASETO) is a secure alternative to JWT that is resistant to many cryptographic vulnerabilities. PASETO tokens use versioned protocols that specify modern cryptographic algorithms. + verifiableCredentials: + type: http + scheme: bearer + bearerFormat: VC-JWT + description: W3C Verifiable Credentials 2.0 with proof field is a standard for expressing verifiable credentials as signed JWT tokens. The integrity and authenticity of the credential can be cryptographically verified. + hmacAuth: + type: apiKey + in: header + name: X-HMAC-Signature + description: HMAC authentication uses a shared secret key to create a signature of the request content using a secure hash algorithm (SHA256, SHA384, SHA512, SHA3-256, SHA3-384, or SHA3-512). The server verifies this signature to authenticate the request. operations: standard_delete: responses: @@ -1205,6 +1352,10 @@ components: security: - bearerAuth: [] - basicAuth: [] + - mutualTLS: [] + - pasetoAuth: [] + - verifiableCredentials: [] + - hmacAuth: [] tags: - name: TEA Product description: Operations related to TEA Products From 637e29f023c6549a8c7f401f37778c18b631fb39 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Wed, 21 May 2025 20:49:59 +1000 Subject: [PATCH 04/10] chore(lint): address long lines Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 376 +++--------------------------------- 1 file changed, 24 insertions(+), 352 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index 8c88f99..877a534 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -3,7 +3,8 @@ openapi: 3.1.1 info: title: Transparency Exchange API summary: Transparency Exchange API specification for consumers and publishers - description: The Transparency Exchange API (TEA) provides standardized access to software transparency artifacts such as SBOMs, VEX, VDR, and other attestations. + description: | + The Transparency Exchange API (TEA) provides standardized access to software transparency artifacts such as SBOMs, VEX, VDR, and other attestations. contact: name: TEA Working Group url: https://github.com/CycloneDX/transparency-exchange-api @@ -15,32 +16,7 @@ servers: - url: http://localhost/tea/v1 description: Local development paths: - /.well-known/tea/{tei_identifier}: - get: - description: TEI discovery endpoint that redirects to appropriate API endpoint - parameters: - - name: tei_identifier - in: path - required: true - schema: - type: string /product/{tei_urn}: - get: - description: Returns the corresponding releases for a given TEI URN - operationId: getTeaProduct - parameters: - - $ref: '#/components/parameters/tei_urn' - responses: - '200': - description: Requested TEA Product found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_product' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Product patch: description: Update an existing TEA Product entry operationId: updateTeaProduct @@ -105,33 +81,6 @@ paths: tags: - TEA Product /product: - get: - description: Returns a list of TEA Products - operationId: listTeaProducts - parameters: - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-size' - - $ref: '#/components/parameters/purl' - - $ref: '#/components/parameters/barcode' - - $ref: '#/components/parameters/sku' - - $ref: '#/components/parameters/vendor_uuid' - responses: - '200': - description: List retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/paginated_product_list' - '400': - description: Invalid request body - content: - application/json: {} - '401': - $ref: '#/components/responses/401-unauthorized' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Product post: description: Create TEA Product entry for the supplied product identifier operationId: createTeaProduct @@ -273,146 +222,7 @@ paths: security: - bearerAuth: [] - basicAuth: [] - /components: # Add advanced search capabilities - get: - description: Returns a list of TEA Components - operationId: listTeaComponents - parameters: - - $ref: '#/components/parameters/page-offset' - - $ref: '#/components/parameters/page-size' - - name: tea_product_identifier - in: query - required: false - description: TEA Product UUID - schema: - type: string - format: uuid - - name: purl - in: query - required: false - description: Package URL (PURL) - schema: - type: string - - name: barcode - in: query - required: false - description: Barcode - schema: - type: string - - name: sku - in: query - required: false - description: SKU of the product - schema: - type: string - - name: version - in: query - schema: - type: string - - name: preRelease - in: query - schema: - type: boolean - - name: releaseDate - in: query - schema: - type: string - format: date-time - - name: vendor_uuid - in: query - required: false - description: Vendor UUID - schema: - type: string - format: uuid - - name: component_uuid - in: query - required: false - description: TEA Component UUID - schema: - type: string - format: uuid - - name: component_name - in: query - required: false - description: TEA Component name - schema: - type: string - - name: identifiers - in: query - required: false - description: TEA Component identifiers - schema: - type: array - items: - $ref: '#/components/schemas/identifier' - responses: - '200': - description: List retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/paginated_product_list' - '400': - description: Invalid request body - content: - application/json: {} - '401': - $ref: '#/components/responses/401-unauthorized' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Component - /component/{component_id}/lifecycle: - get: - description: Get the lifecycle of a TEA Component - operationId: getTeaComponentLifecycle - parameters: - - name: component_id - in: path - required: true - description: UUID of TEA Component in the TEA server - schema: - type: string - format: uuid - responses: - '200': - description: Requested TEA Component lifecycle found and returned - content: - application/json: - schema: - type: object - properties: - lifecycle: - type: string - description: Lifecycle status of the component - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Component Lifecycle /component/{component_identifier}: - get: - description: Get information about a TEA Component - operationId: getTeaComponent - parameters: - - name: component_identifier - in: path - required: true - description: UUID of TEA Component in the TEA server - schema: - type: string - format: uuid - responses: - '200': - description: Requested TEA Component found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_component' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Component patch: description: Update an existing TEA Component entry operationId: updateTeaComponent @@ -539,28 +349,6 @@ paths: - bearerAuth: [] - basicAuth: [] /release/{release_identifier}: - get: - description: Get information about a TEA Release - operationId: getTeaRelease - parameters: - - name: release_identifier - in: path - required: true - description: UUID of TEA Release in the TEA server - schema: - type: string - format: uuid - responses: - '200': - description: Requested TEA Release found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_release' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Release patch: description: Update an existing TEA Release entry operationId: updateTeaRelease @@ -744,137 +532,6 @@ paths: security: - bearerAuth: [] - basicAuth: [] - /release/{release_identifier}/collection: - get: - description: Get the latest TEA Collection belonging to the TEA Release - operationId: getLatestCollectionByReleaseId - parameters: - - name: release_identifier - in: path - required: true - description: UUID of TEA Release in the TEA server - schema: - type: string - format: uuid - responses: - '200': - description: Requested TEA Collection found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_collection' - '400': - description: Invalid request - content: - application/json: {} - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Release - /release/{release_identifier}/collections: - get: - description: Get all TEA Collections belonging to the TEA Release - operationId: getCollectionsByReleaseId - parameters: - - name: release_identifier - in: path - required: true - description: UUID of TEA Release in the TEA server - schema: - type: string - format: uuid - responses: - '200': - description: Requested TEA Collections found and returned - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/tea_collection' - '400': - description: Invalid request - content: - application/json: {} - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Release - /artifact/{artifact_identifier}: - get: - description: Get metadata for specific TEA artifact - operationId: getArtifact - parameters: - - name: artifact_identifier - in: path - required: true - description: UUID of TEA Artifact in the TEA server - schema: - $ref: '#/components/schemas/type_uuid' - responses: - '200': - description: Requested TEA Artifact metadata found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_artifact' - '400': - description: Invalid request - content: - application/json: {} - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Artifact - /collection/{collection_identifier}: - get: - description: Get a TEA Collection by its Identifier - operationId: getTeaCollection - parameters: - - $ref: '#/components/parameters/tea_collection_identifier' - responses: - '200': - description: Requested TEA Collection found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_collection' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Collection - delete: - description: Delete a TEA Collection entry - operationId: deleteTeaCollection - parameters: - - $ref: '#/components/parameters/tea_collection_identifier' - $ref: '#/components/operations/standard_delete' - tags: - - TEA Collection - /collection/{collection_identifier}/{version}: - get: - description: Get a specific version of a TEA Collection - operationId: getTeaCollectionVersion - parameters: - - $ref: '#/components/parameters/tea_collection_identifier' - - name: version - in: path - required: true - description: Version of the TEA Collection - schema: - type: integer - minimum: 1 - responses: - '200': - description: Requested TEA Collection version found and returned - content: - application/json: - schema: - $ref: '#/components/schemas/tea_collection' - '404': - $ref: '#/components/responses/404-object-by-id-not-found' - tags: - - TEA Collection components: schemas: identifier: @@ -1046,7 +703,8 @@ components: description: A collection of security-related documents properties: uuid: - description: UUID of the TEA Collection object. Note that this is equal to the UUID of the associated TEA Release object. + description: | + UUID of the TEA Collection object. Note that this is equal to the UUID of the associated TEA Release object. $ref: '#/components/schemas/type_uuid' version: type: integer @@ -1314,29 +972,43 @@ components: type: http scheme: bearer bearerFormat: JWT - description: Bearer token authentication is a stateless authentication scheme where the client sends a token in the HTTP Authorization header. The server validates the token and grants access to the requested resource to anyone with the token without needing to authenticate again, and stolen tokens can be used by anyone. + description: | + Bearer token authentication is a stateless authentication scheme where the client sends a token in the HTTP Authorization header. + The server validates the token and grants access to the requested resource to anyone with the token without needing to authenticate + again, and stolen tokens can be used by anyone. basicAuth: type: http scheme: basic - description: Basic authentication is a plaintext scheme built into the HTTP protocol and has been deemed insecure because headers are commonly logged in plaintext. + description: | + Basic authentication is a plaintext scheme built into the HTTP protocol and has been deemed insecure because headers are commonly + logged in plaintext. mutualTLS: type: mutualTLS - description: Client certificate authentication is a secure authentication scheme where the client presents a valid certificate to the server for authentication. The server validates the certificate and grants access to the requested resource, but stolen certificates can be used by anyone. + description: | + Client certificate authentication is a secure authentication scheme where the client presents a valid certificate to the server + for authentication. The server validates the certificate and grants access to the requested resource, but stolen certificates can be + used by anyone. pasetoAuth: type: http scheme: bearer bearerFormat: PASETO - description: Platform-Agnostic Security Tokens (PASETO) is a secure alternative to JWT that is resistant to many cryptographic vulnerabilities. PASETO tokens use versioned protocols that specify modern cryptographic algorithms. + description: | + Platform-Agnostic Security Tokens (PASETO) is a secure alternative to JWT that is resistant to many cryptographic vulnerabilities. + PASETO tokens use versioned protocols that specify modern cryptographic algorithms. verifiableCredentials: type: http scheme: bearer bearerFormat: VC-JWT - description: W3C Verifiable Credentials 2.0 with proof field is a standard for expressing verifiable credentials as signed JWT tokens. The integrity and authenticity of the credential can be cryptographically verified. + description: | + W3C Verifiable Credentials 2.0 with proof field is a standard for expressing verifiable credentials as signed JWT tokens. + The integrity and authenticity of the credential can be cryptographically verified. hmacAuth: type: apiKey in: header name: X-HMAC-Signature - description: HMAC authentication uses a shared secret key to create a signature of the request content using a secure hash algorithm (SHA256, SHA384, SHA512, SHA3-256, SHA3-384, or SHA3-512). The server verifies this signature to authenticate the request. + description: | + HMAC authentication uses a shared secret key to create a signature of the request content using a secure hash algorithm (SHA256, + SHA384, SHA512, SHA3-256, SHA3-384, or SHA3-512). The server verifies this signature to authenticate the request. operations: standard_delete: responses: From 059fd752ee3ea85c59d16824fb88c433de516db7 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Wed, 21 May 2025 22:31:17 +1000 Subject: [PATCH 05/10] chore: use camelCase instea of snake_case Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 272 ++++++++++++++++-------------------- 1 file changed, 124 insertions(+), 148 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index 877a534..b6277ca 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -16,12 +16,12 @@ servers: - url: http://localhost/tea/v1 description: Local development paths: - /product/{tei_urn}: + /product/{teiUrn}: patch: description: Update an existing TEA Product entry operationId: updateTeaProduct parameters: - - $ref: '#/components/parameters/tea_product_identifier' + - $ref: '#/components/parameters/teaProductIdentifier' requestBody: required: true content: @@ -29,7 +29,7 @@ paths: schema: type: object properties: - product_name: + productName: type: string barcode: type: string @@ -37,8 +37,8 @@ paths: sku: type: string description: Product SKU - vendor_uuid: - $ref: '#/components/schemas/type_uuid' + vendorUuid: + $ref: '#/components/schemas/typeUuid' description: Vendor UUID purl: type: string @@ -47,10 +47,10 @@ paths: basic: summary: Basic product update value: - product_name: Updated Product Name + productName: Updated Product Name barcode: '123456789012' sku: PROD-001 - vendor_uuid: 123e4567-e89b-12d3-a456-426614174000 + vendorUuid: 123e4567-e89b-12d3-a456-426614174000 purl: pkg:generic/example@1.0.0 responses: '200': @@ -58,7 +58,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/tea_product' + $ref: '#/components/schemas/teaProduct' '400': description: Invalid request body content: @@ -69,15 +69,12 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Product - security: - - bearerAuth: [] - - basicAuth: [] delete: description: Delete a TEA Product entry operationId: deleteTeaProduct parameters: - - $ref: '#/components/parameters/tea_product_identifier' - $ref: '#/components/operations/standard_delete' + - $ref: '#/components/parameters/teaProductIdentifier' + $ref: '#/components/operations/standardDelete' tags: - TEA Product /product: @@ -91,7 +88,7 @@ paths: schema: type: object properties: - product_name: + productName: type: string barcode: type: string @@ -99,13 +96,13 @@ paths: sku: type: string description: Product SKU - vendor_uuid: - $ref: '#/components/schemas/type_uuid' + vendorUuid: + $ref: '#/components/schemas/typeUuid' description: Vendor UUID purl: type: string description: Package URL (PURL) - tei_urns: + teiUrns: type: array items: type: string @@ -113,21 +110,21 @@ paths: pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ description: List of TEI URNs associated with this product required: - - product_name + - productName examples: basic: summary: Basic product creation value: - product_name: Example Product + productName: Example Product full: summary: Full product creation with all fields value: - product_name: Complete Product Example + productName: Complete Product Example barcode: '123456789012' sku: PROD-001 - vendor_uuid: 123e4567-e89b-12d3-a456-426614174000 + vendorUuid: 123e4567-e89b-12d3-a456-426614174000 purl: pkg:generic/example@1.0.0 - tei_urns: + teiUrns: - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 responses: '201': @@ -138,24 +135,24 @@ paths: type: object properties: identifier: - $ref: '#/components/schemas/type_uuid' - product_name: + $ref: '#/components/schemas/typeUuid' + productName: type: string barcode: type: string sku: type: string - vendor_uuid: - $ref: '#/components/schemas/type_uuid' + vendorUuid: + $ref: '#/components/schemas/typeUuid' purl: type: string - tei_urns: + teiUrns: type: array items: type: string required: - identifier - - product_name + - productName '400': description: Invalid request body content: @@ -166,9 +163,6 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Product - security: - - bearerAuth: [] - - basicAuth: [] /component: post: description: Create a new TEA Component entry @@ -180,8 +174,8 @@ paths: schema: type: object properties: - tea_product_identifier: - $ref: '#/components/schemas/type_uuid' + teaProductIdentifier: + $ref: '#/components/schemas/typeUuid' name: type: string description: Component name @@ -191,13 +185,13 @@ paths: $ref: '#/components/schemas/identifier' description: List of identifiers for the component required: - - tea_product_identifier + - teaProductIdentifier - name examples: basic: summary: Basic component creation value: - tea_product_identifier: 123e4567-e89b-12d3-a456-426614174000 + teaProductIdentifier: 123e4567-e89b-12d3-a456-426614174000 name: Example Component identifiers: - idType: purl @@ -208,7 +202,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/tea_component' + $ref: '#/components/schemas/teaComponent' '400': description: Invalid parameters content: @@ -219,15 +213,12 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Component - security: - - bearerAuth: [] - - basicAuth: [] - /component/{component_identifier}: + /component/{componentIdentifier}: patch: description: Update an existing TEA Component entry operationId: updateTeaComponent parameters: - - name: component_identifier + - name: componentIdentifier in: path required: true description: UUID of TEA Component in the TEA server @@ -255,7 +246,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/tea_component' + $ref: '#/components/schemas/teaComponent' '400': description: Invalid request body content: @@ -266,21 +257,18 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Component - security: - - bearerAuth: [] - - basicAuth: [] delete: description: Delete a TEA Component entry operationId: deleteTeaComponent parameters: - - name: component_identifier + - name: componentIdentifier in: path required: true description: UUID of TEA Component in the TEA server schema: type: string format: uuid - $ref: '#/components/operations/standard_delete' + $ref: '#/components/operations/standardDelete' tags: - TEA Component /release: @@ -294,18 +282,18 @@ paths: schema: type: object properties: - component_identifier: - $ref: '#/components/schemas/type_uuid' + componentIdentifier: + $ref: '#/components/schemas/typeUuid' description: UUID of the TEA Component version: type: string description: Version number - release_date: + releaseDate: type: string format: date-time example: '2024-03-20T15:30:00Z' description: Timestamp of the release - pre_release: + preRelease: type: boolean description: Flag indicating pre-release status identifiers: @@ -314,17 +302,17 @@ paths: $ref: '#/components/schemas/identifier' description: List of identifiers for the release required: - - component_identifier + - componentIdentifier - version - - release_date + - releaseDate examples: basic: summary: Basic release creation value: - component_identifier: 123e4567-e89b-12d3-a456-426614174000 + componentIdentifier: 123e4567-e89b-12d3-a456-426614174000 version: 1.0.0 - release_date: '2024-03-20T15:30:00Z' - pre_release: false + releaseDate: '2024-03-20T15:30:00Z' + preRelease: false identifiers: - idType: purl idValue: pkg:maven/org.example/component@1.0.0 @@ -334,7 +322,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/tea_release' + $ref: '#/components/schemas/teaRelease' '400': description: Invalid parameters content: @@ -345,15 +333,12 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Release - security: - - bearerAuth: [] - - basicAuth: [] - /release/{release_identifier}: + /release/{releaseIdentifier}: patch: description: Update an existing TEA Release entry operationId: updateTeaRelease parameters: - - name: release_identifier + - name: releaseIdentifier in: path required: true description: UUID of TEA Release in the TEA server @@ -370,11 +355,11 @@ paths: version: type: string description: Version number - release_date: + releaseDate: type: string format: date-time example: '2024-03-20T15:30:00Z' - pre_release: + preRelease: type: boolean description: May only be set to false if previously true identifiers: @@ -387,7 +372,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/tea_release' + $ref: '#/components/schemas/teaRelease' '400': description: Invalid request body content: @@ -398,21 +383,18 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Release - security: - - bearerAuth: [] - - basicAuth: [] delete: description: Delete a TEA Release entry operationId: deleteTeaRelease parameters: - - name: release_identifier + - name: releaseIdentifier in: path required: true description: UUID of TEA Release in the TEA server schema: type: string format: uuid - $ref: '#/components/operations/standard_delete' + $ref: '#/components/operations/standardDelete' tags: - TEA Release /collection: @@ -426,11 +408,11 @@ paths: schema: type: object properties: - release_identifier: - $ref: '#/components/schemas/type_uuid' + releaseIdentifier: + $ref: '#/components/schemas/typeUuid' description: UUID of the TEA Release - update_reason: - $ref: '#/components/schemas/collection_update_reason' + updateReason: + $ref: '#/components/schemas/collectionUpdateReason' description: Reason for collection creation or update artifacts: type: array @@ -441,10 +423,10 @@ paths: type: string description: Artifact name type: - $ref: '#/components/schemas/type_tea_collection_artifact_type' + $ref: '#/components/schemas/typeTeaCollectionArtifactType' description: Type of artifact author: - $ref: '#/components/schemas/type_author' + $ref: '#/components/schemas/typeAuthor' description: Author of the artifact formats: type: array @@ -454,46 +436,46 @@ paths: description: type: string description: A free text describing the artifact - mime_type: + mimeType: type: string description: The MIME type of the document - artifact_url: + artifactUrl: type: string format: uri description: Direct download URL for the artifact - artifact_size_in_bytes: + artifactSizeInBytes: type: integer format: int64 description: Size of the artifact in bytes - artifact_checksums: + artifactChecksums: type: array items: - $ref: '#/components/schemas/artifact_checksum' + $ref: '#/components/schemas/artifactChecksum' description: List of checksums for the artifact - signature_url: + signatureUrl: type: string format: uri description: URL for an external signature of the artifact required: - description - - mime_type - - artifact_url - - artifact_size_in_bytes - - artifact_checksums + - mimeType + - artifactUrl + - artifactSizeInBytes + - artifactChecksums required: - name - type - author - formats required: - - release_identifier - - update_reason + - releaseIdentifier + - updateReason examples: basic: summary: Basic collection creation value: - release_identifier: 123e4567-e89b-12d3-a456-426614174000 - update_reason: + releaseIdentifier: 123e4567-e89b-12d3-a456-426614174000 + updateReason: type: INITIAL_RELEASE comment: Initial release of collection artifacts: @@ -505,20 +487,20 @@ paths: organization: Example Org formats: - description: CycloneDX SBOM (XML) - mime_type: application/vnd.cyclonedx+xml - artifact_url: https://example.com/sbom.xml - artifact_size_in_bytes: 1024 - artifact_checksums: + mimeType: application/vnd.cyclonedx+xml + artifactUrl: https://example.com/sbom.xml + artifactSizeInBytes: 1024 + artifactChecksums: - algType: SHA-256 algValue: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 - signature_url: https://example.com/sbom.xml.sig + signatureUrl: https://example.com/sbom.xml.sig responses: '201': description: TEA Collection created successfully content: application/json: schema: - $ref: '#/components/schemas/tea_collection' + $ref: '#/components/schemas/teaCollection' '400': description: Invalid request body content: @@ -529,9 +511,6 @@ paths: $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Collection - security: - - bearerAuth: [] - - basicAuth: [] components: schemas: identifier: @@ -551,7 +530,7 @@ components: required: - idType - idValue - artifact_checksum: + artifactChecksum: type: object properties: algType: @@ -576,11 +555,11 @@ components: required: - algType - algValue - tea_product: + teaProduct: type: object properties: identifier: - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' description: A unique identifier for the TEA product name: type: string @@ -594,8 +573,8 @@ components: type: array description: List of TEA component UUIDs items: - $ref: '#/components/schemas/type_uuid' - tei_urns: + $ref: '#/components/schemas/typeUuid' + teiUrns: type: array items: type: string @@ -607,22 +586,22 @@ components: - name - identifiers - components - paginated_product_list: + paginatedProductList: allOf: - - $ref: '#/components/schemas/pagination_details' + - $ref: '#/components/schemas/paginationDetails' - type: object properties: results: type: array items: - $ref: '#/components/schemas/tea_product' - tea_component: + $ref: '#/components/schemas/teaProduct' + teaComponent: type: object description: A TEA component properties: uuid: description: A unique identifier for the TEA component - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' name: type: string description: Component name @@ -640,19 +619,19 @@ components: type: array description: List of UUIDs referencing TEA Release entries items: - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' required: - uuid - name - identifiers - versions - tea_release: + teaRelease: type: object description: A TEA release properties: uuid: description: A unique identifier for the TEA Component Release - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' version: description: Version number type: string @@ -670,17 +649,17 @@ components: description: List of identifiers for the component items: $ref: '#/components/schemas/identifier' - collection_references: + collectionReferences: type: array items: - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' description: Array of UUIDs referencing TEA Collection entries default: [] required: - uuid - version - releaseDate - collection_update_reason: + collectionUpdateReason: type: object description: Reason for the update to the TEA collection properties: @@ -698,14 +677,14 @@ components: description: Free text description required: - type - tea_collection: + teaCollection: type: object description: A collection of security-related documents properties: uuid: description: | UUID of the TEA Collection object. Note that this is equal to the UUID of the associated TEA Release object. - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' version: type: integer description: TEA Collection version, incremented each time its content changes. Versions start with 1. @@ -717,73 +696,73 @@ components: example: '2024-03-20T15:30:00Z' updateReason: description: Reason for the update/release of the TEA Collection object. - $ref: '#/components/schemas/collection_update_reason' + $ref: '#/components/schemas/collectionUpdateReason' artifacts: type: array description: List of TEA artifact objects. items: - $ref: '#/components/schemas/tea_artifact' + $ref: '#/components/schemas/teaArtifact' required: - uuid - version - releaseDate - updateReason - tea_artifact: + teaArtifact: type: object description: A security-related document properties: uuid: description: UUID of the TEA Artifact object. - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' name: type: string description: Artifact name type: description: Type of artifact - $ref: '#/components/schemas/type_tea_collection_artifact_type' + $ref: '#/components/schemas/typeTeaCollectionArtifactType' author: - $ref: '#/components/schemas/type_author' + $ref: '#/components/schemas/typeAuthor' description: Author of the artifact formats: type: array description: List of objects with the same content, but in different formats. items: - $ref: '#/components/schemas/artifact_format' + $ref: '#/components/schemas/artifactFormat' required: - uuid - name - type - author - formats - artifact_format: + artifactFormat: type: object description: A security-related document in a specific format properties: - mime_type: + mimeType: type: string description: The MIME type of the document description: type: string description: A free text describing the artifact - url: # Changed from artifact_url to match consumer + url: # Changed from artifactUrl to match consumer type: string format: uri description: Direct download URL for the artifact - signature_url: # Already matches consumer + signatureUrl: # Already matches consumer type: string format: uri description: Direct download URL for an external signature of the artifact - checksums: # Changed from artifact_checksums to match consumer + checksums: # Changed from artifactChecksums to match consumer type: array items: - $ref: '#/components/schemas/artifact_checksum' + $ref: '#/components/schemas/artifactChecksum' description: List of checksums for the artifact required: - - mime_type + - mimeType - description - url - checksums - type_author: + typeAuthor: type: object properties: name: @@ -797,7 +776,7 @@ components: - name - email - organization - type_tea_collection_artifact_type: + typeTeaCollectionArtifactType: type: string title: Type description: Specifies the type of external reference. @@ -845,10 +824,10 @@ components: - digital-signature - rfc-9116 - other - type_uuid: + typeUuid: type: string format: uuid - pagination_details: + paginationDetails: type: object properties: timestamp: @@ -899,24 +878,24 @@ components: type: integer format: int64 default: 100 - tei_urn: - name: tei_urn + teiUrn: + name: teiUrn description: Transparency Exchange Identifier (URN) in: path required: true schema: type: string pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ - tea_product_identifier: - name: tea_product_identifier + teaProductIdentifier: + name: teaProductIdentifier description: TEA Product Identifier in: path required: true schema: type: string format: uuid - tea_collection_identifier: - name: collection_identifier + teaCollectionIdentifier: + name: collectionIdentifier description: TEA Collection Identifier in: path required: true @@ -944,13 +923,13 @@ components: required: false schema: type: string - vendor_uuid: - name: vendor_uuid + vendorUuid: + name: vendorUuid description: Vendor UUID in: query required: false schema: - $ref: '#/components/schemas/type_uuid' + $ref: '#/components/schemas/typeUuid' id-type: name: idType description: Type of identifier specified in the `idValue` parameter @@ -1010,7 +989,7 @@ components: HMAC authentication uses a shared secret key to create a signature of the request content using a secure hash algorithm (SHA256, SHA384, SHA512, SHA3-256, SHA3-384, or SHA3-512). The server verifies this signature to authenticate the request. operations: - standard_delete: + standardDelete: responses: '204': description: Resource successfully deleted @@ -1018,9 +997,6 @@ components: $ref: '#/components/responses/401-unauthorized' '404': $ref: '#/components/responses/404-object-by-id-not-found' - security: - - bearerAuth: [] - - basicAuth: [] security: - bearerAuth: [] - basicAuth: [] From 72746cbe23b68a374437f413bf5cdad269ff10e0 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Wed, 21 May 2025 23:58:09 +1000 Subject: [PATCH 06/10] chore: pointless purl for publisher removed Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 167 ++++++++++++++++++++---------------- 1 file changed, 93 insertions(+), 74 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index b6277ca..581465f 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -21,7 +21,7 @@ paths: description: Update an existing TEA Product entry operationId: updateTeaProduct parameters: - - $ref: '#/components/parameters/teaProductIdentifier' + - $ref: '#/components/parameters/productIdentifier' requestBody: required: true content: @@ -40,9 +40,26 @@ paths: vendorUuid: $ref: '#/components/schemas/typeUuid' description: Vendor UUID - purl: + type: type: string - description: Package URL (PURL) + description: Package type (required) + namespace: + type: string + description: Package namespace (optional) + name: + type: string + description: Package name (required) + version: + type: string + description: Package version (optional) + qualifiers: + type: object + additionalProperties: + type: string + description: Qualifiers as key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) examples: basic: summary: Basic product update @@ -51,14 +68,31 @@ paths: barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 - purl: pkg:generic/example@1.0.0 + type: generic + name: example + version: 1.0.0 + full: + summary: Full product update with all PURL fields + value: + productName: Updated Product Name + barcode: '123456789012' + sku: PROD-001 + vendorUuid: 123e4567-e89b-12d3-a456-426614174000 + type: maven + namespace: org.example + name: component + version: 2.1.0 + qualifiers: + classifier: sources + repository_url: https://repo.example.com + subpath: src/main responses: '200': description: TEA Product updated successfully content: application/json: schema: - $ref: '#/components/schemas/teaProduct' + $ref: '#/components/schemas/product' '400': description: Invalid request body content: @@ -73,7 +107,7 @@ paths: description: Delete a TEA Product entry operationId: deleteTeaProduct parameters: - - $ref: '#/components/parameters/teaProductIdentifier' + - $ref: '#/components/parameters/productIdentifier' $ref: '#/components/operations/standardDelete' tags: - TEA Product @@ -99,9 +133,6 @@ paths: vendorUuid: $ref: '#/components/schemas/typeUuid' description: Vendor UUID - purl: - type: string - description: Package URL (PURL) teiUrns: type: array items: @@ -109,6 +140,26 @@ paths: description: Transparency Exchange Identifier URN pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ description: List of TEI URNs associated with this product + type: + type: string + description: Package type (required) + namespace: + type: string + description: Package namespace (optional) + name: + type: string + description: Package name (required) + version: + type: string + description: Package version (optional) + qualifiers: + type: object + additionalProperties: + type: string + description: Qualifiers as key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) required: - productName examples: @@ -116,6 +167,8 @@ paths: summary: Basic product creation value: productName: Example Product + type: generic + name: example full: summary: Full product creation with all fields value: @@ -123,12 +176,19 @@ paths: barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 - purl: pkg:generic/example@1.0.0 teiUrns: - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 + type: maven + namespace: org.example + name: component + version: 2.1.0 + qualifiers: + classifier: sources + repository_url: https://repo.example.com + subpath: src/main responses: '201': - description: TEA Product created successfully + description: Product created successfully content: application/json: schema: @@ -144,8 +204,6 @@ paths: type: string vendorUuid: $ref: '#/components/schemas/typeUuid' - purl: - type: string teiUrns: type: array items: @@ -174,7 +232,7 @@ paths: schema: type: object properties: - teaProductIdentifier: + productIdentifier: $ref: '#/components/schemas/typeUuid' name: type: string @@ -185,13 +243,13 @@ paths: $ref: '#/components/schemas/identifier' description: List of identifiers for the component required: - - teaProductIdentifier + - productIdentifier - name examples: basic: summary: Basic component creation value: - teaProductIdentifier: 123e4567-e89b-12d3-a456-426614174000 + productIdentifier: 123e4567-e89b-12d3-a456-426614174000 name: Example Component identifiers: - idType: purl @@ -202,7 +260,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/teaComponent' + $ref: '#/components/schemas/component' '400': description: Invalid parameters content: @@ -246,7 +304,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/teaComponent' + $ref: '#/components/schemas/component' '400': description: Invalid request body content: @@ -322,7 +380,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/teaRelease' + $ref: '#/components/schemas/release' '400': description: Invalid parameters content: @@ -372,7 +430,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/teaRelease' + $ref: '#/components/schemas/release' '400': description: Invalid request body content: @@ -423,7 +481,7 @@ paths: type: string description: Artifact name type: - $ref: '#/components/schemas/typeTeaCollectionArtifactType' + $ref: '#/components/schemas/typeCollectionArtifactType' description: Type of artifact author: $ref: '#/components/schemas/typeAuthor' @@ -500,7 +558,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/teaCollection' + $ref: '#/components/schemas/collection' '400': description: Invalid request body content: @@ -555,7 +613,7 @@ components: required: - algType - algValue - teaProduct: + product: type: object properties: identifier: @@ -586,16 +644,7 @@ components: - name - identifiers - components - paginatedProductList: - allOf: - - $ref: '#/components/schemas/paginationDetails' - - type: object - properties: - results: - type: array - items: - $ref: '#/components/schemas/teaProduct' - teaComponent: + component: type: object description: A TEA component properties: @@ -625,7 +674,7 @@ components: - name - identifiers - versions - teaRelease: + release: type: object description: A TEA release properties: @@ -677,7 +726,7 @@ components: description: Free text description required: - type - teaCollection: + collection: type: object description: A collection of security-related documents properties: @@ -701,13 +750,13 @@ components: type: array description: List of TEA artifact objects. items: - $ref: '#/components/schemas/teaArtifact' + $ref: '#/components/schemas/artifact' required: - uuid - version - releaseDate - updateReason - teaArtifact: + artifact: type: object description: A security-related document properties: @@ -719,7 +768,7 @@ components: description: Artifact name type: description: Type of artifact - $ref: '#/components/schemas/typeTeaCollectionArtifactType' + $ref: '#/components/schemas/typeCollectionArtifactType' author: $ref: '#/components/schemas/typeAuthor' description: Author of the artifact @@ -776,7 +825,7 @@ components: - name - email - organization - typeTeaCollectionArtifactType: + typeCollectionArtifactType: type: string title: Type description: Specifies the type of external reference. @@ -827,29 +876,6 @@ components: typeUuid: type: string format: uuid - paginationDetails: - type: object - properties: - timestamp: - type: string - format: date-time - example: '2024-03-20T15:30:00Z' - pageStartIndex: - type: integer - format: int64 - default: 0 - pageSize: - type: integer - format: int64 - default: 100 - totalResults: - type: integer - format: int64 - required: - - timestamp - - pageStartIndex - - pageSize - - totalResults responses: 401-unauthorized: description: Authentication required @@ -869,7 +895,7 @@ components: type: integer format: int64 default: 0 - page-size: + pageSize: name: pageSize description: Pagination size in: query @@ -886,15 +912,15 @@ components: schema: type: string pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ - teaProductIdentifier: - name: teaProductIdentifier + productIdentifier: + name: productIdentifier description: TEA Product Identifier in: path required: true schema: type: string format: uuid - teaCollectionIdentifier: + collectionIdentifier: name: collectionIdentifier description: TEA Collection Identifier in: path @@ -902,13 +928,6 @@ components: schema: type: string format: uuid - purl: - name: purl - description: Package URL (PURL) - in: query - required: false - schema: - type: string barcode: name: barcode description: Barcode @@ -930,7 +949,7 @@ components: required: false schema: $ref: '#/components/schemas/typeUuid' - id-type: + idType: name: idType description: Type of identifier specified in the `idValue` parameter in: query From eac17b686313f02cd3051b1f48b1c2832677f902 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Thu, 22 May 2025 00:21:49 +1000 Subject: [PATCH 07/10] chore: sync version and resolve name inconsistencies Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 57 ++++++++++++++----------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index 581465f..eabb4b6 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -11,7 +11,7 @@ info: license: name: Apache 2.0 url: https://github.com/CycloneDX/transparency-exchange-api/blob/main/LICENSE - version: 0.0.3 + version: 0.1.0-beta.1 servers: - url: http://localhost/tea/v1 description: Local development @@ -29,8 +29,9 @@ paths: schema: type: object properties: - productName: + name: type: string + description: Product name (required) barcode: type: string description: Barcode @@ -42,16 +43,13 @@ paths: description: Vendor UUID type: type: string - description: Package type (required) + description: Product type (required) namespace: type: string - description: Package namespace (optional) - name: - type: string - description: Package name (required) + description: Product namespace (optional) version: type: string - description: Package version (optional) + description: Product version (optional) qualifiers: type: object additionalProperties: @@ -64,23 +62,21 @@ paths: basic: summary: Basic product update value: - productName: Updated Product Name + name: Updated Product Name barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 type: generic - name: example version: 1.0.0 full: summary: Full product update with all PURL fields value: - productName: Updated Product Name + name: Updated Product Name barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 type: maven namespace: org.example - name: component version: 2.1.0 qualifiers: classifier: sources @@ -122,7 +118,7 @@ paths: schema: type: object properties: - productName: + name: type: string barcode: type: string @@ -142,16 +138,13 @@ paths: description: List of TEI URNs associated with this product type: type: string - description: Package type (required) + description: Product type (required) namespace: type: string - description: Package namespace (optional) - name: - type: string - description: Package name (required) + description: Product namespace (optional) version: type: string - description: Package version (optional) + description: Product version (optional) qualifiers: type: object additionalProperties: @@ -161,18 +154,17 @@ paths: type: string description: Subpath (optional) required: - - productName + - name examples: basic: summary: Basic product creation value: - productName: Example Product + name: Example Product type: generic - name: example full: summary: Full product creation with all fields value: - productName: Complete Product Example + name: Complete Product Example barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 @@ -180,7 +172,6 @@ paths: - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 type: maven namespace: org.example - name: component version: 2.1.0 qualifiers: classifier: sources @@ -497,15 +488,11 @@ paths: mimeType: type: string description: The MIME type of the document - artifactUrl: + url: type: string format: uri description: Direct download URL for the artifact - artifactSizeInBytes: - type: integer - format: int64 - description: Size of the artifact in bytes - artifactChecksums: + checksums: type: array items: $ref: '#/components/schemas/artifactChecksum' @@ -517,9 +504,8 @@ paths: required: - description - mimeType - - artifactUrl - - artifactSizeInBytes - - artifactChecksums + - url + - checksums required: - name - type @@ -546,9 +532,8 @@ paths: formats: - description: CycloneDX SBOM (XML) mimeType: application/vnd.cyclonedx+xml - artifactUrl: https://example.com/sbom.xml - artifactSizeInBytes: 1024 - artifactChecksums: + url: https://example.com/sbom.xml + checksums: - algType: SHA-256 algValue: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 signatureUrl: https://example.com/sbom.xml.sig From fafe58a36cfae285a23203b7808117501c5b6e01 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Thu, 22 May 2025 11:39:07 +1000 Subject: [PATCH 08/10] chore: align to Consumer udpate Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 54 ++++++++----------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index eabb4b6..e347640 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -815,49 +815,17 @@ components: title: Type description: Specifies the type of external reference. enum: - - vcs - - issue-tracker - - website - - advisories - - bom - - mailing-list - - social - - chat - - documentation - - support - - source-distribution - - distribution - - distribution-intake - - license - - build-meta - - build-system - - release-notes - - security-contact - - model-card - - log - - configuration - - evidence - - formulation - - attestation - - threat-model - - adversary-model - - risk-assessment - - vulnerability-assertion - - exploitability-statement - - pentest-report - - static-analysis-report - - dynamic-analysis-report - - runtime-analysis-report - - component-analysis-report - - maturity-report - - certification-report - - codified-infrastructure - - quality-metrics - - poam - - electronic-signature - - digital-signature - - rfc-9116 - - other + - ATTESTATION + - BOM + - BUILD_META + - CERTIFICATION + - FORMULATION + - LICENSE + - RELEASE_NOTES + - SECURITY_TXT + - THREAT_MODEL + - VULNERABILITIES + - OTHER typeUuid: type: string format: uuid From 926b98fbc085390699005b26e189d77cc92ba433 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Thu, 22 May 2025 23:05:47 +1000 Subject: [PATCH 09/10] chore: move requestBody into ref components Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 639 ++++++++++++++++++------------------ 1 file changed, 327 insertions(+), 312 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index e347640..8492cea 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -23,65 +23,7 @@ paths: parameters: - $ref: '#/components/parameters/productIdentifier' requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - name: - type: string - description: Product name (required) - barcode: - type: string - description: Barcode - sku: - type: string - description: Product SKU - vendorUuid: - $ref: '#/components/schemas/typeUuid' - description: Vendor UUID - type: - type: string - description: Product type (required) - namespace: - type: string - description: Product namespace (optional) - version: - type: string - description: Product version (optional) - qualifiers: - type: object - additionalProperties: - type: string - description: Qualifiers as key-value pairs (optional) - subpath: - type: string - description: Subpath (optional) - examples: - basic: - summary: Basic product update - value: - name: Updated Product Name - barcode: '123456789012' - sku: PROD-001 - vendorUuid: 123e4567-e89b-12d3-a456-426614174000 - type: generic - version: 1.0.0 - full: - summary: Full product update with all PURL fields - value: - name: Updated Product Name - barcode: '123456789012' - sku: PROD-001 - vendorUuid: 123e4567-e89b-12d3-a456-426614174000 - type: maven - namespace: org.example - version: 2.1.0 - qualifiers: - classifier: sources - repository_url: https://repo.example.com - subpath: src/main + $ref: '#/components/requestBodies/UpdateTeaProduct' responses: '200': description: TEA Product updated successfully @@ -112,71 +54,7 @@ paths: description: Create TEA Product entry for the supplied product identifier operationId: createTeaProduct requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - name: - type: string - barcode: - type: string - description: Barcode - sku: - type: string - description: Product SKU - vendorUuid: - $ref: '#/components/schemas/typeUuid' - description: Vendor UUID - teiUrns: - type: array - items: - type: string - description: Transparency Exchange Identifier URN - pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ - description: List of TEI URNs associated with this product - type: - type: string - description: Product type (required) - namespace: - type: string - description: Product namespace (optional) - version: - type: string - description: Product version (optional) - qualifiers: - type: object - additionalProperties: - type: string - description: Qualifiers as key-value pairs (optional) - subpath: - type: string - description: Subpath (optional) - required: - - name - examples: - basic: - summary: Basic product creation - value: - name: Example Product - type: generic - full: - summary: Full product creation with all fields - value: - name: Complete Product Example - barcode: '123456789012' - sku: PROD-001 - vendorUuid: 123e4567-e89b-12d3-a456-426614174000 - teiUrns: - - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 - type: maven - namespace: org.example - version: 2.1.0 - qualifiers: - classifier: sources - repository_url: https://repo.example.com - subpath: src/main + $ref: '#/components/requestBodies/CreateTeaProduct' responses: '201': description: Product created successfully @@ -217,34 +95,7 @@ paths: description: Create a new TEA Component entry operationId: createTeaComponent requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - productIdentifier: - $ref: '#/components/schemas/typeUuid' - name: - type: string - description: Component name - identifiers: - type: array - items: - $ref: '#/components/schemas/identifier' - description: List of identifiers for the component - required: - - productIdentifier - - name - examples: - basic: - summary: Basic component creation - value: - productIdentifier: 123e4567-e89b-12d3-a456-426614174000 - name: Example Component - identifiers: - - idType: purl - idValue: pkg:maven/org.example/component@1.0.0 + $ref: '#/components/requestBodies/CreateTeaComponent' responses: '201': description: TEA Component created successfully @@ -275,20 +126,7 @@ paths: type: string format: uuid requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - name: - type: string - description: Component name - identifiers: - type: array - items: - $ref: '#/components/schemas/identifier' - description: List of identifiers for the component + $ref: '#/components/requestBodies/UpdateTeaComponent' responses: '200': description: TEA Component updated successfully @@ -325,46 +163,7 @@ paths: description: Create a new TEA Release operationId: createTeaRelease requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - componentIdentifier: - $ref: '#/components/schemas/typeUuid' - description: UUID of the TEA Component - version: - type: string - description: Version number - releaseDate: - type: string - format: date-time - example: '2024-03-20T15:30:00Z' - description: Timestamp of the release - preRelease: - type: boolean - description: Flag indicating pre-release status - identifiers: - type: array - items: - $ref: '#/components/schemas/identifier' - description: List of identifiers for the release - required: - - componentIdentifier - - version - - releaseDate - examples: - basic: - summary: Basic release creation - value: - componentIdentifier: 123e4567-e89b-12d3-a456-426614174000 - version: 1.0.0 - releaseDate: '2024-03-20T15:30:00Z' - preRelease: false - identifiers: - - idType: purl - idValue: pkg:maven/org.example/component@1.0.0 + $ref: '#/components/requestBodies/CreateTeaRelease' responses: '201': description: TEA Release created successfully @@ -395,26 +194,7 @@ paths: type: string format: uuid requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - version: - type: string - description: Version number - releaseDate: - type: string - format: date-time - example: '2024-03-20T15:30:00Z' - preRelease: - type: boolean - description: May only be set to false if previously true - identifiers: - type: array - items: - $ref: '#/components/schemas/identifier' + $ref: '#/components/requestBodies/UpdateTeaRelease' responses: '200': description: TEA Release updated successfully @@ -451,92 +231,7 @@ paths: description: Create a new TEA Collection operationId: createTeaCollection requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - releaseIdentifier: - $ref: '#/components/schemas/typeUuid' - description: UUID of the TEA Release - updateReason: - $ref: '#/components/schemas/collectionUpdateReason' - description: Reason for collection creation or update - artifacts: - type: array - items: - type: object - properties: - name: - type: string - description: Artifact name - type: - $ref: '#/components/schemas/typeCollectionArtifactType' - description: Type of artifact - author: - $ref: '#/components/schemas/typeAuthor' - description: Author of the artifact - formats: - type: array - items: - type: object - properties: - description: - type: string - description: A free text describing the artifact - mimeType: - type: string - description: The MIME type of the document - url: - type: string - format: uri - description: Direct download URL for the artifact - checksums: - type: array - items: - $ref: '#/components/schemas/artifactChecksum' - description: List of checksums for the artifact - signatureUrl: - type: string - format: uri - description: URL for an external signature of the artifact - required: - - description - - mimeType - - url - - checksums - required: - - name - - type - - author - - formats - required: - - releaseIdentifier - - updateReason - examples: - basic: - summary: Basic collection creation - value: - releaseIdentifier: 123e4567-e89b-12d3-a456-426614174000 - updateReason: - type: INITIAL_RELEASE - comment: Initial release of collection - artifacts: - - name: Example SBOM - type: bom - author: - name: John Doe - email: john.doe@example.com - organization: Example Org - formats: - - description: CycloneDX SBOM (XML) - mimeType: application/vnd.cyclonedx+xml - url: https://example.com/sbom.xml - checksums: - - algType: SHA-256 - algValue: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 - signatureUrl: https://example.com/sbom.xml.sig + $ref: '#/components/requestBodies/CreateTeaCollection' responses: '201': description: TEA Collection created successfully @@ -988,3 +683,323 @@ tags: externalDocs: description: Transparency Exchange API specification url: https://github.com/CycloneDX/transparency-exchange-api + requestBodies: + UpdateTeaProduct: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Product name (required) + barcode: + type: string + description: Barcode + sku: + type: string + description: Product SKU + vendorUuid: + $ref: '#/components/schemas/typeUuid' + description: Vendor UUID + type: + type: string + description: Product type (required) + namespace: + type: string + description: Product namespace (optional) + version: + type: string + description: Product version (optional) + qualifiers: + type: object + additionalProperties: + type: string + description: Qualifiers as key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) + examples: + basic: + summary: Basic product update + value: + name: Updated Product Name + barcode: '123456789012' + sku: PROD-001 + vendorUuid: 123e4567-e89b-12d3-a456-426614174000 + type: generic + version: 1.0.0 + full: + summary: Full product update with all PURL fields + value: + name: Updated Product Name + barcode: '123456789012' + sku: PROD-001 + vendorUuid: 123e4567-e89b-12d3-a456-426614174000 + type: maven + namespace: org.example + version: 2.1.0 + qualifiers: + classifier: sources + repository_url: https://repo.example.com + subpath: src/main + CreateTeaProduct: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + barcode: + type: string + description: Barcode + sku: + type: string + description: Product SKU + vendorUuid: + $ref: '#/components/schemas/typeUuid' + description: Vendor UUID + teiUrns: + type: array + items: + type: string + description: Transparency Exchange Identifier URN + pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ + description: List of TEI URNs associated with this product + type: + type: string + description: Product type (required) + namespace: + type: string + description: Product namespace (optional) + version: + type: string + description: Product version (optional) + qualifiers: + type: object + additionalProperties: + type: string + description: Qualifiers as key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) + required: + - name + examples: + basic: + summary: Basic product creation + value: + name: Example Product + type: generic + full: + summary: Full product creation with all fields + value: + name: Complete Product Example + barcode: '123456789012' + sku: PROD-001 + vendorUuid: 123e4567-e89b-12d3-a456-426614174000 + teiUrns: + - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 + type: maven + namespace: org.example + version: 2.1.0 + qualifiers: + classifier: sources + repository_url: https://repo.example.com + subpath: src/main + CreateTeaComponent: + required: true + content: + application/json: + schema: + type: object + properties: + productIdentifier: + $ref: '#/components/schemas/typeUuid' + name: + type: string + description: Component name + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the component + required: + - productIdentifier + - name + examples: + basic: + summary: Basic component creation + value: + productIdentifier: 123e4567-e89b-12d3-a456-426614174000 + name: Example Component + identifiers: + - idType: purl + idValue: pkg:maven/org.example/component@1.0.0 + UpdateTeaComponent: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Component name + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the component + CreateTeaRelease: + required: true + content: + application/json: + schema: + type: object + properties: + componentIdentifier: + $ref: '#/components/schemas/typeUuid' + description: UUID of the TEA Component + version: + type: string + description: Version number + releaseDate: + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + description: Timestamp of the release + preRelease: + type: boolean + description: Flag indicating pre-release status + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the release + required: + - componentIdentifier + - version + - releaseDate + examples: + basic: + summary: Basic release creation + value: + componentIdentifier: 123e4567-e89b-12d3-a456-426614174000 + version: 1.0.0 + releaseDate: '2024-03-20T15:30:00Z' + preRelease: false + identifiers: + - idType: purl + idValue: pkg:maven/org.example/component@1.0.0 + UpdateTeaRelease: + required: true + content: + application/json: + schema: + type: object + properties: + version: + type: string + description: Version number + releaseDate: + type: string + format: date-time + example: '2024-03-20T15:30:00Z' + preRelease: + type: boolean + description: May only be set to false if previously true + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + CreateTeaCollection: + required: true + content: + application/json: + schema: + type: object + properties: + releaseIdentifier: + $ref: '#/components/schemas/typeUuid' + description: UUID of the TEA Release + updateReason: + $ref: '#/components/schemas/collectionUpdateReason' + description: Reason for collection creation or update + artifacts: + type: array + items: + type: object + properties: + name: + type: string + description: Artifact name + type: + $ref: '#/components/schemas/typeCollectionArtifactType' + description: Type of artifact + author: + $ref: '#/components/schemas/typeAuthor' + description: Author of the artifact + formats: + type: array + items: + type: object + properties: + description: + type: string + description: A free text describing the artifact + mimeType: + type: string + description: The MIME type of the document + url: + type: string + format: uri + description: Direct download URL for the artifact + checksums: + type: array + items: + $ref: '#/components/schemas/artifactChecksum' + description: List of checksums for the artifact + signatureUrl: + type: string + format: uri + description: URL for an external signature of the artifact + required: + - description + - mimeType + - url + - checksums + required: + - name + - type + - author + - formats + required: + - releaseIdentifier + - updateReason + examples: + basic: + summary: Basic collection creation + value: + releaseIdentifier: 123e4567-e89b-12d3-a456-426614174000 + updateReason: + type: INITIAL_RELEASE + comment: Initial release of collection + artifacts: + - name: Example SBOM + type: bom + author: + name: John Doe + email: john.doe@example.com + organization: Example Org + formats: + - description: CycloneDX SBOM (XML) + mimeType: application/vnd.cyclonedx+xml + url: https://example.com/sbom.xml + checksums: + - algType: SHA-256 + algValue: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 + signatureUrl: https://example.com/sbom.xml.sig From 59d2ba53d04af8581cd5adcebd1c1b8159c5f445 Mon Sep 17 00:00:00 2001 From: Chris Langton Date: Sun, 25 May 2025 21:23:05 +1000 Subject: [PATCH 10/10] feat: Refactor to use $ref for operations on product, component, and release paths Signed-off-by: Chris Langton --- spec/publisher/openapi.yaml | 508 ++++++++++++++++++++++++++---------- 1 file changed, 366 insertions(+), 142 deletions(-) diff --git a/spec/publisher/openapi.yaml b/spec/publisher/openapi.yaml index 8492cea..2953082 100644 --- a/spec/publisher/openapi.yaml +++ b/spec/publisher/openapi.yaml @@ -16,25 +16,25 @@ servers: - url: http://localhost/tea/v1 description: Local development paths: - /product/{teiUrn}: + /product/{uuid}: patch: description: Update an existing TEA Product entry operationId: updateTeaProduct parameters: - - $ref: '#/components/parameters/productIdentifier' + - name: uuid + in: path + required: true + description: UUID of TEA Product in the TEA server + schema: + type: string + format: uuid requestBody: $ref: '#/components/requestBodies/UpdateTeaProduct' responses: '200': - description: TEA Product updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/product' + $ref: '#/components/responses/200-tea-product-updated' '400': - description: Invalid request body - content: - application/json: {} + $ref: '#/components/responses/400-invalid-request-body' '401': $ref: '#/components/responses/401-unauthorized' '404': @@ -45,7 +45,13 @@ paths: description: Delete a TEA Product entry operationId: deleteTeaProduct parameters: - - $ref: '#/components/parameters/productIdentifier' + - name: uuid + in: path + required: true + description: UUID of TEA Product in the TEA server + schema: + type: string + format: uuid $ref: '#/components/operations/standardDelete' tags: - TEA Product @@ -57,33 +63,9 @@ paths: $ref: '#/components/requestBodies/CreateTeaProduct' responses: '201': - description: Product created successfully - content: - application/json: - schema: - type: object - properties: - identifier: - $ref: '#/components/schemas/typeUuid' - productName: - type: string - barcode: - type: string - sku: - type: string - vendorUuid: - $ref: '#/components/schemas/typeUuid' - teiUrns: - type: array - items: - type: string - required: - - identifier - - productName + $ref: '#/components/responses/201-tea-product-created' '400': - description: Invalid request body - content: - application/json: {} + $ref: '#/components/responses/400-invalid-request-body' '401': $ref: '#/components/responses/401-unauthorized' '404': @@ -98,27 +80,21 @@ paths: $ref: '#/components/requestBodies/CreateTeaComponent' responses: '201': - description: TEA Component created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/component' + $ref: '#/components/responses/201-tea-component-created' '400': - description: Invalid parameters - content: - application/json: {} + $ref: '#/components/responses/400-invalid-parameters' '401': $ref: '#/components/responses/401-unauthorized' '404': $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Component - /component/{componentIdentifier}: + /component/{uuid}: patch: description: Update an existing TEA Component entry operationId: updateTeaComponent parameters: - - name: componentIdentifier + - name: uuid in: path required: true description: UUID of TEA Component in the TEA server @@ -129,15 +105,9 @@ paths: $ref: '#/components/requestBodies/UpdateTeaComponent' responses: '200': - description: TEA Component updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/component' + $ref: '#/components/responses/200-tea-component-updated' '400': - description: Invalid request body - content: - application/json: {} + $ref: '#/components/responses/400-invalid-request-body' '401': $ref: '#/components/responses/401-unauthorized' '404': @@ -148,7 +118,7 @@ paths: description: Delete a TEA Component entry operationId: deleteTeaComponent parameters: - - name: componentIdentifier + - name: uuid in: path required: true description: UUID of TEA Component in the TEA server @@ -166,27 +136,21 @@ paths: $ref: '#/components/requestBodies/CreateTeaRelease' responses: '201': - description: TEA Release created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/release' + $ref: '#/components/responses/201-tea-release-created' '400': - description: Invalid parameters - content: - application/json: {} + $ref: '#/components/responses/400-invalid-parameters' '401': $ref: '#/components/responses/401-unauthorized' '404': $ref: '#/components/responses/404-object-by-id-not-found' tags: - TEA Release - /release/{releaseIdentifier}: + /release/{uuid}: patch: description: Update an existing TEA Release entry operationId: updateTeaRelease parameters: - - name: releaseIdentifier + - name: uuid in: path required: true description: UUID of TEA Release in the TEA server @@ -197,15 +161,9 @@ paths: $ref: '#/components/requestBodies/UpdateTeaRelease' responses: '200': - description: TEA Release updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/release' + $ref: '#/components/responses/200-tea-release-updated' '400': - description: Invalid request body - content: - application/json: {} + $ref: '#/components/responses/400-invalid-request-body' '401': $ref: '#/components/responses/401-unauthorized' '404': @@ -216,7 +174,7 @@ paths: description: Delete a TEA Release entry operationId: deleteTeaRelease parameters: - - name: releaseIdentifier + - name: uuid in: path required: true description: UUID of TEA Release in the TEA server @@ -234,15 +192,9 @@ paths: $ref: '#/components/requestBodies/CreateTeaCollection' responses: '201': - description: TEA Collection created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/collection' + $ref: '#/components/responses/201-tea-collection-created' '400': - description: Invalid request body - content: - application/json: {} + $ref: '#/components/responses/400-invalid-request-body' '401': $ref: '#/components/responses/401-unauthorized' '404': @@ -256,12 +208,13 @@ components: description: An identifier with a specified type properties: idType: - description: Type of identifier, e.g. `tei`, `purl`, `cpe` + description: Type of identifier, e.g. `tei`, `purl`, `cpe`, `swid` type: string enum: - cpe - tei - purl + - swid idValue: description: Identifier value type: string @@ -275,8 +228,6 @@ components: description: Checksum algorithm type: string enum: - - MD5 - - SHA-1 - SHA-256 - SHA-384 - SHA-512 @@ -302,23 +253,44 @@ components: name: type: string description: Product name + barcode: + type: string + description: Barcode + sku: + type: string + description: Product SKU + vendorUuid: + $ref: '#/components/schemas/typeUuid' + description: Vendor UUID identifiers: type: array description: List of identifiers for the product items: $ref: '#/components/schemas/identifier' + type: + $ref: '#/components/schemas/typePackage' + description: Product type + namespace: + type: string + description: Product namespace (optional) + version: + type: string + description: Product version (optional) + qualifiers: + type: array + items: + type: object + additionalProperties: + type: string + description: Array of qualifier objects containing related key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) components: type: array description: List of TEA component UUIDs items: $ref: '#/components/schemas/typeUuid' - teiUrns: - type: array - items: - type: string - description: Transparency Exchange Identifier URN - pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ - description: List of TEI URNs associated with this product required: - identifier - name @@ -524,7 +496,136 @@ components: typeUuid: type: string format: uuid + typePackage: + type: string + description: Package type following PURL specification + enum: + - alpm + - apk + - bitbucket + - bitnami + - cargo + - cocoapods + - composer + - conan + - conda + - cpan + - cran + - deb + - docker + - gem + - generic + - github + - golang + - hackage + - hex + - huggingface + - luarocks + - maven + - mlflow + - npm + - nuget + - oci + - pub + - pypi + - qpkg + - rpm + - swid + - swift responses: + 200-tea-product-updated: + description: TEA Product updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/product' + 200-tea-component-updated: + description: TEA Component updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/component' + 200-tea-release-updated: + description: TEA Release updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/release' + 201-tea-product-created: + description: Product created successfully + content: + application/json: + schema: + type: object + properties: + identifier: + $ref: '#/components/schemas/typeUuid' + description: Unique identifier for the created product + name: + type: string + description: Product name + barcode: + type: string + description: Barcode + sku: + type: string + description: Product SKU + vendorUuid: + $ref: '#/components/schemas/typeUuid' + description: Vendor UUID + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the product (TEI, CPE, SWID, etc.) + type: + $ref: '#/components/schemas/typePackage' + description: Product type + namespace: + type: string + description: Product namespace (optional) + version: + type: string + description: Product version (optional) + qualifiers: + type: array + items: + type: object + additionalProperties: + type: string + description: Array of qualifier objects containing related key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) + required: + - identifier + - name + 201-tea-component-created: + description: TEA Component created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/component' + 201-tea-release-created: + description: TEA Release created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/release' + 201-tea-collection-created: + description: TEA Collection created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/collection' + 400-invalid-request-body: + description: Invalid request body + content: + application/json: {} + 400-invalid-parameters: + description: Invalid parameters + content: + application/json: {} 401-unauthorized: description: Authentication required content: @@ -562,7 +663,7 @@ components: pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ productIdentifier: name: productIdentifier - description: TEA Product Identifier + description: Customer unique Product Identifier in: path required: true schema: @@ -664,25 +765,6 @@ components: $ref: '#/components/responses/401-unauthorized' '404': $ref: '#/components/responses/404-object-by-id-not-found' -security: - - bearerAuth: [] - - basicAuth: [] - - mutualTLS: [] - - pasetoAuth: [] - - verifiableCredentials: [] - - hmacAuth: [] -tags: - - name: TEA Product - description: Operations related to TEA Products - - name: TEA Component - description: Operations related to TEA Components - - name: TEA Release - description: Operations related to TEA Releases - - name: TEA Collection - description: Operations related to TEA Collections -externalDocs: - description: Transparency Exchange API specification - url: https://github.com/CycloneDX/transparency-exchange-api requestBodies: UpdateTeaProduct: required: true @@ -703,8 +785,13 @@ externalDocs: vendorUuid: $ref: '#/components/schemas/typeUuid' description: Vendor UUID + identifiers: + type: array + items: + $ref: '#/components/schemas/identifier' + description: List of identifiers for the product (TEI, CPE, SWID, etc.) type: - type: string + $ref: '#/components/schemas/typePackage' description: Product type (required) namespace: type: string @@ -713,10 +800,12 @@ externalDocs: type: string description: Product version (optional) qualifiers: - type: object - additionalProperties: - type: string - description: Qualifiers as key-value pairs (optional) + type: array + items: + type: object + additionalProperties: + type: string + description: Array of qualifier objects containing related key-value pairs (optional) subpath: type: string description: Subpath (optional) @@ -730,19 +819,27 @@ externalDocs: vendorUuid: 123e4567-e89b-12d3-a456-426614174000 type: generic version: 1.0.0 + qualifiers: + - os: linux + arch: x86_64 full: - summary: Full product update with all PURL fields + summary: Full product update with all fields value: name: Updated Product Name barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 + identifiers: + - idType: tei + idValue: urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 + - idType: cpe + idValue: cpe:2.3:a:example:product:2.1.0:*:*:*:*:*:*:* type: maven namespace: org.example version: 2.1.0 qualifiers: - classifier: sources - repository_url: https://repo.example.com + - classifier: sources + repository_url: https://repo.example.com subpath: src/main CreateTeaProduct: required: true @@ -762,15 +859,13 @@ externalDocs: vendorUuid: $ref: '#/components/schemas/typeUuid' description: Vendor UUID - teiUrns: + identifiers: type: array items: - type: string - description: Transparency Exchange Identifier URN - pattern: ^urn:tei:[a-zA-Z0-9]+:[a-zA-Z0-9\.-]+:.+$ - description: List of TEI URNs associated with this product + $ref: '#/components/schemas/identifier' + description: List of identifiers for the product (TEI, CPE, SWID, etc.) type: - type: string + $ref: '#/components/schemas/typePackage' description: Product type (required) namespace: type: string @@ -779,10 +874,12 @@ externalDocs: type: string description: Product version (optional) qualifiers: - type: object - additionalProperties: - type: string - description: Qualifiers as key-value pairs (optional) + type: array + items: + type: object + additionalProperties: + type: string + description: Array of qualifier objects containing related key-value pairs (optional) subpath: type: string description: Subpath (optional) @@ -794,6 +891,9 @@ externalDocs: value: name: Example Product type: generic + qualifiers: + - os: linux + arch: x86_64 full: summary: Full product creation with all fields value: @@ -801,14 +901,17 @@ externalDocs: barcode: '123456789012' sku: PROD-001 vendorUuid: 123e4567-e89b-12d3-a456-426614174000 - teiUrns: - - urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 + identifiers: + - idType: tei + idValue: urn:tei:uuid:example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1 + - idType: cpe + idValue: cpe:2.3:a:example:product:2.1.0:*:*:*:*:*:*:* type: maven namespace: org.example version: 2.1.0 qualifiers: - classifier: sources - repository_url: https://repo.example.com + - classifier: sources + repository_url: https://repo.example.com subpath: src/main CreateTeaComponent: required: true @@ -826,7 +929,26 @@ externalDocs: type: array items: $ref: '#/components/schemas/identifier' - description: List of identifiers for the component + description: List of identifiers for the component (TEI, CPE, SWID, etc.) + type: + $ref: '#/components/schemas/typePackage' + description: Component type (required) + namespace: + type: string + description: Component namespace (optional) + version: + type: string + description: Component version (optional) + qualifiers: + type: array + items: + type: object + additionalProperties: + type: string + description: Array of qualifier objects containing related key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) required: - productIdentifier - name @@ -836,9 +958,27 @@ externalDocs: value: productIdentifier: 123e4567-e89b-12d3-a456-426614174000 name: Example Component + type: maven + qualifiers: + - classifier: jar + type: binary + full: + summary: Full component creation with all fields + value: + productIdentifier: 123e4567-e89b-12d3-a456-426614174000 + name: Apache Log4j Core Component identifiers: - - idType: purl - idValue: pkg:maven/org.example/component@1.0.0 + - idType: cpe + idValue: cpe:2.3:a:apache:log4j:2.17.1:*:*:*:*:*:*:* + - idType: tei + idValue: urn:tei:uuid:apache.org:log4j-core-component + type: maven + namespace: org.apache.logging.log4j + version: 2.17.1 + qualifiers: + - classifier: sources + repository_url: https://github.com/apache/logging-log4j2 + subpath: log4j-core UpdateTeaComponent: required: true content: @@ -853,7 +993,54 @@ externalDocs: type: array items: $ref: '#/components/schemas/identifier' - description: List of identifiers for the component + description: List of identifiers for the component (TEI, CPE, SWID, etc.) + type: + $ref: '#/components/schemas/typePackage' + description: Component type + namespace: + type: string + description: Component namespace (optional) + version: + type: string + description: Component version (optional) + qualifiers: + type: array + items: + type: object + additionalProperties: + type: string + description: Array of qualifier objects containing related key-value pairs (optional) + subpath: + type: string + description: Subpath (optional) + examples: + basic: + summary: Basic component update + value: + name: Updated Component Name + type: maven + version: 2.0.0 + qualifiers: + - classifier: jar + type: binary + full: + summary: Full component update with all fields + value: + name: Updated Apache Log4j Core Component + identifiers: + - idType: cpe + idValue: cpe:2.3:a:apache:log4j:2.18.0:*:*:*:*:*:*:* + - idType: tei + idValue: urn:tei:uuid:apache.org:log4j-core-component-updated + type: maven + namespace: org.apache.logging.log4j + version: 2.18.0 + qualifiers: + - classifier: sources + repository_url: https://github.com/apache/logging-log4j2 + - type: library + scope: compile + subpath: log4j-core CreateTeaRelease: required: true content: @@ -863,7 +1050,7 @@ externalDocs: properties: componentIdentifier: $ref: '#/components/schemas/typeUuid' - description: UUID of the TEA Component + description: Customer unique identifier of the TEA Component version: type: string description: Version number @@ -916,6 +1103,24 @@ externalDocs: type: array items: $ref: '#/components/schemas/identifier' + examples: + basic: + summary: Basic release update + value: + version: 1.0.1 + releaseDate: '2024-03-21T10:15:00Z' + preRelease: false + full: + summary: Full release update with identifiers + value: + version: 2.0.0 + releaseDate: '2024-04-15T14:30:00Z' + preRelease: false + identifiers: + - idType: purl + idValue: pkg:maven/org.example/component@2.0.0 + - idType: cpe + idValue: cpe:2.3:a:example:component:2.0.0:*:*:*:*:*:*:* CreateTeaCollection: required: true content: @@ -925,7 +1130,7 @@ externalDocs: properties: releaseIdentifier: $ref: '#/components/schemas/typeUuid' - description: UUID of the TEA Release + description: Customer unique identifier of the TEA Release updateReason: $ref: '#/components/schemas/collectionUpdateReason' description: Reason for collection creation or update @@ -990,7 +1195,7 @@ externalDocs: comment: Initial release of collection artifacts: - name: Example SBOM - type: bom + type: BOM author: name: John Doe email: john.doe@example.com @@ -1003,3 +1208,22 @@ externalDocs: - algType: SHA-256 algValue: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 signatureUrl: https://example.com/sbom.xml.sig +security: + - bearerAuth: [] + - basicAuth: [] + - mutualTLS: [] + - pasetoAuth: [] + - verifiableCredentials: [] + - hmacAuth: [] +tags: + - name: TEA Product + description: Operations related to TEA Products + - name: TEA Component + description: Operations related to TEA Components + - name: TEA Release + description: Operations related to TEA Releases + - name: TEA Collection + description: Operations related to TEA Collections +externalDocs: + description: Transparency Exchange API specification + url: https://github.com/CycloneDX/transparency-exchange-api