diff --git a/app-config.json b/app-config.json index eaccaf50..9bfb38e3 100644 --- a/app-config.json +++ b/app-config.json @@ -714,7 +714,7 @@ "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", "DigitalProductPassport"], + "type": ["DigitalProductPassport"], "dlrLinkTitle": "Cherries Product Passport", "dlrIdentificationKeyType": "gtin", "dlrVerificationPage": "http://localhost:3003/verify" @@ -1297,7 +1297,7 @@ "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", "DigitalIdentityAnchor"], + "type": ["DigitalIdentityAnchor"], "dlrLinkTitle": "DigitalIdentityAnchor", "dlrIdentificationKeyType": "gtin", "dlrVerificationPage": "http://localhost:3003/verify" @@ -1327,6 +1327,1735 @@ } ] }, + { + "name": "Issue DCC", + "id": "produce_product", + "components": [ + { + "name": "JsonForm", + "type": "EntryData", + "props": { + "schema": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["ConformityAttestation", "Attestation"], + "default": ["ConformityAttestation", "Attestation"], + "items": { + "type": "string", + "enum": ["ConformityAttestation", "Attestation"] + } + }, + "id": { + "example": "https://exampleCAB.com/38f73303-a39e-45a7-b8b7-e73517548f27", + "type": "string", + "format": "uri", + "description": "The globally unique ID of this conformity attestation." + }, + "name": { + "example": "Product GHG Footprint certificate in accordance with GBA Rulebook.", + "type": "string", + "description": "A human readable description of this conformity attestation" + }, + "assessorLevel": { + "type": "string", + "enum": ["Self", "Commercial", "Buyer", "Membership", "Unspecified", "3rdParty"], + "example": "Self", + "description": "Assurance code pertaining to assessor (relation to the object under assessment)" + }, + "assessmentLevel": { + "type": "string", + "enum": ["GovtApproval", "GlobalMRA", "Accredited", "Verified", "Validated", "Unspecified"], + "example": "GovtApproval", + "description": "Assurance pertaining to assessment (any authority or support for the assessment process)" + }, + "attestationType": { + "type": "string", + "enum": [ + "certification", + "declaration", + "inspection", + "testing", + "verification", + "validation", + "calibration" + ], + "example": "certification", + "description": "The type of criterion (optional or mandatory)." + }, + "description": { + "example": "SampleCAB Inc attests that the product class LiFePO4 EV batteries manufactured at Sample battery facility have reported GHG footprint that conform to the GBA rulebook version 1.5.", + "type": "string", + "description": "A textual description of the scope or purpose of this conformity attestation" + }, + "issuedToParty": { + "$ref": "#/$defs/Party", + "description": "The party to whom the conformity attestation was issued." + }, + "authorisation": { + "type": "array", + "items": { + "$ref": "#/$defs/Endorsement" + }, + "description": "The authority under which a conformity claim is issued. For example a national accreditation authority may authorise a test lab to issue test certificates about a product against a standard. " + }, + "conformityCertificate": { + "$ref": "#/$defs/SecureLink", + "description": "A reference to the human / printable version of this conformity attestation - typically represented as a PDF document. The document may have more details than are represented in the digital attestation." + }, + "auditableEvidence": { + "$ref": "#/$defs/SecureLink", + "description": "Auditable evidence supporting this assessment such as raw measurements, supporting documents. This is usually private data and would normally be encrypted." + }, + "scope": { + "$ref": "#/$defs/ConformityAssessmentScheme", + "description": "The scheme(s) under which this conformity assesment is issued. " + }, + "assessment": { + "type": "array", + "items": { + "$ref": "#/$defs/ConformityAssessment" + }, + "description": "The list of specific assessments made within this conformity attestation." + } + }, + "description": "A conformity attestation issued by a competent body that defines one or more assessments (eg carbon intensity) about a product (eg battery) against a specification (eg LCA method) defined in a standard or regulation.", + "required": ["id", "assessorLevel", "assessmentLevel", "attestationType"], + "$defs": { + "CredentialIssuer": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["CredentialIssuer"], + "default": ["CredentialIssuer"], + "items": { + "type": "string", + "enum": ["CredentialIssuer"] + } + }, + "id": { + "example": "did:web:identifiers.example-company.com:12345", + "type": "string", + "format": "uri", + "description": "The W3C DID of the issuer - should be a did:web or did:tdw" + }, + "name": { + "example": "Example Company Pty Ltd", + "type": "string", + "description": "The name of the issuer person or organisation" + }, + "otherIdentifier": { + "type": "array", + "items": { + "$ref": "#/$defs/Identifier" + }, + "description": "An optional list of other registered identifiers for this credential issuer " + } + }, + "description": "The issuer party (person or organisation) of a verifiable credential.", + "required": ["id", "name"] + }, + "Identifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Identifier"], + "default": ["Identifier"], + "items": { + "type": "string", + "enum": ["Identifier"] + } + }, + "id": { + "example": "https://id.gs1.org/01/09520123456788/21/12345", + "type": "string", + "format": "uri", + "description": "The globally unique ID of the entity as a resolvable URL according to ISO 18975. ExamplesProduct - id.gs1.org/01/09520123456788/21/12345 Party - abr.business.gov.au/ABN/View?abn=90664869327. Facility - did:web:facilities.example-company.com:123. " + }, + "name": { + "example": "EV battery 300Ah.", + "type": "string", + "description": "The registered name of the entity within the identifier scheme. Examples: product - EV battery 300Ah, Party - Sample Company Pty Ltd, Facility - Green Acres battery factory" + }, + "registeredId": { + "example": "90664869327", + "type": "string", + "description": "The registration number (alphanumeric) of the entity within the register. Unique within the register." + }, + "idScheme": { + "$ref": "#/$defs/IdentifierScheme", + "description": "The identifier scheme. Examples : Product - id.gs1.org/01, Party - business.gov.au/abn, Facility - did:web:facilities.acme.com. " + } + }, + "description": "The ID and Name of an identified entity such as a product, facility, party, standard, etc. If the identifier is a W3C DID then the corresponding DID document SHOULD include a serviceEndpoint of type \"IdentityResolver\". If the identifier is not a W3C DID then the id property SHOULD be an identity resolver URL.", + "required": ["id", "name"] + }, + "IdentifierScheme": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["IdentifierScheme"], + "default": ["IdentifierScheme"], + "items": { + "type": "string", + "enum": ["IdentifierScheme"] + } + }, + "id": { + "example": "https://id.gs1.org/01/", + "type": "string", + "format": "uri", + "description": "The globally unique identifier of the registration scheme. The scheme should be registered and discoverable from vocabulary.uncefact.org/identifierSchemes" + }, + "name": { + "example": "Global Trade Identification Number (GTIN)", + "type": "string", + "description": "The name of the identifier scheme. " + } + }, + "description": "An identifier registration scheme for products, facilities, or organisations. Typically operated by a state, national or global authority." + }, + "ConformityAttestation": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["ConformityAttestation", "Attestation"], + "default": ["ConformityAttestation", "Attestation"], + "items": { + "type": "string", + "enum": ["ConformityAttestation", "Attestation"] + } + }, + "id": { + "example": "https://exampleCAB.com/38f73303-a39e-45a7-b8b7-e73517548f27", + "type": "string", + "format": "uri", + "description": "The globally unique ID of this conformity attestation." + }, + "name": { + "example": "Product GHG Footprint certificate in accordance with GBA Rulebook.", + "type": "string", + "description": "A human readable description of this conformity attestation" + }, + "assessorLevel": { + "type": "string", + "enum": ["Self", "Commercial", "Buyer", "Membership", "Unspecified", "3rdParty"], + "example": "Self", + "description": "Assurance code pertaining to assessor (relation to the object under assessment)" + }, + "assessmentLevel": { + "type": "string", + "enum": ["GovtApproval", "GlobalMRA", "Accredited", "Verified", "Validated", "Unspecified"], + "example": "GovtApproval", + "description": "Assurance pertaining to assessment (any authority or support for the assessment process)" + }, + "attestationType": { + "type": "string", + "enum": [ + "certification", + "declaration", + "inspection", + "testing", + "verification", + "validation", + "calibration" + ], + "example": "certification", + "description": "The type of criterion (optional or mandatory)." + }, + "description": { + "example": "SampleCAB Inc attests that the product class LiFePO4 EV batteries manufactured at Sample battery facility have reported GHG footprint that conform to the GBA rulebook version 1.5.", + "type": "string", + "description": "A textual description of the scope or purpose of this conformity attestation" + }, + "issuedToParty": { + "$ref": "#/$defs/Party", + "description": "The party to whom the conformity attestation was issued." + }, + "authorisation": { + "type": "array", + "items": { + "$ref": "#/$defs/Endorsement" + }, + "description": "The authority under which a conformity claim is issued. For example a national accreditation authority may authorise a test lab to issue test certificates about a product against a standard. " + }, + "conformityCertificate": { + "$ref": "#/$defs/SecureLink", + "description": "A reference to the human / printable version of this conformity attestation - typically represented as a PDF document. The document may have more details than are represented in the digital attestation." + }, + "auditableEvidence": { + "$ref": "#/$defs/SecureLink", + "description": "Auditable evidence supporting this assessment such as raw measurements, supporting documents. This is usually private data and would normally be encrypted." + }, + "scope": { + "$ref": "#/$defs/ConformityAssessmentScheme", + "description": "The scheme(s) under which this conformity assesment is issued. " + }, + "assessment": { + "type": "array", + "items": { + "$ref": "#/$defs/ConformityAssessment" + }, + "description": "The list of specific assessments made within this conformity attestation." + } + }, + "description": "A conformity attestation issued by a competent body that defines one or more assessments (eg carbon intensity) about a product (eg battery) against a specification (eg LCA method) defined in a standard or regulation.", + "required": ["id", "assessorLevel", "assessmentLevel", "attestationType"] + }, + "Party": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Party"], + "default": ["Party"], + "items": { + "type": "string", + "enum": ["Party"] + } + }, + "id": { + "example": "https://abr.business.gov.au/ABN/View?abn=90664869327", + "type": "string", + "format": "uri", + "description": "The globally unique ID of the party as a URI, ideally as a resolvable ID. " + }, + "name": { + "example": "Sample Company Pty Ltd.", + "type": "string", + "description": "The registered name of the party within the identifier scheme." + }, + "registeredId": { + "example": "90664869327", + "type": "string", + "description": "The registration number (alphanumeric) of the Party within the register. Unique within the register." + }, + "idScheme": { + "$ref": "#/$defs/IdentifierScheme", + "description": "The identifier scheme of the party. Typically a national business register or a global scheme such as GLEIF. " + }, + "description": { + "example": "A leading electric energy storage company", + "type": "string", + "description": "An optional short description of the party." + } + }, + "description": "The organisation that is the subject of this conformity assessment.", + "required": ["id", "name"] + }, + "Endorsement": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Endorsement"], + "default": ["Endorsement"], + "items": { + "type": "string", + "enum": ["Endorsement"] + } + }, + "id": { + "example": "https://authority.gov/schemeABC/123456789", + "type": "string", + "format": "uri", + "description": "Globally unique identifier of an accreditation or authority issued to a conformity assessment body by a regulator or national accreditation authority." + }, + "name": { + "example": "Accreditation of certifiers.com under the Australian National Greenhouse and Energy Reporting scheme (NGER).", + "type": "string", + "description": "The name of the accreditation." + }, + "trustmark": { + "$ref": "#/$defs/BinaryFile", + "description": "The trust mark image awarded by the AB to the CAB to indicate accreditation." + }, + "issuingAuthority": { + "$ref": "#/$defs/Identifier", + "description": "The competent authority that issued the accreditation." + }, + "endorsementEvidence": { + "$ref": "#/$defs/Link", + "description": "The evidence that supports the authority under which the attestation is issued - for an example an accreditation certificate." + } + }, + "description": "The authority under which a conformity claim is issued. For example a national accreditation authority may authorise a test lab to issue test certificates about a product against a standard. ", + "required": ["id", "name", "issuingAuthority"] + }, + "BinaryFile": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["BinaryFile"], + "default": ["BinaryFile"], + "items": { + "type": "string", + "enum": ["BinaryFile"] + } + }, + "fileName": { + "example": "GHG protocol trust mark", + "type": "string", + "description": "A name for referenced binary file" + }, + "fileType": { + "type": "string", + "x-external-enumeration": "https://mimetype.io/all-types", + "description": "The type of file, represented as a MIME type.\n\n This is an enumerated value, but the list of valid values are too big, or change too often to include here. You can access the list of allowable values at this URL: https://mimetype.io/all-types\n " + }, + "file": { + "example": "iVBORw0KGgoAAAANSUhEUgAAADkAAAA2CAYAAAB9TjFQAAAABGdBTUEAAi/9H3pWy6vI9uFdAAAAAElFTkSuQmCC", + "type": "string", + "format": "byte", + "description": "The binary file data encoded as Base64 string." + } + }, + "description": "A binary file reference including name and file type." + }, + "Link": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Link"], + "default": ["Link"], + "items": { + "type": "string", + "enum": ["Link"] + } + }, + "linkURL": { + "example": "https://files.example-certifier.com/1234567.json", + "type": "string", + "format": "uri", + "description": "The URL of the target resource. " + }, + "linkName": { + "example": "GBA rule book conformity certificate", + "type": "string", + "description": "A display name for the target resource " + }, + "linkType": { + "example": "https://test.uncefact.org/vocabulary/linkTypes/dcc", + "type": "string", + "description": "The type of the target resource - drawn from a controlled vocabulary " + } + }, + "description": "A structure to provide a URL link plus metadata associated with the link." + }, + "SecureLink": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["SecureLink", "Link"], + "default": ["SecureLink", "Link"], + "items": { + "type": "string", + "enum": ["SecureLink", "Link"] + } + }, + "linkURL": { + "example": "https://files.example-certifier.com/1234567.json", + "type": "string", + "format": "uri", + "description": "The URL of the target resource. " + }, + "linkName": { + "example": "GBA rule book conformity certificate", + "type": "string", + "description": "A display name for the target resource " + }, + "linkType": { + "example": "https://test.uncefact.org/vocabulary/linkTypes/dcc", + "type": "string", + "description": "The type of the target resource - drawn from a controlled vocabulary " + }, + "hashDigest": { + "example": "6239119dda5bd4c8a6ffb832fe16feaa5c27b7dba154d24c53d4470a2c69adc2", + "type": "string", + "description": "The hash of the file." + }, + "hashMethod": { + "type": "string", + "enum": ["SHA-256", "SHA-1"], + "example": "SHA-256", + "description": "The hashing algorithm used to create the target hash. SHA-265 is the recommended standard" + }, + "encryptionMethod": { + "type": "string", + "enum": ["none", "AES"], + "example": "none", + "description": "The symmetric encryption algorithm used to encrypt the link target. AES is the recommended standard. Decryption keys are expected to be passed out of bounds." + } + }, + "description": "A binary file that is hashed ()for tamper evidence) and optionally encrypted (for confidentiality)." + }, + "ConformityAssessmentScheme": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["ConformityAssessmentScheme", "Standard"], + "default": ["ConformityAssessmentScheme", "Standard"], + "items": { + "type": "string", + "enum": ["ConformityAssessmentScheme", "Standard"] + } + }, + "id": { + "example": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf", + "type": "string", + "format": "uri", + "description": "A unique identifier for the standard (eg https://www.iso.org/standard/60857.html)." + }, + "name": { + "example": "GBA Battery Passport Greenhouse Gas Rulebook - V.2.0", + "type": "string", + "description": "The name of the standard" + }, + "issuingParty": { + "$ref": "#/$defs/Identifier", + "description": "The party that issued the standard " + }, + "issueDate": { + "example": "2023-12-05", + "type": "string", + "format": "date", + "description": "The date when the standard was issued." + }, + "trustmark": { + "$ref": "#/$defs/BinaryFile", + "description": "The trust mark that represents the conformity assessment scheme." + } + }, + "description": "A formal governance scheme under which this attestation is issued (eg ACRS structural steel certification) ", + "required": ["issuingParty"] + }, + "ConformityAssessment": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["ConformityAssessment", "Declaration"], + "default": ["ConformityAssessment", "Declaration"], + "items": { + "type": "string", + "enum": ["ConformityAssessment", "Declaration"] + } + }, + "assessmentDate": { + "example": "2024-03-15", + "type": "string", + "format": "date", + "description": "The date on which this assessment was made. " + }, + "id": { + "example": "https://exampleCAB.com/38f73303-a39e-45a7-b8b7-e73517548f27/01", + "type": "string", + "format": "uri", + "description": "A unique identifier for the declaration. Often this will be an extension of the product.id or attestation.id. But could be a UUID." + }, + "referenceStandard": { + "$ref": "#/$defs/Standard", + "description": "The reference to the standard that defines the specification / criteria" + }, + "referenceRegulation": { + "$ref": "#/$defs/Regulation", + "description": "The reference to the regulation that defines the assessment criteria" + }, + "assessmentCriteria": { + "type": "array", + "items": { + "$ref": "#/$defs/Criterion" + }, + "description": "The specification against which the assessment is made." + }, + "declaredValue": { + "type": "array", + "items": { + "$ref": "#/$defs/Metric" + }, + "description": "The list of specific values measured as part of this assessment (eg tensile strength)" + }, + "conformance": { + "example": "true", + "type": "boolean", + "description": "An indicator of whether or not the claim or assesment conforms to the regulatory or standard criteria." + }, + "conformityTopic": { + "type": "string", + "enum": [ + "environment.energy", + "environment.emissions", + "environment.water", + "environment.waste", + "environment.deforestation", + "environment.biodiversity", + "circularity.content", + "circularity.design", + "social.labour", + "social.rights", + "social.community", + "social.safety", + "governance.ethics", + "governance.compliance", + "governance.transparency" + ], + "example": "environment.energy", + "description": "The conformity topic category for this assessment (eg vocabulary.uncefact.org/sustainability/emissions)" + }, + "assessedProduct": { + "type": "array", + "items": { + "$ref": "#/$defs/Product" + }, + "description": "The list of products that are the object of this conformity assessment" + }, + "assessedFacility": { + "type": "array", + "items": { + "$ref": "#/$defs/Facility" + }, + "description": "The list of facilities that are the object of this conformity assessment." + }, + "assessedOrganisation": { + "$ref": "#/$defs/Party", + "description": "The organisation that is the object of this assessment." + }, + "auditor": { + "$ref": "#/$defs/Party", + "description": "The person or organisations that performed this assessment (if different to the issuer of the parent attestation)" + } + }, + "description": "A specific assessment about the product or facility against a specific specification. Eg the carbon intensity of a given product or batch.", + "required": ["id", "conformance", "conformityTopic"] + }, + "Standard": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Standard"], + "default": ["Standard"], + "items": { + "type": "string", + "enum": ["Standard"] + } + }, + "id": { + "example": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf", + "type": "string", + "format": "uri", + "description": "A unique identifier for the standard (eg https://www.iso.org/standard/60857.html)." + }, + "name": { + "example": "GBA Battery Passport Greenhouse Gas Rulebook - V.2.0", + "type": "string", + "description": "The name of the standard" + }, + "issuingParty": { + "$ref": "#/$defs/Identifier", + "description": "The party that issued the standard " + }, + "issueDate": { + "example": "2023-12-05", + "type": "string", + "format": "date", + "description": "The date when the standard was issued." + } + }, + "description": "A standard (eg ISO 14000) that specifies the criteria for conformance.", + "required": ["issuingParty"] + }, + "Regulation": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Regulation"], + "default": ["Regulation"], + "items": { + "type": "string", + "enum": ["Regulation"] + } + }, + "id": { + "example": "https://www.legislation.gov.au/F2008L02309/latest/versions", + "type": "string", + "format": "uri", + "description": "The globally unique identifier of this regulation. " + }, + "name": { + "example": "NNational Greenhouse and Energy Reporting (Measurement) Determination", + "type": "string", + "description": "The name of the regulation or act." + }, + "jurisdictionCountry": { + "type": "string", + "x-external-enumeration": "https://vocabulary.uncefact.org/CountryId", + "description": "The legal jurisdiction (country) under which the regulation is issued.\n\n This is an enumerated value, but the list of valid values are too big, or change too often to include here. You can access the list of allowable values at this URL: https://vocabulary.uncefact.org/CountryId\n " + }, + "administeredBy": { + "$ref": "#/$defs/Identifier", + "description": "the issuing body of the regulation. For example Australian Government Department of Climate Change, Energy, the Environment and Water" + }, + "effectiveDate": { + "example": "2024-03-20", + "type": "string", + "format": "date", + "description": "the date at which the regulation came into effect." + } + }, + "description": "A regulation (eg EU deforestation regulation) that defines the criteria for assessment.", + "required": ["administeredBy"] + }, + "Criterion": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Criterion"], + "default": ["Criterion"], + "items": { + "type": "string", + "enum": ["Criterion"] + } + }, + "id": { + "example": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf#BatteryAssembly", + "type": "string", + "format": "uri", + "description": "A unique identifier for the criterion within the standard or regulation. For example CO2 emissions calculations for liquid fuel combustion." + }, + "name": { + "example": "GBA Battery rule book v2.0 battery assembly guidelines.", + "type": "string", + "description": "A name that describes this criteria." + }, + "thresholdValues": { + "type": "array", + "items": { + "$ref": "#/$defs/Metric" + }, + "description": "A conformity threshold defined by the specification (eg minimum compressive strength) " + } + }, + "description": "A specific rule or criterion within a standard or regulation. eg a carbon intensity calculation rule within an emissions standard.", + "required": ["id", "name"] + }, + "Metric": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Metric"], + "default": ["Metric"], + "items": { + "type": "string", + "enum": ["Metric"] + } + }, + "metricName": { + "example": "GHG emissions intensity", + "type": "string", + "description": "A human readable name for this metric (for example \"Tensile strength\")" + }, + "metricValue": { + "$ref": "#/$defs/Measure", + "description": "A numeric value and unit of measure for this metric. Could be a measured value or a specified threshold. Eg {\"value\":400, \"unit\":\"MPA\"} as tensile strength of structural steel" + }, + "score": { + "example": "BB", + "type": "string", + "description": "A score or rank associated with this measured metric." + }, + "accuracy": { + "example": 0.05, + "type": "number", + "description": "A percentage represented as a numeric between 0 and 1 indicating the rage of accuracy of the claimed value (eg 0.05 means that the actual value is within 5% of the claimed value.)" + } + }, + "description": "A specific measure of performance against the criteria that governs the claim. Expressed as an array of metric (ie unit of measure) / value (ie the actual numeric value) pairs. ", + "required": ["metricName", "metricValue"] + }, + "Measure": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Measure"], + "default": ["Measure"], + "items": { + "type": "string", + "enum": ["Measure"] + } + }, + "value": { + "example": 10, + "type": "number", + "description": "The numeric value of the measure" + }, + "unit": { + "type": "string", + "x-external-enumeration": "https://vocabulary.uncefact.org/UnitMeasureCode", + "description": "Unit of measure drawn from the UNECE Rec20 measure code list.\n\n This is an enumerated value, but the list of valid values are too big, or change too often to include here. You can access the list of allowable values at this URL: https://vocabulary.uncefact.org/UnitMeasureCode\n " + } + }, + "description": "The measure class defines a numeric measured value (eg 10) and a coded unit of measure (eg KG).", + "required": ["value", "unit"] + }, + "Product": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Product"], + "default": ["Product"], + "items": { + "type": "string", + "enum": ["Product"] + } + }, + "id": { + "example": "https://id.gs1.org/01/09520123456788/21/12345", + "type": "string", + "format": "uri", + "description": "The globally unique ID of the product as a URI. Ideally as a resolvable URL according to ISO 18975. " + }, + "name": { + "example": "EV battery 300Ah.", + "type": "string", + "description": "The registered name of the product within the identifier scheme. " + }, + "registeredId": { + "example": "09520123456788.21.12345", + "type": "string", + "description": "The registration number (alphanumeric) of the entity within the register. Unique within the register." + }, + "idScheme": { + "$ref": "#/$defs/IdentifierScheme", + "description": "The identifier scheme for this product. Eg a GS1 GTIN or an AU Livestock NLIS, or similar. If self issued then use the party ID of the issuer. " + }, + "serialNumber": { + "example": "12345678", + "type": "string", + "description": "A number or code representing a specific serialised item of the product. Unique within product class." + }, + "batchNumber": { + "example": "6789", + "type": "string", + "description": "Identifier of the specific production batch of the product. Unique within the product class." + }, + "IDverifiedByCAB": { + "example": "true", + "type": "boolean", + "description": "Indicates whether the conformity assessment body has verified the identity product that is the subject of the assessment." + } + }, + "description": "The product which is the subject of this conformity assessment", + "required": ["id", "name"] + }, + "Facility": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Facility"], + "default": ["Facility"], + "items": { + "type": "string", + "enum": ["Facility"] + } + }, + "id": { + "example": "https://sample-facility-register.com/1234567", + "type": "string", + "format": "uri", + "description": "The globally unique ID of the facility as URI, ideally as a resolvable URL." + }, + "name": { + "example": "Greenacres battery factory", + "type": "string", + "description": "The registered name of the facility within the identifier scheme. " + }, + "registeredId": { + "example": "1234567", + "type": "string", + "description": "The registration number (alphanumeric) of the facility within the identifier scheme. Unique within the register." + }, + "idScheme": { + "$ref": "#/$defs/IdentifierScheme", + "description": "The ID scheme of the facility. eg a GS1 GLN or a National land registry scheme. If self issued then use the party ID of the facility owner. " + }, + "locationInformation": { + "$ref": "#/$defs/Location", + "description": "Geo-location information for this facility as a resolvable geographic area (a Plus Code), and/or a geo-located point (latitude / longitude), and/or a defined boundary (GeoJSON Polygon)." + }, + "address": { + "$ref": "#/$defs/Address", + "description": "The Postal address of the location." + }, + "IDverifiedByCAB": { + "example": "true", + "type": "boolean", + "description": "Indicates whether the conformity assessment body has verified the identity of the facility which is the subject of the assessment." + } + }, + "description": "The facility which is the subject of this conformity assessment", + "required": ["id", "name"] + }, + "Location": { + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Location"], + "default": ["Location"], + "items": { + "type": "string", + "enum": ["Location"] + } + }, + "plusCode": { + "example": "https://plus.codes/8CGRC78W+MM", + "type": "string", + "format": "uri", + "description": "An open location code (https://maps.google.com/pluscodes/) representing this geographic location or region. Open location codes can represent any sized area from a point to a large region and are easily resolved to a visual map location. " + }, + "geoLocation": { + "$ref": "#/$defs/Point", + "description": "The latitude and longitude coordinates that best represent the specified location. Using GeoJSON Point notation." + }, + "geoBoundary": { + "$ref": "#/$defs/Polygon", + "description": "The list of ordered coordinates that define a closed area polygon as a location boundary using GeoJSON polygon notation." + } + }, + "description": "Location information including address and geo-location of points, areas, and boundaries" + }, + "Point": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": ["Point"], + "example": "Point", + "description": "" + }, + "coordinates": { + "$ref": "#/$defs/Point3D", + "description": "Coordinates property of type Point3D" + } + }, + "description": "Represents a Point geometry", + "required": ["type"] + }, + "Point3D": { + "description": "Point in 3d space", + "oneOf": [ + { + "type": "array", + "readOnly": true, + "const": ["Point3D"], + "default": ["Point3D"], + "items": { + "type": "string", + "enum": ["Point3D"] + } + }, + { + "type": "array", + "items": { + "type": "number", + "format": "float" + }, + "description": "Array of decimal values" + } + ] + }, + "Polygon": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": ["Polygon"], + "example": "Polygon", + "description": "" + }, + "coordinates": { + "type": "array", + "items": { + "$ref": "#/$defs/Point3DWrapper" + }, + "description": "Array of PolygonCoordinates" + } + }, + "description": "Represents a Polygon geometry", + "required": ["type"] + }, + "Point3DWrapper": { + "description": "", + "oneOf": [ + { + "type": "array", + "readOnly": true, + "const": ["Point3DWrapper"], + "default": ["Point3DWrapper"], + "items": { + "type": "string", + "enum": ["Point3DWrapper"] + } + }, + { + "type": "array", + "items": { + "$ref": "#/$defs/Point3D" + }, + "description": "" + } + ] + }, + "Address": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "array", + "readOnly": true, + "const": ["Address"], + "default": ["Address"], + "items": { + "type": "string", + "enum": ["Address"] + } + }, + "streetAddress": { + "example": "level 11, 15 London Circuit", + "type": "string", + "description": "the street address as an unstructured string." + }, + "postalCode": { + "example": "2601", + "type": "string", + "description": "The postal code or zip code for this address." + }, + "addressLocality": { + "example": "Acton", + "type": "string", + "description": "The city, suburb or township name." + }, + "addressRegion": { + "example": "ACT", + "type": "string", + "description": "The state or territory or province" + }, + "addressCountry": { + "type": "string", + "x-external-enumeration": "https://vocabulary.uncefact.org/CountryId", + "description": "The address country as an ISO-3166 two letter country code.\n\n This is an enumerated value, but the list of valid values are too big, or change too often to include here. You can access the list of allowable values at this URL: https://vocabulary.uncefact.org/CountryId\n " + } + }, + "description": "A postal address." + } + } + }, + "data": { + "type": ["ConformityAttestation", "Attestation"], + "id": "0105012345678900", + "name": "Product GHG Footprint certificate in accordance with GBA Rulebook.", + "assessorLevel": "3rdParty", + "assessmentLevel": "Accredited", + "attestationType": "certification", + "description": "SampleCAB Inc attests that the product class LiFePO4 EV batteries manufactured at Sample battery facility have reported GHG footprint that conform to the GBA rulebook version 1.5.", + "issuedToParty": { + "type": ["Party"], + "id": "https://abr.business.gov.au/ABN/View?abn=90664869327", + "name": "Sample Company Pty Ltd.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "description": "A leading electric energy storage company" + }, + "authorisation": [ + { + "type": ["Endorsement"], + "id": "https://authority.gov/schemeABC/123456789", + "name": "Accreditation of certifiers.com under the Australian National Greenhouse and Energy Reporting scheme (NGER).", + "trustmark": { + "fileName": "GHG protocol trust mark", + "fileType": "image/png", + "file": "iVBORw0KGgoAAAANSUhEUgAAADkAAAA2CAYAAAB9TjFQAAAABGdBTUEAAi/9H3pWy6vI9uFdAAAAAElFTkSuQmCC" + }, + "issuingAuthority": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "endorsementEvidence": { + "linkURL": "https://files.example-certifier.com/1234567.json", + "linkName": "GBA rule book conformity certificate", + "linkType": "https://test.uncefact.org/vocabulary/linkTypes/dcc" + } + }, + { + "type": ["Endorsement"], + "id": "https://authority.gov/schemeABC/123456789", + "name": "Accreditation of certifiers.com under the Australian National Greenhouse and Energy Reporting scheme (NGER).", + "trustmark": { + "fileName": "GHG protocol trust mark", + "fileType": "image/png", + "file": "iVBORw0KGgoAAAANSUhEUgAAADkAAAA2CAYAAAB9TjFQAAAABGdBTUEAAi/9H3pWy6vI9uFdAAAAAElFTkSuQmCC" + }, + "issuingAuthority": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "endorsementEvidence": { + "linkURL": "https://files.example-certifier.com/1234567.json", + "linkName": "GBA rule book conformity certificate", + "linkType": "https://test.uncefact.org/vocabulary/linkTypes/dcc" + } + } + ], + "conformityCertificate": { + "linkURL": "https://files.example-certifier.com/1234567.json", + "linkName": "GBA rule book conformity certificate", + "linkType": "https://test.uncefact.org/vocabulary/linkTypes/dcc", + "hashDigest": "6239119", + "hashMethod": "SHA-256", + "encryptionMethod": "AES" + }, + "auditableEvidence": { + "linkURL": "https://files.example-certifier.com/1234567.json", + "linkName": "GBA rule book conformity certificate", + "linkType": "https://test.uncefact.org/vocabulary/linkTypes/dcc", + "hashDigest": "6239119", + "hashMethod": "SHA-256", + "encryptionMethod": "AES" + }, + "scope": { + "type": ["ConformityAssessmentScheme", "Standard"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf", + "name": "GBA Battery Passport Greenhouse Gas Rulebook - V.2.0", + "issuingParty": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "issueDate": "2023-12-05", + "trustmark": { + "fileName": "GHG protocol trust mark", + "fileType": "image/png", + "file": "iVBORw0KGgoAAAANSUhEUgAAADkAAAA2CAYAAAB9TjFQAAAABGdBTUEAAi/9H3pWy6vI9uFdAAAAAElFTkSuQmCC" + } + }, + "assessment": [ + { + "type": ["ConformityAssessment", "Declaration"], + "assessmentDate": "2024-03-15", + "id": "https://exampleCAB.com/38f73303-a39e-45a7-b8b7-e73517548f27/01", + "referenceStandard": { + "type": ["Standard"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf", + "name": "GBA Battery Passport Greenhouse Gas Rulebook - V.2.0", + "issuingParty": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "issueDate": "2023-12-05" + }, + "referenceRegulation": { + "type": ["Regulation"], + "id": "https://www.legislation.gov.au/F2008L02309/latest/versions", + "name": "NNational Greenhouse and Energy Reporting (Measurement) Determination", + "jurisdictionCountry": "Enumeration Value", + "administeredBy": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "effectiveDate": "2024-03-20" + }, + "assessmentCriteria": [ + { + "type": ["Criterion"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf#BatteryAssembly", + "name": "GBA Battery rule book v2.0 battery assembly guidelines.", + "thresholdValues": [ + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + }, + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + } + ] + }, + { + "type": ["Criterion"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf#BatteryAssembly", + "name": "GBA Battery rule book v2.0 battery assembly guidelines.", + "thresholdValues": [ + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + }, + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + } + ] + } + ], + "declaredValue": [ + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + }, + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + } + ], + "conformance": true, + "conformityTopic": "environment.emissions", + "assessedProduct": [ + { + "type": ["Product"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "09520123456788.21.12345", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "serialNumber": "12345678", + "batchNumber": "6789", + "IDverifiedByCAB": true + }, + { + "type": ["Product"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "09520123456788.21.12345", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "serialNumber": "12345678", + "batchNumber": "6789", + "IDverifiedByCAB": true + } + ], + "assessedFacility": [ + { + "type": ["Facility"], + "id": "https://sample-facility-register.com/1234567", + "name": "Greenacres battery factory", + "registeredId": "1234567", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "locationInformation": { + "plusCode": "https://plus.codes/8CGRC78W+MM", + "geoLocation": { + "type": "Point", + "coordinates": [3.141579, 3.141579] + }, + "geoBoundary": { + "type": "Polygon", + "coordinates": [[[3.141579, 3.141579]]] + } + }, + "address": { + "streetAddress": "level 11, 15 London Circuit", + "postalCode": "2601", + "addressLocality": "Acton", + "addressRegion": "ACT", + "addressCountry": "AU" + }, + "IDverifiedByCAB": true + }, + { + "type": ["Facility"], + "id": "https://sample-facility-register.com/1234567", + "name": "Greenacres battery factory", + "registeredId": "1234567", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "locationInformation": { + "plusCode": "https://plus.codes/8CGRC78W+MM", + "geoLocation": { + "type": "Point", + "coordinates": [3.141579, 3.141579] + }, + "geoBoundary": { + "type": "Polygon", + "coordinates": [[[3.141579, 3.141579]]] + } + }, + "address": { + "streetAddress": "level 11, 15 London Circuit", + "postalCode": "2601", + "addressLocality": "Acton", + "addressRegion": "ACT", + "addressCountry": "AU" + }, + "IDverifiedByCAB": true + } + ], + "assessedOrganisation": { + "type": ["Party"], + "id": "https://abr.business.gov.au/ABN/View?abn=90664869327", + "name": "Sample Company Pty Ltd.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "description": "A leading electric energy storage company" + }, + "auditor": { + "type": ["Party"], + "id": "https://abr.business.gov.au/ABN/View?abn=90664869327", + "name": "Sample Company Pty Ltd.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "description": "A leading electric energy storage company" + } + }, + { + "type": ["ConformityAssessment", "Declaration"], + "assessmentDate": "2024-03-15", + "id": "https://exampleCAB.com/38f73303-a39e-45a7-b8b7-e73517548f27/01", + "referenceStandard": { + "type": ["Standard"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf", + "name": "GBA Battery Passport Greenhouse Gas Rulebook - V.2.0", + "issuingParty": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "issueDate": "2023-12-05" + }, + "referenceRegulation": { + "type": ["Regulation"], + "id": "https://www.legislation.gov.au/F2008L02309/latest/versions", + "name": "NNational Greenhouse and Energy Reporting (Measurement) Determination", + "jurisdictionCountry": "Enumeration Value", + "administeredBy": { + "type": ["Identifier"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + } + }, + "effectiveDate": "2024-03-20" + }, + "assessmentCriteria": [ + { + "type": ["Criterion"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf#BatteryAssembly", + "name": "GBA Battery rule book v2.0 battery assembly guidelines.", + "thresholdValues": [ + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + }, + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + } + ] + }, + { + "type": ["Criterion"], + "id": "https://www.globalbattery.org/media/publications/gba-rulebook-v2.0-master.pdf#BatteryAssembly", + "name": "GBA Battery rule book v2.0 battery assembly guidelines.", + "thresholdValues": [ + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + }, + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + } + ] + } + ], + "declaredValue": [ + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + }, + { + "metricName": "GHG emissions intensity", + "metricValue": { + "value": 10, + "unit": "KGM" + }, + "score": "BB", + "accuracy": 0.05 + } + ], + "conformance": true, + "conformityTopic": "environment.emissions", + "assessedProduct": [ + { + "type": ["Product"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "09520123456788.21.12345", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "serialNumber": "12345678", + "batchNumber": "6789", + "IDverifiedByCAB": true + }, + { + "type": ["Product"], + "id": "https://id.gs1.org/01/09520123456788/21/12345", + "name": "EV battery 300Ah.", + "registeredId": "09520123456788.21.12345", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "serialNumber": "12345678", + "batchNumber": "6789", + "IDverifiedByCAB": true + } + ], + "assessedFacility": [ + { + "type": ["Facility"], + "id": "https://sample-facility-register.com/1234567", + "name": "Greenacres battery factory", + "registeredId": "1234567", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "locationInformation": { + "plusCode": "https://plus.codes/8CGRC78W+MM", + "geoLocation": { + "type": "Point", + "coordinates": [3.141579, 3.141579] + }, + "geoBoundary": { + "type": "Polygon", + "coordinates": [[[3.141579, 3.141579]]] + } + }, + "address": { + "streetAddress": "level 11, 15 London Circuit", + "postalCode": "2601", + "addressLocality": "Acton", + "addressRegion": "ACT", + "addressCountry": "AU" + }, + "IDverifiedByCAB": true + }, + { + "type": ["Facility"], + "id": "https://sample-facility-register.com/1234567", + "name": "Greenacres battery factory", + "registeredId": "1234567", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "locationInformation": { + "plusCode": "https://plus.codes/8CGRC78W+MM", + "geoLocation": { + "type": "Point", + "coordinates": [3.141579, 3.141579] + }, + "geoBoundary": { + "type": "Polygon", + "coordinates": [[[3.141579, 3.141579]]] + } + }, + "address": { + "streetAddress": "level 11, 15 London Circuit", + "postalCode": "2601", + "addressLocality": "Acton", + "addressRegion": "ACT", + "addressCountry": "AU" + }, + "IDverifiedByCAB": true + } + ], + "assessedOrganisation": { + "type": ["Party"], + "id": "https://abr.business.gov.au/ABN/View?abn=90664869327", + "name": "Sample Company Pty Ltd.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "description": "A leading electric energy storage company" + }, + "auditor": { + "type": ["Party"], + "id": "https://abr.business.gov.au/ABN/View?abn=90664869327", + "name": "Sample Company Pty Ltd.", + "registeredId": "90664869327", + "idScheme": { + "type": ["IdentifierScheme"], + "id": "https://id.gs1.org/01/", + "name": "Global Trade Identification Number (GTIN)" + }, + "description": "A leading electric energy storage company" + } + } + ] + }, + "constructData": { + "mappingFields": [], + "dummyFields": [], + "generationFields": [ + { + "path": "/eventID", + "handler": "generateIdWithSerialNumber" + } + ] + }, + "className": "json-form", + "style": { + "margin": "40px auto", + "paddingTop": "40px", + "width": "80%" + } + } + }, + { + "name": "CustomButton", + "type": "Submit", + "props": {} + } + ], + "services": [ + { + "name": "processDigitalConformityCredential", + "parameters": [ + { + "vckit": { + "vckitAPIUrl": "http://localhost:3332/v2", + "issuer": "did:web:uncefact.github.io:project-vckit:test-and-development" + }, + "digitalConformityCredential": { + "context": [ + "https://jargon.sh/user/unece/ConformityCredential/v/0.5.0/artefacts/jsonldContexts/ConformityCredential.jsonld?class=ConformityCredential" + ], + "renderTemplate": [ + { + "template": "
Digital Conformity Credential
", + "@type": "WebRenderingTemplate2022" + } + ], + "type": ["DigitalConformityCredential"], + "dlrLinkTitle": "DigitalConformityCredential", + "dlrIdentificationKeyType": "gtin", + "dlrVerificationPage": "http://localhost:3003/verify" + }, + "dlr": { + "dlrAPIUrl": "http://localhost:3000", + "dlrAPIKey": "test123", + "namespace": "gs1", + "linkRegisterPath": "/api/resolver" + }, + "storage": { + "url": "http://localhost:3334/v1/documents", + "params": { + "resultPath": "/uri", + "bucket": "verifiable-credentials" + }, + "options": { + "method": "POST", + "headers": { + "Content-Type": "application/json" + } + } + }, + "identifierKeyPath": "/id" + } + ] + } + ] + }, { "name": "Issue DFR", "id": "produce_product", @@ -2491,7 +4220,7 @@ "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", "DigitalFacilityRecord"], + "type": ["DigitalFacilityRecord"], "dlrLinkTitle": "DigitalFacilityRecord", "dlrIdentificationKeyType": "gln", "dlrVerificationPage": "http://localhost:3003/verify" @@ -3716,7 +5445,7 @@ "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", "DigitalProductPassport"], + "type": ["DigitalProductPassport"], "dlrLinkTitle": "Cherries Product Passport", "dlrIdentificationKeyType": "gtin", "dlrVerificationPage": "http://localhost:3003/verify" @@ -4951,7 +6680,7 @@ "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", "DigitalProductPassport"], + "type": ["DigitalProductPassport"], "dlrLinkTitle": "Cherries Product Passport", "dlrIdentificationKeyType": "gtin", "dlrVerificationPage": "http://localhost:3003/verify" @@ -6186,7 +7915,7 @@ "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", "DigitalProductPassport"], + "type": ["DigitalProductPassport"], "dlrLinkTitle": "Cherries Product Passport", "dlrIdentificationKeyType": "gtin", "dlrVerificationPage": "http://localhost:3003/verify" diff --git a/documentation/docs/mock-apps/services/process-aggregation-event.md b/documentation/docs/mock-apps/services/process-aggregation-event.md index e43689c1..5131227e 100644 --- a/documentation/docs/mock-apps/services/process-aggregation-event.md +++ b/documentation/docs/mock-apps/services/process-aggregation-event.md @@ -45,7 +45,7 @@ P-->>C: Return VC and resolver URL }, "epcisAggregationEvent": { "context": ["https://www.w3.org/2018/credentials/v1", "https://gs1.org/voc/"], - "type": ["VerifiableCredential", "EPCISAggregationEvent"], + "type": ["DigitalTraceabilityEvent"], "renderTemplate": [ { "type": "html", diff --git a/documentation/docs/mock-apps/services/process-digital-conformity-credential.md b/documentation/docs/mock-apps/services/process-digital-conformity-credential.md new file mode 100644 index 00000000..aed9d832 --- /dev/null +++ b/documentation/docs/mock-apps/services/process-digital-conformity-credential.md @@ -0,0 +1,88 @@ +--- +sidebar_position: 53 +title: Process Digital Conformity Credential +--- + +import Disclaimer from '../../\_disclaimer.mdx'; + + + +## Description + +The `processDigitalConformityCredential` service is responsible for processing a digital conformity credential, issuing a [Verifiable Credential (VC)](https://uncefact.github.io/spec-untp/docs/specification/VerifiableCredentials), uploading it to the [Storage service](/docs/mock-apps/dependent-services/storage-service), registering the link to the stored digital conformity credential with the [Identity Resolver service](/docs/mock-apps/dependent-services/identity-resolution-service). It handles the entire lifecycle of creating and managing a digital conformity credential, from data input to storage and resolution. + +## Diagram + +```mermaid +sequenceDiagram +participant C as Client +participant P as processDigitalConformityCredential +participant V as VCKit +participant S as Storage +participant D as DLR +C->>P: Call processDigitalConformityCredential(digitalConformityCredential, context) +P->>P: Validate context +P->>P: Extract identifier +P->>V: Issue VC +V-->>P: Return VC +P->>S: Upload VC +S-->>P: Return VC URL +P->>D: Register link resolver +D-->>P: Return resolver URL +P-->>C: Return digital conformity credential VC and resolver URL +``` + +## Example + +```json +{ + "name": "processDigitalConformityCredential", + "parameters": [ + { + "vckit": { + "vckitAPIUrl": "https://api.vckit.example.com", + "issuer": "did:example:123456789abcdefghi" + }, + "digitalConformityCredential": { + "context": [ + "https://jargon.sh/user/unece/ConformityCredential/v/0.5.0/artefacts/jsonldContexts/ConformityCredential.jsonld?class=ConformityCredential" + ], + "type": ["DigitalConformityCredential"], + "renderTemplate": [ + { + "template": "

DigitalConformityCredential

", + "@type": "WebRenderingTemplate2022" + } + ], + "dlrIdentificationKeyType": "gtin", + "dlrLinkTitle": "DigitalConformityCredential", + "dlrVerificationPage": "https://verify.example.com" + }, + "storage": { + "url": "https://storage.example.com/upload", + "params": { + "bucket": "bucket-name", + "resultPath": "/url" + } + }, + "dlr": { + "dlrAPIUrl": "https://dlr.example.com/api", + "dlrAPIKey": "dlr-api-key-12345", + "namespace": "gs1", + "linkRegisterPath": "/api/resolver" + }, + "identifierKeyPath": "/id" + } + ] +} +``` + +## Definitions + +| Property | Required | Description | Type | +| --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) | +| digitalConformityCredential | Yes | Configuration for the Digital Conformity Credential | [Credential](/docs/mock-apps/common/credential) | +| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) | +| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) | +| identifierKeyPath | Yes | JSON path to the identifier in the credential subject or the object for function and arguments of JSON path to construct identifier | [IdentifierKeyPath](/docs/mock-apps/common/identifier-key-path) | diff --git a/documentation/docs/mock-apps/services/process-digital-facility-record.md b/documentation/docs/mock-apps/services/process-digital-facility-record.md index e25686ba..969903a0 100644 --- a/documentation/docs/mock-apps/services/process-digital-facility-record.md +++ b/documentation/docs/mock-apps/services/process-digital-facility-record.md @@ -45,7 +45,7 @@ P-->>C: Return digital facility record VC and resolver URL }, "digitalFacilityRecord": { "context": ["https://www.w3.org/2018/credentials/v1", "https://gs1.org/voc/"], - "type": ["VerifiableCredential", "DigitalFacilityRecord"], + "type": ["DigitalFacilityRecord"], "renderTemplate": [ { "template": "

DigitalFacilityRecord

", diff --git a/documentation/docs/mock-apps/services/process-digital-identity-anchor.md b/documentation/docs/mock-apps/services/process-digital-identity-anchor.md index a1174413..21654711 100644 --- a/documentation/docs/mock-apps/services/process-digital-identity-anchor.md +++ b/documentation/docs/mock-apps/services/process-digital-identity-anchor.md @@ -45,7 +45,7 @@ P-->>C: Return digital identity anchor VC and resolver URL }, "digitalIdentityAnchor": { "context": ["https://www.w3.org/2018/credentials/v1", "https://gs1.org/voc/"], - "type": ["VerifiableCredential", "DigitalIdentityAnchor"], + "type": ["DigitalIdentityAnchor"], "renderTemplate": [ { "template": "

DigitalIdentityAnchor

", diff --git a/documentation/docs/mock-apps/services/process-dpp.md b/documentation/docs/mock-apps/services/process-dpp.md index 5653abfb..dc26401d 100644 --- a/documentation/docs/mock-apps/services/process-dpp.md +++ b/documentation/docs/mock-apps/services/process-dpp.md @@ -68,7 +68,7 @@ P-->>C: Return VC and resolver URL "@type": "WebRenderingTemplate2022" } ], - "type": ["VerifiableCredential", " DigitalProductPassport"], + "type": ["DigitalProductPassport"], "dlrLinkTitle": "Steel Passport", "dlrIdentificationKeyType": "gtin", "dlrVerificationPage": "http://localhost:3332/verify" diff --git a/documentation/docs/mock-apps/services/process-object-event.md b/documentation/docs/mock-apps/services/process-object-event.md index 53c1a805..5f536f99 100644 --- a/documentation/docs/mock-apps/services/process-object-event.md +++ b/documentation/docs/mock-apps/services/process-object-event.md @@ -45,7 +45,7 @@ P-->>C: Return object event VC and resolver URL }, "epcisObjectEvent": { "context": ["https://www.w3.org/2018/credentials/v1", "https://gs1.org/voc/"], - "type": ["VerifiableCredential", "DigitalTraceabilityEvent"], + "type": ["DigitalTraceabilityEvent"], "renderTemplate": [ { "template": "

Object Event

", diff --git a/documentation/docs/mock-apps/services/process-transaction-event.md b/documentation/docs/mock-apps/services/process-transaction-event.md index 2de2da29..1b9feb84 100644 --- a/documentation/docs/mock-apps/services/process-transaction-event.md +++ b/documentation/docs/mock-apps/services/process-transaction-event.md @@ -47,7 +47,7 @@ P-->>C: Return VC and resolver URL }, "epcisTransactionEvent": { "context": ["https://www.w3.org/2018/credentials/v1", "https://gs1.org/voc/"], - "type": ["VerifiableCredential", "EPCISTransactionEvent"], + "type": ["DigitalTraceabilityEvent"], "renderTemplate": [ { "type": "html", diff --git a/documentation/docs/mock-apps/services/process-transformation-event.md b/documentation/docs/mock-apps/services/process-transformation-event.md index fbea3939..8b1c516b 100644 --- a/documentation/docs/mock-apps/services/process-transformation-event.md +++ b/documentation/docs/mock-apps/services/process-transformation-event.md @@ -52,7 +52,7 @@ P-->>C: Return EPCIS VC }, "epcisTransformationEvent": { "context": ["https://www.w3.org/2018/credentials/v1", "https://gs1.org/voc/"], - "type": ["VerifiableCredential", "EPCISTransformationEvent"], + "type": ["DigitalTraceabilityEvent"], "renderTemplate": [ { "type": "html", @@ -84,7 +84,7 @@ P-->>C: Return EPCIS VC }, "dpp": { "context": ["https://www.w3.org/2018/credentials/v1", "https://schema.org/"], - "type": ["VerifiableCredential", "DigitalProductPassport"], + "type": ["DigitalProductPassport"], "renderTemplate": [ { "type": "html", diff --git a/packages/services/src/__tests__/mocks/constants.ts b/packages/services/src/__tests__/mocks/constants.ts index 55883c63..b5bb5203 100644 --- a/packages/services/src/__tests__/mocks/constants.ts +++ b/packages/services/src/__tests__/mocks/constants.ts @@ -42,6 +42,8 @@ export const contextTransformationEvent = { dlr: { dlrAPIUrl: 'http://localhost', dlrAPIKey: '5555555555555', + namespace: 'gs1', + linkRegisterPath: '/api/resolver', }, storage: { url: 'https://storage.example.com', @@ -170,7 +172,7 @@ export const transactionEventMock = { transactionEventDLRMock: `https://example-dlr.com/nlisid/9988776600000?linkType=all`, transactionVCMock: { '@context': ['https://example.sh/TransactionEvent.jsonld'], - type: ['VerifiableCredential', 'TransactionEventCredential'], + type: ['TransactionEventCredential'], issuer: 'did:web:example.com', credentialSubject: { sourceParty: { partyID: `https://beef-steak-shop.com/info.json`, name: 'Beef Steak Shop' }, @@ -194,7 +196,7 @@ export const aggregationEventMock = { aggregationEventDLRMock: `https://example.com/gtin/9988776600000.json`, aggregationVCMock: { '@context': ['https://example.sh/AggregationEvent.jsonld'], - type: ['VerifiableCredential', 'AggregationEventCredential'], + type: ['AggregationEventCredential'], issuer: 'did:web:example.com', credentialSubject: { parentItem: { @@ -214,7 +216,7 @@ export const objectEventContext = { }, epcisObjectEvent: { context: ['https://www.w3.org/2018/credentials/v1', 'https://gs1.org/voc/'], - type: ['VerifiableCredential', 'ObjectEventCredential'], + type: ['ObjectEventCredential'], renderTemplate: [ { template: '

Object Event

', @@ -275,6 +277,8 @@ export const digitalIdentityAnchorContext = { dlr: { dlrAPIUrl: 'http://dlr.example.com', dlrAPIKey: '1234', + namespace: 'gs1', + linkRegisterPath: '/api/resolver', }, storage: { url: 'https://storage.example.com', @@ -301,6 +305,8 @@ export const digitalFacilityRecordContext = { dlr: { dlrAPIUrl: 'http://dlr.example.com', dlrAPIKey: '1234', + namespace: 'gs1', + linkRegisterPath: '/api/resolver', }, storage: { url: 'https://storage.example.com', @@ -318,7 +324,7 @@ export const associationEventContext = { }, epcisAssociationEvent: { context: ['https://www.w3.org/2018/credentials/v1', 'https://gs1.org/voc/'], - type: ['VerifiableCredential', 'AssociationEventCredential'], + type: ['AssociationEventCredential'], renderTemplate: [ { template: '

Association Event

', @@ -343,3 +349,31 @@ export const associationEventContext = { }, identifierKeyPath: '/id', }; + +export const digitalConformityCredentialContext = { + vckit: { + vckitAPIUrl: 'https://vckit.example.com', + issuer: 'did:web:example.com', + }, + digitalConformityCredential: { + context: ['https://www.w3.org/2018/credentials/v1'], + renderTemplate: [{ template: '

Render dcc template

', '@type': 'WebRenderingTemplate2022' }], + type: ['DigitalConformityCredential'], + dlrLinkTitle: 'DigitalConformityCredential', + dlrIdentificationKeyType: 'gtin', + dlrVerificationPage: 'https://web.example.com/verify', + }, + dlr: { + dlrAPIUrl: 'http://dlr.example.com', + dlrAPIKey: '1234', + namespace: 'gs1', + linkRegisterPath: '/api/resolver', + }, + storage: { + url: 'https://storage.example.com', + params: { + resultPath: '', + }, + }, + identifierKeyPath: '/id', +}; diff --git a/packages/services/src/__tests__/processDigitalConformityCredential.test.ts b/packages/services/src/__tests__/processDigitalConformityCredential.test.ts new file mode 100644 index 00000000..64d8dd02 --- /dev/null +++ b/packages/services/src/__tests__/processDigitalConformityCredential.test.ts @@ -0,0 +1,101 @@ +import * as vckitService from '../vckit.service'; +import { uploadData } from '../storage.service'; +import * as linkResolverService from '../linkResolver.service'; +import { Result } from '../types/validateContext'; +import * as validateContext from '../validateContext'; +import { IDigitalConformityCredentialContext } from '../types'; +import { processDigitalConformityCredential } from '../processDigitalConformityCredential.service'; +import { digitalConformityCredentialContext as context } from './mocks/constants'; + +jest.mock('../vckit.service', () => ({ + issueVC: jest.fn(), +})); +jest.mock('../storage.service', () => ({ + uploadData: jest.fn(), +})); +jest.mock('../linkResolver.service', () => ({ + registerLinkResolver: jest.fn(), + createLinkResolver: jest.fn(), + IdentificationKeyType: jest.fn(), + getLinkResolverIdentifier: jest.fn(), + getLinkResolverIdentifierFromURI: jest.fn(), + LinkType: { + verificationLinkType: 'verificationService', + certificationLinkType: 'certificationInfo', + epcisLinkType: 'epcis', + }, +})); + +describe('processDigitalConformityCredential', () => { + const digitalConformityCredentialData = { + data: { + type: 'DigitalConformityCredential', + id: '0123456789', + name: 'Digital Conformity Credential', + registeredId: '9220664869327', + }, + }; + + it('should process digital conformity credential successfully', async () => { + (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ + credentialSubject: { id: 'https://example.com/123' }, + })); + (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + + jest + .spyOn(validateContext, 'validateDigitalConformityCredentialContext') + .mockReturnValueOnce({ ok: true, value: context } as unknown as Result); + jest + .spyOn(linkResolverService, 'getLinkResolverIdentifier') + .mockReturnValue({ identifier: '0123456789', qualifierPath: '/' }); + jest.spyOn(linkResolverService, 'registerLinkResolver').mockResolvedValue('https://example.com/link-resolver'); + + const result = await processDigitalConformityCredential(digitalConformityCredentialData, context); + + expect(result.vc).toEqual({ credentialSubject: { id: 'https://example.com/123' } }); + expect(result.linkResolver).toEqual('https://example.com/link-resolver'); + }); + + it('should throw error when context validation false', async () => { + const invalidContext: any = { ...context }; + delete invalidContext.digitalConformityCredential; + + jest + .spyOn(validateContext, 'validateDigitalConformityCredentialContext') + .mockReturnValueOnce({ ok: false, value: 'Invalid context' }); + + expect( + async () => await processDigitalConformityCredential(digitalConformityCredentialData, invalidContext), + ).rejects.toThrow('Invalid context'); + }); + + it('should throw error when identifier not found', async () => { + const invalidIdentifierContent = { + ...context, + identifierKeyPath: '/invalid', + }; + + jest + .spyOn(validateContext, 'validateDigitalConformityCredentialContext') + .mockReturnValueOnce({ ok: true, value: context } as unknown as Result); + + expect( + async () => await processDigitalConformityCredential(digitalConformityCredentialData, invalidIdentifierContent), + ).rejects.toThrow('Identifier not found'); + }); + + it('should throw error when DigitalConformityCredential data not found', async () => { + const invalidDigitalConformityCredentialData = { + ...digitalConformityCredentialData, + data: undefined, + }; + + jest + .spyOn(validateContext, 'validateDigitalConformityCredentialContext') + .mockReturnValueOnce({ ok: true, value: context } as unknown as Result); + + expect( + async () => await processDigitalConformityCredential(invalidDigitalConformityCredentialData, context), + ).rejects.toThrow('digitalConformityCredential data not found'); + }); +}); diff --git a/packages/services/src/index.ts b/packages/services/src/index.ts index 92de6b8c..9cdc626f 100644 --- a/packages/services/src/index.ts +++ b/packages/services/src/index.ts @@ -3,6 +3,7 @@ export * from './epcisEvents/index.js'; export * from './processDPP.service.js'; export * from './processDigitalIdentityAnchor.service.js'; export * from './processDigitalFacilityRecord.service.js'; +export * from './processDigitalConformityCredential.service.js'; export * from './vckit.service.js'; export * from './linkResolver.service.js'; export * from './storage.service.js'; diff --git a/packages/services/src/processDigitalConformityCredential.service.ts b/packages/services/src/processDigitalConformityCredential.service.ts new file mode 100644 index 00000000..a4f51999 --- /dev/null +++ b/packages/services/src/processDigitalConformityCredential.service.ts @@ -0,0 +1,64 @@ +import { VerifiableCredential } from '@vckit/core-types'; +import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from './linkResolver.service.js'; +import { uploadData } from './storage.service.js'; +import { IService } from './types/IService.js'; +import { constructIdentifierString, generateUUID } from './utils/helpers.js'; +import { issueVC } from './vckit.service.js'; +import { ITraceabilityEvent, IDigitalConformityCredentialContext } from './types/index.js'; +import { validateDigitalConformityCredentialContext } from './validateContext.js'; + +/** + * Processes a digital conformity credential by issuing a verifiable credential, storing it in a storage service and registering a link resolver. + * @param digitalConformityCredentialData The digital conformity credential to process, containing the digital conformity credential data + * @param context The context to use for processing the digital conformity credential + * @returns The result of processing the digital conformity credential + */ +export const processDigitalConformityCredential: IService = async ( + digitalConformityCredentialData: ITraceabilityEvent, + context: IDigitalConformityCredentialContext, +): Promise => { + const validationResult = validateDigitalConformityCredentialContext(context); + if (!validationResult.ok) throw new Error(validationResult.value); + + if (!digitalConformityCredentialData.data) { + throw new Error('digitalConformityCredential data not found'); + } + + const { vckit, digitalConformityCredential, dlr, storage, identifierKeyPath } = context; + + const identifierString = constructIdentifierString(digitalConformityCredentialData.data, identifierKeyPath); + if (!identifierString) { + throw new Error('Identifier not found'); + } + + const { identifier, qualifierPath } = getLinkResolverIdentifier(identifierString); + + const vc: VerifiableCredential = await issueVC({ + credentialSubject: digitalConformityCredentialData.data, + vcKitAPIUrl: vckit.vckitAPIUrl, + issuer: vckit.issuer, + context: digitalConformityCredential.context, + type: digitalConformityCredential.type, + restOfVC: { + render: digitalConformityCredential.renderTemplate, + }, + }); + + const vcUrl = await uploadData(storage, vc, generateUUID()); + + const linkResolver = await registerLinkResolver( + vcUrl, + digitalConformityCredential.dlrIdentificationKeyType, + identifier, + digitalConformityCredential.dlrLinkTitle, + LinkType.certificationLinkType, + digitalConformityCredential.dlrVerificationPage, + dlr.dlrAPIUrl, + dlr.dlrAPIKey, + dlr.namespace, + qualifierPath, + LinkType.certificationLinkType, + ); + + return { vc, linkResolver }; +}; diff --git a/packages/services/src/types/types.ts b/packages/services/src/types/types.ts index f8f40f68..f0e128f2 100644 --- a/packages/services/src/types/types.ts +++ b/packages/services/src/types/types.ts @@ -135,3 +135,7 @@ export interface IDigitalFacilityRecordContext extends IContext { export interface IAssociationEventContext extends IContext { epcisAssociationEvent: IEntityIssue; } + +export interface IDigitalConformityCredentialContext extends IContext { + digitalConformityCredential: IEntityIssue; +} diff --git a/packages/services/src/validateContext.ts b/packages/services/src/validateContext.ts index e0c9f04d..18068f1e 100644 --- a/packages/services/src/validateContext.ts +++ b/packages/services/src/validateContext.ts @@ -10,6 +10,7 @@ import { IDppContext, IDigitalIdentityAnchorContext, IDigitalFacilityRecordContext, + IDigitalConformityCredentialContext, } from './types/index.js'; export const error: (message: string) => Result = (message) => ({ @@ -272,3 +273,32 @@ export const validateAssociationEventContext = ( return { ok: true, value: context }; }; + +export const validateDigitalConformityCredentialContext = ( + context: IDigitalConformityCredentialContext, +): Result => { + const validationResult = checkContextProperties(context); + if (!validationResult.ok) return error(validationResult.value); + + if (_.isEmpty(context.vckit.vckitAPIUrl)) return error('Invalid vckitAPIUrl'); + if (_.isEmpty(context.vckit.issuer)) return error('Invalid issuer'); + + if (_.isEmpty(context.digitalConformityCredential)) return error('Invalid digitalConformityCredential context'); + if (_.isEmpty(context.digitalConformityCredential.context)) + return error('Invalid digitalConformityCredential context'); + if (_.isEmpty(context.digitalConformityCredential.type)) return error('Invalid type'); + if (_.isEmpty(context.digitalConformityCredential.dlrLinkTitle)) return error('Invalid dlrLinkTitle'); + if (_.isEmpty(context.digitalConformityCredential.dlrVerificationPage)) return error('Invalid dlrVerificationPage'); + if (_.isEmpty(context.digitalConformityCredential.dlrIdentificationKeyType)) + return error('Invalid dlrIdentificationKeyType'); + + if (_.isEmpty(context.storage)) return error('Invalid storage context'); + if (_.isEmpty(context.storage.url)) return error('Invalid storage url'); + if (_.isEmpty(context.storage.params)) return error('Invalid storage params'); + + if (_.isEmpty(context.dlr.dlrAPIUrl)) return error('Invalid dlrAPIUrl'); + if (_.isEmpty(context.dlr.dlrAPIKey)) return error('Invalid dlrAPIKey'); + if (_.isEmpty(context.dlr.namespace)) return error('Invalid dlr namespace'); + + return { ok: true, value: context }; +};