diff --git a/CHANGELOG.md b/CHANGELOG.md index b0d1c3e..707749b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.34.0] - 2026-04-01 +### Added +- Added `error_message` and `error_code` fields to `ComponentLicenseInfo` message in license responses for error handling at the individual component level +- Added error response example to license API README.md documentation +- Added `component_url` field to `ComponentLicenseInfo` message providing a URL linking to the component's source or repository page +- Added `is_spdx_approved` and `url` fields to `LicenseInfo` message indicating SPDX approval status and linking to the license reference page + ## [0.33.0] - 2026-03-26 ### Added - Added `License` nested message to `HFHResponse.Version` with `name`, `spdx_id`, `is_spdx_approved`, and `url` fields @@ -255,6 +262,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Vulnerabilities - Added REST endpoint support for each service also +[0.34.0]: https://github.com/scanoss/papi/compare/v0.33.0...v0.34.0 [0.33.0]: https://github.com/scanoss/papi/compare/v0.32.1...v0.33.0 [0.32.1]: https://github.com/scanoss/papi/compare/v0.32.0...v0.32.1 [0.32.0]: https://github.com/scanoss/papi/compare/v0.31.0...v0.32.0 diff --git a/api/licensesv2/scanoss-licenses.pb.go b/api/licensesv2/scanoss-licenses.pb.go index 32eb8f2..6a7c5f1 100644 --- a/api/licensesv2/scanoss-licenses.pb.go +++ b/api/licensesv2/scanoss-licenses.pb.go @@ -577,7 +577,11 @@ type LicenseInfo struct { // Best human-readable license name (normalized when possible) // - For SPDX licenses: Official SPDX name (e.g., "MIT License", "GNU General Public License v2.0 only") // - For non SPDX licenses: Best normalized name from SCANOSS database or original statement - FullName string `protobuf:"bytes,2,opt,name=full_name,proto3" json:"full_name,omitempty"` + FullName string `protobuf:"bytes,2,opt,name=full_name,proto3" json:"full_name,omitempty"` + // Indicates whether the license is approved by the SPDX License List + IsSpdxApproved bool `protobuf:"varint,3,opt,name=is_spdx_approved,proto3" json:"is_spdx_approved,omitempty"` + // URL to the license text or reference page (e.g., SPDX license page or original license source) + Url string `protobuf:"bytes,4,opt,name=url,proto3" json:"url,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -626,6 +630,20 @@ func (x *LicenseInfo) GetFullName() string { return "" } +func (x *LicenseInfo) GetIsSpdxApproved() bool { + if x != nil { + return x.IsSpdxApproved + } + return false +} + +func (x *LicenseInfo) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + // Comprehensive license metadata container. // // Provides detailed information about a specific license including SPDX registry data, @@ -766,7 +784,13 @@ type ComponentLicenseInfo struct { // SPDX expression when licensing terms are clearly determinable from source analysis Statement string `protobuf:"bytes,4,opt,name=statement,proto3" json:"statement,omitempty"` // Individual licenses identified in the component - Licenses []*LicenseInfo `protobuf:"bytes,5,rep,name=licenses,proto3" json:"licenses,omitempty"` + Licenses []*LicenseInfo `protobuf:"bytes,5,rep,name=licenses,proto3" json:"licenses,omitempty"` + // Optional error message describing what went wrong during component processing + ErrorMessage *string `protobuf:"bytes,8,opt,name=error_message,proto3,oneof" json:"error_message,omitempty"` + // Optional error code indicating the type of error encountered + ErrorCode *commonv2.ErrorCode `protobuf:"varint,9,opt,name=error_code,proto3,enum=scanoss.api.common.v2.ErrorCode,oneof" json:"error_code,omitempty"` + // Component URL + ComponentUrl string `protobuf:"bytes,10,opt,name=component_url,proto3" json:"component_url,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -836,6 +860,27 @@ func (x *ComponentLicenseInfo) GetLicenses() []*LicenseInfo { return nil } +func (x *ComponentLicenseInfo) GetErrorMessage() string { + if x != nil && x.ErrorMessage != nil { + return *x.ErrorMessage + } + return "" +} + +func (x *ComponentLicenseInfo) GetErrorCode() commonv2.ErrorCode { + if x != nil && x.ErrorCode != nil { + return *x.ErrorCode + } + return commonv2.ErrorCode(0) +} + +func (x *ComponentLicenseInfo) GetComponentUrl() string { + if x != nil { + return x.ComponentUrl + } + return "" +} + // Cross-reference information for SPDX license URLs. // // Contains metadata about license reference URLs and their compliance with SPDX @@ -1096,17 +1141,18 @@ var File_scanoss_api_licenses_v2_scanoss_licenses_proto protoreflect.FileDescrip const file_scanoss_api_licenses_v2_scanoss_licenses_proto_rawDesc = "" + "\n" + - ".scanoss/api/licenses/v2/scanoss-licenses.proto\x12\x17scanoss.api.licenses.v2\x1a*scanoss/api/common/v2/scanoss-common.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xd0\x03\n" + + ".scanoss/api/licenses/v2/scanoss-licenses.proto\x12\x17scanoss.api.licenses.v2\x1a*scanoss/api/common/v2/scanoss-common.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xf9\a\n" + "\x18ComponentLicenseResponse\x12K\n" + "\tcomponent\x18\x01 \x01(\v2-.scanoss.api.licenses.v2.ComponentLicenseInfoR\tcomponent\x12=\n" + - "\x06status\x18\x02 \x01(\v2%.scanoss.api.common.v2.StatusResponseR\x06status:\xa7\x02\x92A\xa3\x02\n" + - "\xa0\x02J\x9d\x02{\"component\":{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\"}]}, \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}\"\xfd\x04\n" + + "\x06status\x18\x02 \x01(\v2%.scanoss.api.common.v2.StatusResponseR\x06status:\xd0\x06\x92A\xcc\x06\n" + + "\xc9\x062\xa0\x03Success example. For error cases, the component block includes error_message and error_code fields, e.g.: {\\\"component\\\":{\\\"purl\\\":\\\"pkg:github/scanoss/unknown-component\\\",\\\"requirement\\\":\\\"\\\",\\\"version\\\":\\\"\\\",\\\"statement\\\":\\\"\\\",\\\"licenses\\\":[],\\\"component_url\\\":\\\"\\\",\\\"error_message\\\":\\\"Component version not found\\\",\\\"error_code\\\":\\\"VERSION_NOT_FOUND\\\"},\\\"status\\\":{\\\"status\\\":\\\"SUCCESS\\\",\\\"message\\\":\\\"Success\\\"}}J\xa3\x03{\"component\":{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/GPL-2.0-only.html\"}], \"component_url\": \"https://github.com/scanoss/engine\"}, \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}\"\xa8\n" + + "\n" + "\x19ComponentsLicenseResponse\x12M\n" + "\n" + "components\x18\x01 \x03(\v2-.scanoss.api.licenses.v2.ComponentLicenseInfoR\n" + "components\x12=\n" + - "\x06status\x18\x02 \x01(\v2%.scanoss.api.common.v2.StatusResponseR\x06status:\xd1\x03\x92A\xcd\x03\n" + - "\xca\x03J\xc7\x03{\"components\":[{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\"}]}, {\"purl\": \"pkg:github/scanoss/scanoss.py@v1.30.0\",\"requirement\": \"\",\"version\": \"v1.30.0\",\"statement\": \"MIT\", \"licenses\": [{\"id\": \"MIT\",\"full_name\": \"MIT License\"}]} ], \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}\"\x9a\x01\n" + + "\x06status\x18\x02 \x01(\v2%.scanoss.api.common.v2.StatusResponseR\x06status:\xfc\b\x92A\xf8\b\n" + + "\xf5\b2\xa3\x03Success example. For error cases, the component block includes error_message and error_code fields, e.g.: {\\\"components\\\":[{\\\"purl\\\":\\\"pkg:github/scanoss/unknown-component\\\",\\\"requirement\\\":\\\"\\\",\\\"version\\\":\\\"\\\",\\\"statement\\\":\\\"\\\",\\\"licenses\\\":[],\\\"component_url\\\":\\\"\\\",\\\"error_message\\\":\\\"Component version not found\\\",\\\"error_code\\\":\\\"VERSION_NOT_FOUND\\\"}],\\\"status\\\":{\\\"status\\\":\\\"SUCCESS\\\",\\\"message\\\":\\\"Success\\\"}}J\xcc\x05{\"components\":[{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/GPL-2.0-only.html\"}], \"component_url\": \"https://github.com/scanoss/engine\"}, {\"purl\": \"pkg:github/scanoss/scanoss.py@v1.30.0\",\"requirement\": \"\",\"version\": \"v1.30.0\",\"statement\": \"MIT\", \"licenses\": [{\"id\": \"MIT\",\"full_name\": \"MIT License\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/MIT.html\"}], \"component_url\": \"https://github.com/scanoss/scanoss.py\"}], \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}\"\x9a\x01\n" + "\x16LicenseDetailsResponse\x12A\n" + "\alicense\x18\x01 \x01(\v2'.scanoss.api.licenses.v2.LicenseDetailsR\alicense\x12=\n" + "\x06status\x18\x02 \x01(\v2%.scanoss.api.common.v2.StatusResponseR\x06status\"\x96\x01\n" + @@ -1153,24 +1199,34 @@ const file_scanoss_api_licenses_v2_scanoss_licenses_proto_rawDesc = "" + "\fOSADLUseCase\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12(\n" + "\x0fobligation_text\x18\x02 \x01(\tR\x0fobligation_text\x12(\n" + - "\x0fobligation_json\x18\x03 \x01(\tR\x0fobligation_json\"\x8a\x01\n" + + "\x0fobligation_json\x18\x03 \x01(\tR\x0fobligation_json\"\x9c\x02\n" + "\vLicenseInfo\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1c\n" + - "\tfull_name\x18\x02 \x01(\tR\tfull_name:M\x92AJ\n" + - "HJF{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\"}\"\xd1\x01\n" + + "\tfull_name\x18\x02 \x01(\tR\tfull_name\x12*\n" + + "\x10is_spdx_approved\x18\x03 \x01(\bR\x10is_spdx_approved\x12\x10\n" + + "\x03url\x18\x04 \x01(\tR\x03url:\xa0\x01\x92A\x9c\x01\n" + + "\x99\x01J\x96\x01{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/GPL-2.0-only.html\"}\"\xd1\x01\n" + "\x0eLicenseDetails\x12\x1c\n" + "\tfull_name\x18\x01 \x01(\tR\tfull_name\x128\n" + "\x04type\x18\x02 \x01(\x0e2$.scanoss.api.licenses.v2.LicenseTypeR\x04type\x121\n" + "\x04spdx\x18\x03 \x01(\v2\x1d.scanoss.api.licenses.v2.SPDXR\x04spdx\x124\n" + "\x05osadl\x18\x04 \x01(\v2\x1e.scanoss.api.licenses.v2.OSADLR\x05osadl\" \n" + "\x0eLicenseRequest\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\"\xc6\x01\n" + + "\x02id\x18\x01 \x01(\tR\x02id\"\xff\x02\n" + "\x14ComponentLicenseInfo\x12\x12\n" + "\x04purl\x18\x01 \x01(\tR\x04purl\x12 \n" + "\vrequirement\x18\x02 \x01(\tR\vrequirement\x12\x18\n" + "\aversion\x18\x03 \x01(\tR\aversion\x12\x1c\n" + "\tstatement\x18\x04 \x01(\tR\tstatement\x12@\n" + - "\blicenses\x18\x05 \x03(\v2$.scanoss.api.licenses.v2.LicenseInfoR\blicenses*l\n" + + "\blicenses\x18\x05 \x03(\v2$.scanoss.api.licenses.v2.LicenseInfoR\blicenses\x12)\n" + + "\rerror_message\x18\b \x01(\tH\x00R\rerror_message\x88\x01\x01\x12E\n" + + "\n" + + "error_code\x18\t \x01(\x0e2 .scanoss.api.common.v2.ErrorCodeH\x01R\n" + + "error_code\x88\x01\x01\x12$\n" + + "\rcomponent_url\x18\n" + + " \x01(\tR\rcomponent_urlB\x10\n" + + "\x0e_error_messageB\r\n" + + "\v_error_code*l\n" + "\vLicenseType\x12\v\n" + "\aUNKNOWN\x10\x00\x12\x0e\n" + "\n" + @@ -1220,10 +1276,11 @@ var file_scanoss_api_licenses_v2_scanoss_licenses_proto_goTypes = []any{ (*SPDX_SPDXException)(nil), // 12: scanoss.api.licenses.v2.SPDX.SPDXException (*OSADL_OSADLUseCase)(nil), // 13: scanoss.api.licenses.v2.OSADL.OSADLUseCase (*commonv2.StatusResponse)(nil), // 14: scanoss.api.common.v2.StatusResponse - (*commonv2.EchoRequest)(nil), // 15: scanoss.api.common.v2.EchoRequest - (*commonv2.ComponentRequest)(nil), // 16: scanoss.api.common.v2.ComponentRequest - (*commonv2.ComponentsRequest)(nil), // 17: scanoss.api.common.v2.ComponentsRequest - (*commonv2.EchoResponse)(nil), // 18: scanoss.api.common.v2.EchoResponse + (commonv2.ErrorCode)(0), // 15: scanoss.api.common.v2.ErrorCode + (*commonv2.EchoRequest)(nil), // 16: scanoss.api.common.v2.EchoRequest + (*commonv2.ComponentRequest)(nil), // 17: scanoss.api.common.v2.ComponentRequest + (*commonv2.ComponentsRequest)(nil), // 18: scanoss.api.common.v2.ComponentsRequest + (*commonv2.EchoResponse)(nil), // 19: scanoss.api.common.v2.EchoResponse } var file_scanoss_api_licenses_v2_scanoss_licenses_proto_depIdxs = []int32{ 10, // 0: scanoss.api.licenses.v2.ComponentLicenseResponse.component:type_name -> scanoss.api.licenses.v2.ComponentLicenseInfo @@ -1241,21 +1298,22 @@ var file_scanoss_api_licenses_v2_scanoss_licenses_proto_depIdxs = []int32{ 5, // 12: scanoss.api.licenses.v2.LicenseDetails.spdx:type_name -> scanoss.api.licenses.v2.SPDX 6, // 13: scanoss.api.licenses.v2.LicenseDetails.osadl:type_name -> scanoss.api.licenses.v2.OSADL 7, // 14: scanoss.api.licenses.v2.ComponentLicenseInfo.licenses:type_name -> scanoss.api.licenses.v2.LicenseInfo - 15, // 15: scanoss.api.licenses.v2.License.Echo:input_type -> scanoss.api.common.v2.EchoRequest - 16, // 16: scanoss.api.licenses.v2.License.GetComponentLicenses:input_type -> scanoss.api.common.v2.ComponentRequest - 17, // 17: scanoss.api.licenses.v2.License.GetComponentsLicenses:input_type -> scanoss.api.common.v2.ComponentsRequest - 9, // 18: scanoss.api.licenses.v2.License.GetDetails:input_type -> scanoss.api.licenses.v2.LicenseRequest - 9, // 19: scanoss.api.licenses.v2.License.GetObligations:input_type -> scanoss.api.licenses.v2.LicenseRequest - 18, // 20: scanoss.api.licenses.v2.License.Echo:output_type -> scanoss.api.common.v2.EchoResponse - 1, // 21: scanoss.api.licenses.v2.License.GetComponentLicenses:output_type -> scanoss.api.licenses.v2.ComponentLicenseResponse - 2, // 22: scanoss.api.licenses.v2.License.GetComponentsLicenses:output_type -> scanoss.api.licenses.v2.ComponentsLicenseResponse - 3, // 23: scanoss.api.licenses.v2.License.GetDetails:output_type -> scanoss.api.licenses.v2.LicenseDetailsResponse - 4, // 24: scanoss.api.licenses.v2.License.GetObligations:output_type -> scanoss.api.licenses.v2.ObligationsResponse - 20, // [20:25] is the sub-list for method output_type - 15, // [15:20] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 15, // 15: scanoss.api.licenses.v2.ComponentLicenseInfo.error_code:type_name -> scanoss.api.common.v2.ErrorCode + 16, // 16: scanoss.api.licenses.v2.License.Echo:input_type -> scanoss.api.common.v2.EchoRequest + 17, // 17: scanoss.api.licenses.v2.License.GetComponentLicenses:input_type -> scanoss.api.common.v2.ComponentRequest + 18, // 18: scanoss.api.licenses.v2.License.GetComponentsLicenses:input_type -> scanoss.api.common.v2.ComponentsRequest + 9, // 19: scanoss.api.licenses.v2.License.GetDetails:input_type -> scanoss.api.licenses.v2.LicenseRequest + 9, // 20: scanoss.api.licenses.v2.License.GetObligations:input_type -> scanoss.api.licenses.v2.LicenseRequest + 19, // 21: scanoss.api.licenses.v2.License.Echo:output_type -> scanoss.api.common.v2.EchoResponse + 1, // 22: scanoss.api.licenses.v2.License.GetComponentLicenses:output_type -> scanoss.api.licenses.v2.ComponentLicenseResponse + 2, // 23: scanoss.api.licenses.v2.License.GetComponentsLicenses:output_type -> scanoss.api.licenses.v2.ComponentsLicenseResponse + 3, // 24: scanoss.api.licenses.v2.License.GetDetails:output_type -> scanoss.api.licenses.v2.LicenseDetailsResponse + 4, // 25: scanoss.api.licenses.v2.License.GetObligations:output_type -> scanoss.api.licenses.v2.ObligationsResponse + 21, // [21:26] is the sub-list for method output_type + 16, // [16:21] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_scanoss_api_licenses_v2_scanoss_licenses_proto_init() } @@ -1263,6 +1321,7 @@ func file_scanoss_api_licenses_v2_scanoss_licenses_proto_init() { if File_scanoss_api_licenses_v2_scanoss_licenses_proto != nil { return } + file_scanoss_api_licenses_v2_scanoss_licenses_proto_msgTypes[9].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/protobuf/scanoss/api/licenses/v2/README.md b/protobuf/scanoss/api/licenses/v2/README.md index b2515cd..53213cb 100644 --- a/protobuf/scanoss/api/licenses/v2/README.md +++ b/protobuf/scanoss/api/licenses/v2/README.md @@ -24,9 +24,14 @@ The method returns license information in two complementary formats: The response includes these fields: - `purl` field: the requested component -- `licenses` array: Always contains individual license objects found in the component +- `licenses` array: Always contains individual license objects found in the component. Each license object includes: + - `id`: SPDX identifier or licenseRef + - `full_name`: Human-readable license name + - `is_spdx_approved`: Whether the license is approved by the SPDX License List + - `url`: URL to the license text or reference page - `statement` field: Contains SPDX expression when licensing terms are clearly determinable from source analysis - `version` field: Shows the specific version that was analyzed +- `component_url` field: URL linking to the component's source or repository page - `requirement` field: Echoes the client's version constraint from the request ### Response Examples @@ -45,17 +50,22 @@ This allows consumers to understand all licensing obligations present in the com { "component": { "purl": "pkg:github/ffmpeg/ffmpeg@n7.0", + "component_url": "https://github.com/ffmpeg/ffmpeg", "requirement": "", "version": "n7.0", "statement": "", "licenses": [ { "id": "LGPL-2.1-or-later", - "full_name": "GNU Lesser General Public License v2.1 or later" + "full_name": "GNU Lesser General Public License v2.1 or later", + "is_spdx_approved": true, + "url": "https://spdx.org/licenses/LGPL-2.1-or-later.html" }, { "id": "GPL-2.0-or-later", - "full_name": "GNU General Public License v2.0 or later" + "full_name": "GNU General Public License v2.0 or later", + "is_spdx_approved": true, + "url": "https://spdx.org/licenses/GPL-2.0-or-later.html" } ] }, @@ -82,12 +92,13 @@ Individual license objects are also provided for detailed analysis. { "component": { "purl": "pkg:maven/ch.qos.logback/logback-classic@1.5.0", + "component_url": "https://github.com/qos-ch/logback", "requirement": "", "version": "1.5.0", "statement": "EPL-1.0 OR LGPL-2.1-only", "licenses": [ - {"id": "EPL-1.0", "full_name": "Eclipse Public License 1.0"}, - {"id": "LGPL-2.1-only", "full_name": "GNU Lesser General Public License v2.1 only"} + {"id": "EPL-1.0", "full_name": "Eclipse Public License 1.0", "is_spdx_approved": true, "url": "https://spdx.org/licenses/EPL-1.0.html"}, + {"id": "LGPL-2.1-only", "full_name": "GNU Lesser General Public License v2.1 only", "is_spdx_approved": true, "url": "https://spdx.org/licenses/LGPL-2.1-only.html"} ] }, "status": { @@ -110,12 +121,13 @@ This indicates users must comply with both licenses, generating the SPDX express { "component": { "purl": "pkg:github/openssl/openssl@1.1.1n", + "component_url": "https://github.com/openssl/openssl", "requirement": "", "version": "1.1.1n", "statement": "OpenSSL AND SSLeay", "licenses": [ - {"id": "OpenSSL", "full_name": "OpenSSL License"}, - {"id": "SSLeay", "full_name": "Original SSLeay License"} + {"id": "OpenSSL", "full_name": "OpenSSL License", "is_spdx_approved": false, "url": "https://www.openssl.org/source/license-openssl-ssleay.txt"}, + {"id": "SSLeay", "full_name": "Original SSLeay License", "is_spdx_approved": false, "url": "https://www.openssl.org/source/license-openssl-ssleay.txt"} ] }, "status": { @@ -127,6 +139,27 @@ This indicates users must comply with both licenses, generating the SPDX express +#### Error in component +When a component cannot be processed, the response includes `error_message` and `error_code` fields. The remaining fields will be empty since the component could not be resolved: +```json +{ + "component": { + "purl": "pkg:github/scanoss/unknown-component", + "component_url": "", + "requirement": "", + "version": "", + "statement": "", + "licenses": [], + "error_message": "Component version not found", + "error_code": "VERSION_NOT_FOUND" + }, + "status": { + "status": "SUCCESS", + "message": "Licenses Successfully retrieved" + } +} +``` + ## GetComponentsLicenses Batch version of GetLicenses - retrieves license information for multiple components in a single request. diff --git a/protobuf/scanoss/api/licenses/v2/scanoss-licenses.proto b/protobuf/scanoss/api/licenses/v2/scanoss-licenses.proto index a33521e..49a815a 100644 --- a/protobuf/scanoss/api/licenses/v2/scanoss-licenses.proto +++ b/protobuf/scanoss/api/licenses/v2/scanoss-licenses.proto @@ -128,7 +128,8 @@ service License { message ComponentLicenseResponse { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { json_schema: { - example: "{\"component\":{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\"}]}, \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}"; + example: "{\"component\":{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/GPL-2.0-only.html\"}], \"component_url\": \"https://github.com/scanoss/engine\"}, \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}"; + description: "Success example. For error cases, the component block includes error_message and error_code fields, e.g.: {\\\"component\\\":{\\\"purl\\\":\\\"pkg:github/scanoss/unknown-component\\\",\\\"requirement\\\":\\\"\\\",\\\"version\\\":\\\"\\\",\\\"statement\\\":\\\"\\\",\\\"licenses\\\":[],\\\"component_url\\\":\\\"\\\",\\\"error_message\\\":\\\"Component version not found\\\",\\\"error_code\\\":\\\"VERSION_NOT_FOUND\\\"},\\\"status\\\":{\\\"status\\\":\\\"SUCCESS\\\",\\\"message\\\":\\\"Success\\\"}}"; } }; // License info for the component @@ -145,7 +146,8 @@ message ComponentLicenseResponse { message ComponentsLicenseResponse { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { json_schema: { - example: "{\"components\":[{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\"}]}, {\"purl\": \"pkg:github/scanoss/scanoss.py@v1.30.0\",\"requirement\": \"\",\"version\": \"v1.30.0\",\"statement\": \"MIT\", \"licenses\": [{\"id\": \"MIT\",\"full_name\": \"MIT License\"}]} ], \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}"; + example: "{\"components\":[{\"purl\": \"pkg:github/scanoss/engine@1.0.0\", \"requirement\": \"\", \"version\": \"1.0.0\", \"statement\": \"GPL-2.0\", \"licenses\": [{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/GPL-2.0-only.html\"}], \"component_url\": \"https://github.com/scanoss/engine\"}, {\"purl\": \"pkg:github/scanoss/scanoss.py@v1.30.0\",\"requirement\": \"\",\"version\": \"v1.30.0\",\"statement\": \"MIT\", \"licenses\": [{\"id\": \"MIT\",\"full_name\": \"MIT License\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/MIT.html\"}], \"component_url\": \"https://github.com/scanoss/scanoss.py\"}], \"status\": {\"status\": \"SUCCESS\", \"message\": \"Licenses Successfully retrieved\"}}"; + description: "Success example. For error cases, the component block includes error_message and error_code fields, e.g.: {\\\"components\\\":[{\\\"purl\\\":\\\"pkg:github/scanoss/unknown-component\\\",\\\"requirement\\\":\\\"\\\",\\\"version\\\":\\\"\\\",\\\"statement\\\":\\\"\\\",\\\"licenses\\\":[],\\\"component_url\\\":\\\"\\\",\\\"error_message\\\":\\\"Component version not found\\\",\\\"error_code\\\":\\\"VERSION_NOT_FOUND\\\"}],\\\"status\\\":{\\\"status\\\":\\\"SUCCESS\\\",\\\"message\\\":\\\"Success\\\"}}"; } }; // License info for each component in the batch @@ -309,7 +311,7 @@ message OSADL { message LicenseInfo { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { json_schema: { - example: "{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\"}" + example: "{\"id\": \"GPL-2.0\", \"full_name\": \"GNU General Public License v2.0 only\", \"is_spdx_approved\": true, \"url\": \"https://spdx.org/licenses/GPL-2.0-only.html\"}" } }; @@ -322,6 +324,11 @@ message LicenseInfo { // - For SPDX licenses: Official SPDX name (e.g., "MIT License", "GNU General Public License v2.0 only") // - For non SPDX licenses: Best normalized name from SCANOSS database or original statement string full_name = 2 [json_name = "full_name"]; + + // Indicates whether the license is approved by the SPDX License List + bool is_spdx_approved = 3 [json_name = "is_spdx_approved"]; + // URL to the license text or reference page (e.g., SPDX license page or original license source) + string url = 4; } /* @@ -372,4 +379,10 @@ message ComponentLicenseInfo { string statement = 4; // Individual licenses identified in the component repeated LicenseInfo licenses = 5; + // Optional error message describing what went wrong during component processing + optional string error_message = 8 [json_name = "error_message"]; + // Optional error code indicating the type of error encountered + optional common.v2.ErrorCode error_code = 9 [json_name = "error_code"]; + // Component URL + string component_url = 10 [json_name = "component_url"]; } \ No newline at end of file diff --git a/protobuf/scanoss/api/licenses/v2/scanoss-licenses.swagger.json b/protobuf/scanoss/api/licenses/v2/scanoss-licenses.swagger.json index dcbbab0..c3545d7 100644 --- a/protobuf/scanoss/api/licenses/v2/scanoss-licenses.swagger.json +++ b/protobuf/scanoss/api/licenses/v2/scanoss-licenses.swagger.json @@ -364,6 +364,18 @@ "$ref": "#/definitions/v2LicenseInfo" }, "title": "Individual licenses identified in the component" + }, + "error_message": { + "type": "string", + "title": "Optional error message describing what went wrong during component processing" + }, + "error_code": { + "$ref": "#/definitions/v2ErrorCode", + "title": "Optional error code indicating the type of error encountered" + }, + "component_url": { + "type": "string", + "title": "Component URL" } }, "description": "License information for a specific component identified by PURL and version." @@ -379,9 +391,12 @@ "licenses": [ { "id": "GPL-2.0", - "full_name": "GNU General Public License v2.0 only" + "full_name": "GNU General Public License v2.0 only", + "is_spdx_approved": true, + "url": "https://spdx.org/licenses/GPL-2.0-only.html" } - ] + ], + "component_url": "https://github.com/scanoss/engine" }, "status": { "status": "SUCCESS", @@ -397,7 +412,7 @@ "$ref": "#/definitions/v2StatusResponse" } }, - "description": "Response message for GetComponentLicenses method.\n\nContains license information for a single software component including\ndiscovered licenses and SPDX expressions when determinable." + "description": "Success example. For error cases, the component block includes error_message and error_code fields, e.g.: {\\\"component\\\":{\\\"purl\\\":\\\"pkg:github/scanoss/unknown-component\\\",\\\"requirement\\\":\\\"\\\",\\\"version\\\":\\\"\\\",\\\"statement\\\":\\\"\\\",\\\"licenses\\\":[],\\\"component_url\\\":\\\"\\\",\\\"error_message\\\":\\\"Component version not found\\\",\\\"error_code\\\":\\\"VERSION_NOT_FOUND\\\"},\\\"status\\\":{\\\"status\\\":\\\"SUCCESS\\\",\\\"message\\\":\\\"Success\\\"}}" }, "v2ComponentRequest": { "type": "object", @@ -431,9 +446,12 @@ "licenses": [ { "id": "GPL-2.0", - "full_name": "GNU General Public License v2.0 only" + "full_name": "GNU General Public License v2.0 only", + "is_spdx_approved": true, + "url": "https://spdx.org/licenses/GPL-2.0-only.html" } - ] + ], + "component_url": "https://github.com/scanoss/engine" }, { "purl": "pkg:github/scanoss/scanoss.py@v1.30.0", @@ -443,9 +461,12 @@ "licenses": [ { "id": "MIT", - "full_name": "MIT License" + "full_name": "MIT License", + "is_spdx_approved": true, + "url": "https://spdx.org/licenses/MIT.html" } - ] + ], + "component_url": "https://github.com/scanoss/scanoss.py" } ], "status": { @@ -466,7 +487,7 @@ "$ref": "#/definitions/v2StatusResponse" } }, - "description": "Response message for GetComponentsLicenses method.\n\nContains license information for multiple software components processed\nin a single batch request. Each component is analyzed independently." + "description": "Success example. For error cases, the component block includes error_message and error_code fields, e.g.: {\\\"components\\\":[{\\\"purl\\\":\\\"pkg:github/scanoss/unknown-component\\\",\\\"requirement\\\":\\\"\\\",\\\"version\\\":\\\"\\\",\\\"statement\\\":\\\"\\\",\\\"licenses\\\":[],\\\"component_url\\\":\\\"\\\",\\\"error_message\\\":\\\"Component version not found\\\",\\\"error_code\\\":\\\"VERSION_NOT_FOUND\\\"}],\\\"status\\\":{\\\"status\\\":\\\"SUCCESS\\\",\\\"message\\\":\\\"Success\\\"}}" }, "v2ComponentsRequest": { "type": "object", @@ -513,6 +534,18 @@ }, "description": "Echo Message Response." }, + "v2ErrorCode": { + "type": "string", + "enum": [ + "INVALID_PURL", + "COMPONENT_NOT_FOUND", + "NO_INFO", + "INVALID_SEMVER", + "VERSION_NOT_FOUND" + ], + "default": "INVALID_PURL", + "description": "Error code enum for component analysis operations.\nRepresents the various error conditions that can occur during component processing and validation.\n\n - INVALID_PURL: The provided Package URL (PURL) is invalid or malformed\n - COMPONENT_NOT_FOUND: The requested component could not be found in the database\n - NO_INFO: No information is available for the requested component\n - INVALID_SEMVER: The provided semantic version (SemVer) is invalid or malformed\n - VERSION_NOT_FOUND: Component version not found" + }, "v2LicenseDetails": { "type": "object", "properties": { @@ -553,7 +586,9 @@ "type": "object", "example": { "id": "GPL-2.0", - "full_name": "GNU General Public License v2.0 only" + "full_name": "GNU General Public License v2.0 only", + "is_spdx_approved": true, + "url": "https://spdx.org/licenses/GPL-2.0-only.html" }, "properties": { "id": { @@ -563,6 +598,14 @@ "full_name": { "type": "string", "title": "Best human-readable license name (normalized when possible)\n- For SPDX licenses: Official SPDX name (e.g., \"MIT License\", \"GNU General Public License v2.0 only\")\n- For non SPDX licenses: Best normalized name from SCANOSS database or original statement" + }, + "is_spdx_approved": { + "type": "boolean", + "title": "Indicates whether the license is approved by the SPDX License List" + }, + "url": { + "type": "string", + "title": "URL to the license text or reference page (e.g., SPDX license page or original license source)" } }, "description": "Individual license identification with SPDX ID and human-readable name.\n\nProvides basic license information including standardized identifiers and \nhuman-readable names for discovered licenses in software components."