From 19e02bfaf4f6c5d2b2790edb783d0f009de546c7 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Tue, 19 Dec 2023 16:24:19 -0500 Subject: [PATCH 01/26] add cached traceability context Signed-off-by: pstlouis --- .../vc/ld_proofs/document_downloader.py | 1 + .../resources/traceability-v1-context.jsonld | 5371 +++++++++++++++++ 2 files changed, 5372 insertions(+) create mode 100644 aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld diff --git a/aries_cloudagent/vc/ld_proofs/document_downloader.py b/aries_cloudagent/vc/ld_proofs/document_downloader.py index 19c64bbb97..be9da39eb6 100644 --- a/aries_cloudagent/vc/ld_proofs/document_downloader.py +++ b/aries_cloudagent/vc/ld_proofs/document_downloader.py @@ -42,6 +42,7 @@ class StaticCacheJsonLdDownloader: "https://w3id.org/security/v1": "security-v1-context.jsonld", "https://w3id.org/security/v2": "security-v2-context.jsonld", "https://w3id.org/security/suites/ed25519-2020/v1": "ed25519-2020-context.jsonld", + "https://w3id.org/traceability/v1": "traceability-v1-context.jsonld", } def __init__( diff --git a/aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld b/aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld new file mode 100644 index 0000000000..8aeb1d5ea8 --- /dev/null +++ b/aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld @@ -0,0 +1,5371 @@ +{ + "@context": { + "@version": 1.1, + "@vocab": "https://www.w3.org/ns/credentials/issuer-dependent#", + "id": "@id", + "type": "@type", + "name": "https://schema.org/name", + "description": "https://schema.org/description", + "identifier": "https://schema.org/identifier", + "image": { + "@id": "https://schema.org/image", + "@type": "@id" + }, + "relatedLink": { + "@id": "https://w3id.org/traceability#LinkRole" + }, + "manufacturer": "https://vocabulary.uncefact.org/manufacturerParty", + "manufacturingCountry": "https://vocabulary.uncefact.org/manufactureCountry", + "product": "https://w3id.org/traceability#SteelProduct", + "rawMaterial": "https://w3id.org/traceability#rawMaterial", + "items": "https://schema.org/ItemList", + "dateOfExport": { + "@id": "https://vocabulary.uncefact.org/exportExitDateTime", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "TraceablePresentation": { + "@id": "https://w3id.org/traceability#traceable-presentation", + "@context": { + "replace": { + "@id": "https://w3id.org/traceability#workflow-replace", + "@type": "@id" + }, + "workflow": { + "@id": "https://w3id.org/traceability#workflow", + "@context": { + "definition": { + "@id": "https://w3id.org/traceability#workflow-definition", + "@type": "@id" + }, + "instance": { + "@id": "https://w3id.org/traceability#workflow-instance", + "@type": "@id" + } + } + } + } + }, + "AgricultureActivity": { + "@id": "https://w3id.org/traceability#AgricultureActivity", + "@context": { + "business": { + "@id": "https://w3id.org/traceability#dfn-entities" + }, + "actor": { + "@id": "https://w3id.org/traceability#Person" + }, + "location": { + "@id": "https://www.gs1.org/voc/Place" + }, + "activityDate": { + "@id": "https://schema.org/DateTime" + }, + "activityType": { + "@id": "https://schema.org/description" + }, + "agricultureProduct": { + "@id": "https://schema.org/ItemList" + }, + "observation": { + "@id": "https://w3id.org/traceability#observation" + } + } + }, + "AgricultureInspectionCommonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo", + "@context": { + "applicant": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "facility": { + "@id": "https://www.gs1.org/voc/location" + }, + "inspector": { + "@id": "https://w3id.org/traceability#Inspector" + }, + "delegateOf": { + "@id": "https://vocabulary.uncefact.org/specifiedLegalOrganization" + }, + "regulatoryAgency": { + "@id": "https://vocabulary.uncefact.org/specifiedLegalOrganization" + }, + "inspectionStarted": { + "@id": "https://schema.org/startDate" + }, + "inspectionEnded": { + "@id": "https://schema.org/endDate" + } + } + }, + "AgricultureInspectionGeneric": { + "@id": "https://w3id.org/traceability#AgricultureInspectionGeneric", + "@context": { + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "inspectionType": { + "@id": "https://www.gs1.org/voc/certificationType" + }, + "observation": { + "@id": "https://vocabulary.uncefact.org/relatedObservation" + }, + "name": { + "@id": "https://schema.org/name" + }, + "status": { + "@id": "https://vocabulary.uncefact.org/status" + }, + "productQuantity": { + "@id": "https://vocabulary.uncefact.org/Measurement" + }, + "packageSize": { + "@id": "https://vocabulary.uncefact.org/Measurement" + }, + "inspectorCounted": { + "@id": "https://vocabulary.uncefact.org/applicableSpecifiedAction" + } + } + }, + "AgriculturePackage": { + "@id": "https://w3id.org/traceability#AgriculturePackage", + "@context": { + "packageName": { + "@id": "https://schema.org/name" + }, + "grade": { + "@id": "https://w3id.org/traceability#grade" + }, + "responsibleParty": { + "@id": "https://w3id.org/traceability#responsibleParty" + }, + "voicePickCode": { + "@id": "https://w3id.org/traceability#voicePickCode" + }, + "date": { + "@id": "https://schema.org/DateTime" + }, + "labelImageUrl": { + "@id": "https://schema.org/url" + }, + "labelImageHash": { + "@id": "https://w3id.org/traceability#labelImageHash" + }, + "agricultureProduct": { + "@id": "https://schema.org/ItemList" + }, + "harvest": { + "@id": "https://w3id.org/traceability#AgricultureActivity" + } + } + }, + "AgricultureParcelDelivery": { + "@id": "https://w3id.org/traceability#AgricultureParcelDelivery", + "@context": { + "deliveryAddress": { + "@id": "https://schema.org/deliveryAddress" + }, + "originAddress": { + "@id": "https://schema.org/originAddress" + }, + "foreignPortExport": { + "@id": "https://schema.org/itinerary" + }, + "portOfEntry": { + "@id": "https://schema.org/itinerary" + }, + "deliveryMethod": { + "@id": "https://schema.org/hasDeliveryMethod" + }, + "trackingNumber": { + "@id": "https://schema.org/trackingNumber" + }, + "expectedArrival": { + "@id": "https://schema.org/expectedArrivalFrom" + }, + "specialInstructions": { + "@id": "https://schema.org/comment" + }, + "consignee": { + "@id": "https://schema.org/Organization" + }, + "agriculturePackage": { + "@id": "https://schema.org/itemShipped" + }, + "movementPoints": { + "@id": "https://schema.org/itinerary" + }, + "plannedRoute": { + "@id": "https://schema.org/itinerary" + }, + "shipper": { + "@id": "https://schema.org/seller" + }, + "purchaser": { + "@id": "https://schema.org/buyer" + }, + "carrier": { + "@id": "https://schema.org/carrier" + }, + "broker": { + "@id": "https://schema.org/broker" + } + } + }, + "AgricultureProduct": { + "@id": "https://w3id.org/traceability#AgricultureProduct", + "@context": { + "plu": { + "@id": "https://schema.org/identifier" + }, + "product": { + "@id": "https://www.gs1.org/voc/Product" + }, + "scientificName": { + "@id": "https://vocabulary.uncefact.org/scientificName" + }, + "plantParts": { + "@id": "https://schema.org/description" + }, + "labelImageUrl": { + "@id": "https://schema.org/url" + }, + "labelImageHash": { + "@id": "https://w3id.org/traceability#labelImageHash" + }, + "name": { + "@id": "https://schema.org/name" + }, + "variety": { + "@id": "https://www.gs1.org/voc/consumerProductVariant" + }, + "commodityDesignation": { + "@id": "https://www.gs1.org/voc/additionalProductDescription" + }, + "packType": { + "@id": "https://www.gs1.org/voc/packaging" + } + } + }, + "BankAccount": { + "@id": "https://w3id.org/traceability#BankAccount", + "@context": { + "accountId": { + "@id": "https://w3id.org/traceability#accountId" + }, + "BIC11": { + "@id": "https://w3id.org/traceability#BIC11" + }, + "iban": { + "@id": "https://w3id.org/traceability#iban" + }, + "routingInfo": { + "@id": "https://w3id.org/traceability#routingInfo" + }, + "familyName": { + "@id": "http://schema.org/familyName" + }, + "givenName": { + "@id": "http://schema.org/givenName" + }, + "address": { + "@id": "https://schema.org/PostalAddress" + } + } + }, + "BankAccountHolderAffirmation": { + "@id": "https://w3id.org/traceability#BankAccountHolderAffirmation", + "@context": { + "affirmingParty": { + "@id": "https://w3id.org/traceability#evidenceVerifier" + }, + "bankAccountHolderAffirmationApproach": { + "@id": "https://schema.org/name" + }, + "bank": { + "@id": "https://schema.org/Organization" + } + } + }, + "BillOfLading": { + "@id": "https://w3id.org/traceability#BillOfLading", + "@context": { + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "bookingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BN" + }, + "relatedDocuments": { + "@id": "https://schema.org/Purchase" + }, + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "consignor": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "notify": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "freightForwarder": { + "@id": "https://vocabulary.uncefact.org/freightForwarderParty" + }, + "freight": { + "@id": "https://schema.org/ParcelDelivery" + }, + "nmfcFreightClass": { + "@id": "https://w3id.org/traceability#nmfcFreightClass" + }, + "hazardCode": { + "@id": "https://w3id.org/traceability#hazardCode" + }, + "portOfLoading": { + "@id": "https://vocabulary.uncefact.org/LocationFunctionCodeList#9" + }, + "portOfDischarge": { + "@id": "https://vocabulary.uncefact.org/LocationFunctionCodeList#11" + }, + "particulars": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + } + } + }, + "BusinessRegistrationVerification": { + "@id": "https://w3id.org/traceability#BusinessRegistrationVerification", + "@context": { + "affirmingParty": { + "@id": "https://w3id.org/traceability#affirmingParty" + }, + "registrationUrl": { + "@id": "https://schema.org/url" + }, + "taxIdentificationNumber": { + "@id": "https://vocabulary.uncefact.org/uncl1153#AHP" + }, + "countryOfRegistration": { + "@id": "https://schema.org/country" + } + } + }, + "CBPEntry": { + "@id": "https://w3id.org/traceability#CBPEntry", + "@context": { + "portOfEntry": { + "@id": "https://schema.org/Place" + }, + "bondType": { + "@id": "https://w3id.org/traceability#bondType" + }, + "importer": { + "@id": "https://vocabulary.uncefact.org/importerParty" + }, + "importerOfRecord": { + "@id": "https://w3id.org/traceability#importerOfRecord" + }, + "entryNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" + }, + "bondValue": { + "@id": "https://schema.org/MonetaryAmount" + }, + "entryValue": { + "@id": "https://schema.org/MonetaryAmount" + }, + "centralizedExaminationSite": { + "@id": "https://w3id.org/traceability#centralizedExaminationSite" + }, + "entryType": { + "@id": "https://w3id.org/traceability#entryType" + }, + "originatingWarehouseEntryNumber": { + "@id": "https://w3id.org/traceability#originatingWarehouseEntryNumber" + }, + "suretyCode": { + "@id": "https://w3id.org/traceability#suretyCode" + }, + "portOfUnlading": { + "@id": "https://schema.org/Place" + }, + "transportMode": { + "@id": "https://w3id.org/traceability#transportMode" + }, + "locationOfGoods": { + "@id": "https://schema.org/Place" + }, + "generalOrderNumber": { + "@id": "https://w3id.org/traceability#generalOrderNumber" + }, + "conveyanceNameOrFreeTradeZoneID": { + "@id": "https://w3id.org/traceability#conveyanceNameOrFreeTradeZoneID" + }, + "referenceIDCode": { + "@id": "https://w3id.org/traceability#referenceIDCode" + }, + "referenceIDNumber": { + "@id": "https://w3id.org/traceability#referenceIDNumber" + }, + "lineItems": { + "@id": "https://w3id.org/traceability#lineItems" + }, + "nonAMS": { + "@id": "https://w3id.org/traceability#nonAMS" + }, + "splitBill": { + "@id": "https://w3id.org/traceability#splitBill" + }, + "bolType": { + "@id": "https://w3id.org/traceability#bolType" + }, + "scac": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" + }, + "inBondNumber": { + "@id": "https://w3id.org/traceability#inBondNumber" + }, + "bolNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "quantity": { + "@id": "https://w3id.org/traceability#quantity" + }, + "voyageFlightTrip": { + "@id": "https://w3id.org/traceability#voyageFlightTrip" + }, + "conveyanceName": { + "@id": "https://w3id.org/traceability#conveyanceName" + }, + "arrivalDate": { + "@id": "https://vocabulary.uncefact.org/actualArrivalRelatedDateTime" + } + } + }, + "CBPEntryEntity": { + "@id": "https://w3id.org/traceability#CBPEntryEntity", + "@context": { + "importerOfRecord": { + "@id": "https://w3id.org/traceability#importerOfRecord" + } + } + }, + "CBPEntryLineItem": { + "@id": "https://w3id.org/traceability#CBPEntryLineItem", + "@context": { + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "productDescription": { + "@id": "https://schema.org/description" + }, + "itemCount": { + "@id": "https://vocabulary.uncefact.org/despatchedQuantity" + }, + "itemParty": { + "@id": "https://w3id.org/traceability#itemParty" + }, + "freeTradeZoneFilingDate": { + "@id": "https://schema.org/Date" + }, + "freeTradeZoneStatus": { + "@id": "https://w3id.org/traceability#freeTradeZoneStatus" + }, + "countryOfOrigin": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "value": { + "@id": "https://schema.org/MonetaryAmount" + } + } + }, + "CBPEntrySummary": { + "@id": "https://w3id.org/traceability#CBPEntrySummary", + "@context": { + "entryNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" + }, + "entryType": { + "@id": "https://w3id.org/traceability#entryType" + }, + "summaryDate": { + "@id": "https://schema.org/Date" + }, + "suretyCode": { + "@id": "https://w3id.org/traceability#suretyCode" + }, + "bondType": { + "@id": "https://w3id.org/traceability#bondType" + }, + "portCode": { + "@id": "https://schema.org/Place" + }, + "entryDate": { + "@id": "https://schema.org/Date" + }, + "importingCarrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "transportMode": { + "@id": "https://w3id.org/traceability#transportMode" + }, + "countryOfOrigin": { + "@id": "https://w3id.org/traceability#countryOfOrigin" + }, + "importDate": { + "@id": "https://schema.org/Date" + }, + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "manufacturerId": { + "@id": "https://schema.org/identifier" + }, + "exportingCountry": { + "@id": "https://schema.org/addressCountry" + }, + "exportDate": { + "@id": "https://schema.org/Date" + }, + "immediateTransportationNumber": { + "@id": "https://schema.org/identifier" + }, + "immediateTransportationDate": { + "@id": "https://schema.org/Date" + }, + "missingDocuments": { + "@id": "https://w3id.org/traceability#missingDocuments" + }, + "portOfLoading": { + "@id": "https://schema.org/Place" + }, + "portOfUnlading": { + "@id": "https://schema.org/Place" + }, + "locationOfGoods": { + "@id": "https://schema.org/Place" + }, + "consigneeNumber": { + "@id": "https://schema.org/identifier" + }, + "importerNumber": { + "@id": "https://w3id.org/traceability#importerOfRecord" + }, + "referenceNumber": { + "@id": "https://w3id.org/traceability#referenceNumber" + }, + "ultimateConsignee": { + "@id": "https://vocabulary.uncefact.org/shipToParty" + }, + "importerOfRecord": { + "@id": "https://vocabulary.uncefact.org/importerParty" + }, + "descriptionOfMerchandise": { + "@id": "https://w3id.org/traceability#descriptionOfMerchandise" + }, + "otherFeeSummary": { + "@id": "https://w3id.org/traceability#otherFeeSummary" + }, + "totalEnteredValue": { + "@id": "https://schema.org/MonetaryAmount" + }, + "declarationOfImporter": { + "@id": "https://w3id.org/traceability#declarationOfImporter" + }, + "duty": { + "@id": "https://schema.org/MonetaryAmount" + }, + "tax": { + "@id": "https://schema.org/MonetaryAmount" + }, + "other": { + "@id": "https://schema.org/MonetaryAmount" + }, + "total": { + "@id": "https://schema.org/MonetaryAmount" + } + } + }, + "CBPEntrySummaryLineItem": { + "@id": "https://w3id.org/traceability#CBPEntrySummaryLineItem", + "@context": { + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "adCvdNumber": { + "@id": "https://w3id.org/traceability#adCvdNumber" + }, + "categoryNumber": { + "@id": "https://w3id.org/traceability#categoryNumber" + }, + "otherFees": { + "@id": "https://w3id.org/traceability#otherFees" + }, + "grossWeight": { + "@id": "https://schema.org/weight" + }, + "manifestQuantity": { + "@id": "https://w3id.org/traceability#manifestQuantity" + }, + "netQuantity": { + "@id": "https://schema.org/Quantity" + }, + "enteredValue": { + "@id": "https://schema.org/MonetaryAmount" + }, + "charges": { + "@id": "https://schema.org/MonetaryAmount" + }, + "relationship": { + "@id": "https://schema.org/MonetaryAmount" + }, + "htsRate": { + "@id": "https://w3id.org/traceability#htsRate" + }, + "adCvdRate": { + "@id": "https://w3id.org/traceability#adCvdRate" + }, + "ircRate": { + "@id": "https://w3id.org/traceability#ircRate" + }, + "visaNumber": { + "@id": "https://w3id.org/traceability#visaNumber" + }, + "agriculturalLicenseNumber": { + "@id": "https://w3id.org/traceability#agriculturalLicenseNumber" + }, + "dutyAndIRTax": { + "@id": "https://w3id.org/traceability#dutyAndIRTax" + } + } + }, + "CBPEntryType86": { + "@id": "https://w3id.org/traceability#CBPEntryType86", + "@context": { + "bolNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "entryNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" + }, + "portOfEntry": { + "@id": "https://schema.org/Place" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "countryOfOrigin": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "quantity": { + "@id": "https://w3id.org/traceability#quantity" + }, + "fairRetailValue": { + "@id": "https://schema.org/MonetaryAmount" + }, + "htsusNumber": { + "@id": "https://w3id.org/traceability#commodityCode" + }, + "importerOfRecord": { + "@id": "https://w3id.org/traceability#importerOfRecord" + } + } + }, + "CBPImporterOfRecord": { + "@id": "https://w3id.org/traceability#CBPImporterOfRecord", + "@context": { + "number": { + "@id": "https://w3id.org/traceability#CBPImporterOfRecordNumber" + }, + "identifierType": { + "@id": "https://w3id.org/traceability#CBPImporterOfRecordType" + } + } + }, + "CTPAT": { + "@id": "https://w3id.org/traceability#CTPAT", + "@context": { + "sviNumber": { + "@id": "https://w3id.org/traceability#sviNumber" + }, + "ctpatAccountNumber": { + "@id": "https://w3id.org/traceability#ctpatAccountNumber" + }, + "tradeSector": { + "@id": "https://schema.org/industry" + }, + "tier": { + "@id": "https://w3id.org/traceability#ctpatTier" + }, + "dateOfLastValidation": { + "@id": "https://schema.org/Date" + }, + "issuingCountry": { + "@id": "https://schema.org/addressCountry" + } + } + }, + "CTPATEIPApplication": { + "@id": "https://w3id.org/traceability#CTPAT", + "@context": { + "applicant": { + "@id": "https://w3id.org/traceability#applicant" + }, + "applicantType": { + "@id": "https://w3id.org/traceability#applicantType" + } + } + }, + "CTPATMember": { + "@id": "https://schema.org/Organization", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "scac": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" + }, + "iataCarrierCode": { + "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" + }, + "importerOfRecord": { + "@id": "https://w3id.org/traceability#importerOfRecord" + }, + "faxNumber": { + "@id": "https://schema.org/faxNumber" + }, + "url": { + "@id": "https://schema.org/url" + }, + "logo": { + "@id": "https://schema.org/logo" + } + } + }, + "CargoItem": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/cargoItem", + "@context": { + "cargoLineItems": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/cargoLineItem" + }, + "carrierBookingReference": { + "@id": "https://vocabulary.uncefact.org/carrierAssignedId" + }, + "weight": { + "@id": "https://schema.org/weight" + }, + "volume": { + "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" + }, + "weightUnit": { + "@id": "https://schema.org/unitCode" + }, + "volumeUnit": { + "@id": "https://schema.org/unitCode" + }, + "numberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "packageCode": { + "@id": "https://vocabulary.uncefact.org/packageTypeCode" + } + } + }, + "CargoLineItem": { + "@id": "https://w3id.org/traceability#CargoLineItem", + "@context": { + "cargoLineItemID": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/cargoLineItemID" + }, + "shippingMarks": { + "@id": "https://vocabulary.uncefact.org/physicalShippingMarks" + }, + "descriptionOfGoods": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/descriptionOfGoods" + }, + "HSCode": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/HSCode" + } + } + }, + "ChargeDeclaration": { + "@id": "https://w3id.org/traceability#ChargeDeclaration", + "@context": { + "weightCharge": { + "@id": "https://schema.org/price" + }, + "valuationCharge": { + "@id": "https://schema.org/price" + }, + "tax": { + "@id": "https://schema.org/price" + }, + "dueAgent": { + "@id": "https://schema.org/price" + }, + "dueCarrier": { + "@id": "https://schema.org/price" + }, + "total": { + "@id": "https://schema.org/totalPrice" + } + } + }, + "ChemicalProperty": { + "@id": "https://w3id.org/traceability#ChemicalProperty", + "@context": { + "identifier": { + "@id": "https://schema.org/identifier" + }, + "name": { + "@id": "https://schema.org/name" + }, + "description": { + "@id": "https://schema.org/description" + }, + "formula": { + "@id": "https://purl.obolibrary.org/obo/chebi/formula" + }, + "inchi": { + "@id": "https://purl.obolibrary.org/obo/chebi/inchi" + }, + "inchikey": { + "@id": "https://purl.obolibrary.org/obo/chebi/inchikey" + } + } + }, + "CommissionEvent": { + "@id": "https://w3id.org/traceability#CommissionEvent", + "@context": { + "place": { + "@id": "https://schema.org/Place" + }, + "organization": { + "@id": "https://w3id.org/traceability#Organization" + }, + "products": { + "@id": "https://schema.org/Product" + } + } + }, + "Commodity": { + "@id": "https://w3id.org/traceability#Commodity", + "@context": { + "commodityCode": { + "@id": "https://w3id.org/traceability#commodityCode" + }, + "commodityCodeType": { + "@id": "https://w3id.org/traceability#commodityCodeType" + }, + "description": { + "@id": "https://schema.org/description" + } + } + }, + "ConsignmentItem": { + "@id": "https://vocabulary.uncefact.org/ConsignmentItem", + "@context": { + "marksAndNumbers": { + "@id": "https://vocabulary.uncefact.org/ShippingMarks" + }, + "descriptionOfPackagesAndGoods": { + "@id": "https://vocabulary.uncefact.org/natureIdentificationCargo" + }, + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "packageQuantity": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "netWeight": { + "@id": "https://schema.org/weight" + }, + "grossWeight": { + "@id": "https://schema.org/weight" + }, + "grossVolume": { + "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" + }, + "countryOfOrigin": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "manufacturer": { + "@id": "https://vocabulary.uncefact.org/manufacturerParty" + }, + "transportPackages": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + } + } + }, + "ConsignmentRatingDetail": { + "@id": "https://w3id.org/traceability#ConsignmentRatingDetail", + "@context": { + "numberOfPieces": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "grossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "grossWeightUnit": { + "@id": "https://schema.org/unitCode" + }, + "rateClass": { + "@id": "https://vocabulary.uncefact.org/freightChargeTariffClassCode" + }, + "commodityItemNumber": { + "@id": "https://vocabulary.uncefact.org/discountIndicator" + }, + "chargeableWeight": { + "@id": "https://schema.org/weight" + }, + "rateCharge": { + "@id": "https://schema.org/price" + }, + "total": { + "@id": "https://schema.org/totalPrice" + }, + "natureAndVolumeOfGoods": { + "@id": "https://schema.org/description" + } + } + }, + "ContactPoint": { + "@id": "https://schema.org/ContactPoint", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "place": { + "@id": "https://w3id.org/traceability#place" + }, + "email": { + "@id": "https://schema.org/email" + }, + "phoneNumber": { + "@id": "https://schema.org/telephone" + } + } + }, + "Customer": { + "@id": "https://w3id.org/traceability#Customer", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "address": { + "@id": "https://schema.org/PostalAddress" + }, + "telephone": { + "@id": "https://schema.org/telephone" + }, + "email": { + "@id": "https://schema.org/email" + } + } + }, + "DCSAShippingInstruction": { + "@id": "https://vocabulary.uncefact.org/TransportInstructions", + "@context": { + "shippingInstructionID": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#TIN" + }, + "transportDocumentType": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/transportDocumentType" + }, + "preCarriageUnderShippersResponsibility": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/preCarriageUnderShippersResponsibility" + }, + "invoicePayableAt": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/invoicePayableAt" + }, + "carrierBookingReference": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BN" + }, + "cargoItems": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "utilizedTransportEquipments": { + "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" + }, + "shipmentLocations": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DOCUMENTATION_DOMAIN/1.0.0#/components/schemas/shipmentLocation" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "invoicePayerShipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "invoicePayerConsignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "firstNotify": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "secondNotify": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "otherNotify": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "shippersFreightForwarder": { + "@id": "https://vocabulary.uncefact.org/freightForwarderParty" + }, + "consigneesFreightForwarder": { + "@id": "https://vocabulary.uncefact.org/freightForwarderParty" + } + } + }, + "DCSATransportDocument": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/transportDocument", + "@context": { + "transportDocumentReference": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "placeOfIssue": { + "@id": "https://vocabulary.uncefact.org/issueLocation" + }, + "issueDate": { + "@id": "https://vocabulary.uncefact.org/issueDateTime" + }, + "shippedOnBoardDate": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/shippedOnBoardDate" + }, + "receivedForShipmentDate": { + "@id": "https://vocabulary.uncefact.org/availabilityDueDateTime" + }, + "termsAndConditions": { + "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" + }, + "issuerCode": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" + }, + "issuerCodeListProvider": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/issuerCodeListProvider" + }, + "declaredValueCurrency": { + "@id": "https://schema.org/currency" + }, + "cargoMovementTypeAtOrigin": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/cargoMovementTypeAtOrigin" + }, + "cargoMovementTypeAtDestination": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/cargoMovementTypeAtDestination" + }, + "receiptDeliveryTypeAtOrigin": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/receiptDeliveryTypeAtOrigin" + }, + "receiptDeliveryTypeAtDestination": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/receiptDeliveryTypeAtDestination" + }, + "serviceContractReference": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/serviceContractReference" + }, + "shippingInstruction": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/shippingInstruction" + }, + "charges": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/charges" + }, + "clauses": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/clauses" + }, + "transports": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/transports" + } + } + }, + "DeMinimisShipment": { + "@id": "https://w3id.org/traceability#DeMinimisShipment", + "@context": { + "originatorCode": { + "@id": "https://w3id.org/traceability#originatorCode" + }, + "participantFilerType": { + "@id": "https://w3id.org/traceability#participantFilerType" + }, + "shipmentTrackingNumber": { + "@id": "https://vocabulary.uncefact.org/MarkingInstructionCodeList#37" + }, + "houseBillOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BH" + }, + "masterBillOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "modeOfTransportation": { + "@id": "https://vocabulary.uncefact.org/mode" + }, + "shipmentInitiator": { + "@id": "https://w3id.org/traceability#shipmentInitiator" + }, + "seller": { + "@id": "https://vocabulary.uncefact.org/sellerParty" + }, + "buyer": { + "@id": "https://vocabulary.uncefact.org/buyerParty" + }, + "finalDeliverTo": { + "@id": "https://vocabulary.uncefact.org/shipToParty" + }, + "enhancedProductDescription": { + "@id": "https://w3id.org/traceability#enhancedProductDescription" + }, + "shipmentSecurityScan": { + "@id": "https://w3id.org/traceability#shipmentSecurityScan" + }, + "knownCarrierCustomerFlag": { + "@id": "https://w3id.org/traceability#knownCarrierCustomerFlag" + }, + "knownMarketplaceSellerFlag": { + "@id": "https://w3id.org/traceability#knownMarketplaceSellerFlag" + }, + "marketplaceSellerAccountNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#ADE" + }, + "productPicture": { + "@id": "https://schema.org/image" + }, + "listedPriceOnMarketplace": { + "@id": "https://schema.org/price" + } + } + }, + "DeliverySchedule": { + "@id": "https://w3id.org/traceability#DeliverySchedule", + "@context": { + "transporter": { + "@id": "https://schema.org/agent" + }, + "batchNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BT" + }, + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "place": { + "@id": "https://schema.org/toLocation" + }, + "consignor": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "scheduledVolume": { + "@id": "https://w3id.org/traceability#QuantitativeValue" + }, + "scheduledDate": { + "@id": "https://schema.org/departureTime" + }, + "injectionVolume": { + "@id": "https://w3id.org/traceability#QuantitativeValue" + }, + "injectionDate": { + "@id": "https://schema.org/departureTime" + }, + "injectionEndDate": { + "@id": "https://schema.org/departureTime" + }, + "deliveryDate": { + "@id": "https://schema.org/arrivalTime" + }, + "deliveryEndDate": { + "@id": "https://schema.org/arrivalTime" + }, + "portOfEntry": { + "@id": "https://w3id.org/traceability#Place" + }, + "portOfDestination": { + "@id": "https://w3id.org/traceability#Place" + }, + "portOfArrival": { + "@id": "https://w3id.org/traceability#Place" + }, + "addressCountry": { + "@id": "https://schema.org/addressCountry" + } + } + }, + "DeliveryStatement": { + "@id": "https://w3id.org/traceability#DeliveryStatement", + "@context": { + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "deliveredDate": { + "@id": "https://schema.org/Date" + }, + "deliveredVolume": { + "@id": "https://schema.org/MeasuredValue" + }, + "observation": { + "@id": "https://w3id.org/traceability#observation" + } + } + }, + "EDDShape": { + "@id": "https://w3id.org/traceability#EDDShape", + "@context": { + "meta": { + "@id": "https://w3id.org/traceability#EDDShapeMeta" + }, + "reporter": { + "@id": "https://schema.org/name" + }, + "scientificName": { + "@id": "http://rs.tdwg.org/dwc/terms/scientificName" + }, + "commonName": { + "@id": "http://rs.tdwg.org/dwc/terms/vernacularName" + }, + "subjectNativity": { + "@id": "http://rs.tdwg.org/dwc/terms/establishmentMeans" + }, + "occurrenceStatus": { + "@id": "http://rs.tdwg.org/dwc/iri/measurementValue" + }, + "status": { + "@id": "https://schema.org/description" + }, + "observationDate": { + "@id": "http://rs.tdwg.org/dwc/terms/eventDate" + }, + "dateEntered": { + "@id": "http://rs.tdwg.org/dwc/terms/eventDate" + }, + "dateUpdated": { + "@id": "http://rs.tdwg.org/dwc/terms/eventDate" + }, + "location": { + "@id": "https://schema.org/location" + }, + "mapResources": { + "@id": "https://w3id.org/traceability#MapResource" + }, + "naDatum": { + "@id": "http://rs.tdwg.org/dwc/terms/geodeticDatum" + }, + "coordinateUncertainty": { + "@id": "http://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters" + }, + "centroidType": { + "@id": "https://schema.org/polygon" + }, + "abundance": { + "@id": "https://schema.org/description" + }, + "infestedAreaAcres": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "grossAreaAcres": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "percentCover": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "density": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementRemarks" + }, + "quantity": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "quantityUnits": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantityType" + }, + "approximateQuantity": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "incidence": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "severity": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "managementStatus": { + "@id": "https://schema.org/status" + }, + "habitat": { + "@id": "http://rs.tdwg.org/dwc/terms/habitat" + }, + "siteName": { + "@id": "http://rs.tdwg.org/dwc/terms/locationID" + }, + "recordBasis": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" + }, + "surveyor": { + "@id": "http://rs.tdwg.org/dwc/terms/recordedBy" + }, + "dateUncertaintyDays": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementAccuracy" + }, + "visitType": { + "@id": "https://schema.org/description" + }, + "persistentId": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceID" + }, + "uuid": { + "@id": "http://rs.tdwg.org/dwc/terms/dateIdentified" + }, + "reviewer": { + "@id": "http://rs.tdwg.org/dwc/terms/identifiedBy" + }, + "verificationMethod": { + "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" + }, + "verified": { + "@id": "http://rs.tdwg.org/dwc/terms/identificationVerificationStatus" + }, + "identificationCredibility": { + "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" + } + } + }, + "EDDShapeMeta": { + "@id": "https://w3id.org/traceability#EDDShapeMeta", + "@context": { + "recordOwner": { + "@id": "https://schema.org/name" + }, + "shapeType": { + "@id": "https://schema.org/description" + }, + "method": { + "@id": "http://rs.tdwg.org/dwc/terms/locationRemarks" + }, + "numberCollected": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementRemarks" + }, + "populationStatus": { + "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" + }, + "smallestOrganismSampled": { + "@id": "https://schema.org/size" + }, + "largestOrganismSampled": { + "@id": "https://schema.org/size" + }, + "hostScientificName": { + "@id": "http://rs.tdwg.org/dwc/terms/scientificName" + }, + "hostName": { + "@id": "http://rs.tdwg.org/dwc/terms/vernacularName" + }, + "hostPhenology": { + "@id": "http://rs.tdwg.org/dwc/terms/lifeStage" + }, + "hostDamage": { + "@id": "https://schema.org/description" + }, + "localOwnership": { + "@id": "http://rs.tdwg.org/dwc/terms/locality" + }, + "museum": { + "@id": "https://schema.org/name" + }, + "museumRecord": { + "@id": "http://rs.tdwg.org/dwc/terms/catalogNumber" + }, + "voucher": { + "@id": "http://rs.tdwg.org/dwc/terms/disposition" + }, + "observationId": { + "@id": "http://rs.tdwg.org/dwc/terms/identifiedBy" + }, + "collectionTimeMinutes": { + "@id": "https://schema.org/activityDuration" + }, + "originalRecordId": { + "@id": "http://rs.tdwg.org/dwc/terms/recordNumber" + }, + "originalReportedName": { + "@id": "http://rs.tdwg.org/dwc/terms/verbatimIdentification" + }, + "recordSourceType": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementRemarks" + }, + "dataCollectionMethod": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementMethod" + }, + "trapType": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" + }, + "numberTraps": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingEffort" + }, + "targetName": { + "@id": "http://rs.tdwg.org/dwc/terms/organismName" + }, + "targetCount": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "targetRange": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "phenology": { + "@id": "http://rs.tdwg.org/dwc/terms/organismRemarks" + }, + "lifeStatus": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + }, + "sex": { + "@id": "http://rs.tdwg.org/dwc/terms/sex" + }, + "waterBodyName": { + "@id": "http://rs.tdwg.org/dwc/terms/waterBody" + }, + "waterBodyType": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + }, + "substrate": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + }, + "treatmentArea": { + "@id": "http://rs.tdwg.org/dwc/iri/measurementValue" + }, + "plantsTreated": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "treatmentComments": { + "@id": "http://rs.tdwg.org/dwc/terms/eventRemarks" + }, + "reference": { + "@id": "http://rs.tdwg.org/dwc/terms/associatedReferences" + }, + "locality": { + "@id": "http://rs.tdwg.org/dwc/terms/locationRemarks" + }, + "comments": { + "@id": "http://rs.tdwg.org/dwc/terms/eventRemarks" + }, + "publicReviewerComments": { + "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" + } + } + }, + "Entity": { + "@id": "https://w3id.org/traceability#Entity", + "@context": { + "entityType": { + "@id": "https://schema.org/additionalType" + }, + "name": { + "@id": "https://schema.org/name" + }, + "legalName": { + "@id": "https://schema.org/legalName" + }, + "url": { + "@id": "https://schema.org/url" + }, + "taxId": { + "@id": "https://schema.org/taxID" + }, + "address": { + "@id": "https://schema.org/PostalAddress" + }, + "email": { + "@id": "https://schema.org/email" + }, + "phoneNumber": { + "@id": "https://schema.org/telephone" + }, + "faxNumber": { + "@id": "https://schema.org/faxNumber" + } + } + }, + "EntryNumber": { + "@id": "https://w3id.org/traceability#EntryNumber", + "@context": { + "entryNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" + } + } + }, + "Event": { + "@id": "https://w3id.org/traceability#EventCredential", + "@context": {} + }, + "ExternalResource": { + "@id": "https://w3id.org/traceability#ExternalResource", + "@context": { + "uri": { + "@id": "https://schema.org/contentUrl" + }, + "hash": { + "@id": "https://schema.org/sha256" + } + } + }, + "FSMAAbstractKDE": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE", + "@context": { + "name": { + "@id": "https://schema.org/propertyID" + }, + "value": { + "@id": "https://schema.org/value" + } + } + }, + "FSMACreatingCTE": { + "@id": "https://w3id.org/traceability#FSMACreatingCTE", + "@context": { + "food": { + "@id": "https://w3id.org/traceability#FSMAProduct" + }, + "location": { + "@id": "https://schema.org/location" + }, + "dateCompleted": { + "@id": "https://schema.org/endDate" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMAFirstReceiverData": { + "@id": "https://w3id.org/traceability#FSMAFirstReceiverData", + "@context": { + "traceabilityLot": { + "@id": "https://w3id.org/traceability#FSMATraceabilityLot" + }, + "originatorLocation": { + "@id": "https://schema.org/location" + }, + "harvestDate": { + "@id": "https://schema.org/endDate" + }, + "coolingLocation": { + "@id": "https://schema.org/location" + }, + "coolingDate": { + "@id": "https://schema.org/endDate" + }, + "packingLocation": { + "@id": "https://schema.org/location" + }, + "packingDate": { + "@id": "https://schema.org/endDate" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMAGrowingCTE": { + "@id": "https://w3id.org/traceability#FSMAGrowingCTE", + "@context": { + "traceabilityLot": { + "@id": "https://w3id.org/traceability#FSMATraceabilityLot" + }, + "growingAreaCoordinates": { + "@id": "https://w3id.org/traceability#GeoCoordinates" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMAProduct": { + "@id": "https://w3id.org/traceability#FSMAProduct", + "@context": { + "traceabilityLot": { + "@id": "https://w3id.org/traceability#FSMATraceabilityLot" + }, + "quantity": { + "@id": "https://vocabulary.uncefact.org/applicableQuantity" + }, + "unit": { + "@id": "https://vocabulary.uncefact.org/applicableQuantityUnitTypeCode" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMAReceivingCTE": { + "@id": "https://w3id.org/traceability#FSMAReceivingCTE", + "@context": { + "shipment": { + "@id": "https://w3id.org/traceability#FSMAShipment" + }, + "dateReceived": { + "@id": "https://schema.org/endDate" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMAShipment": { + "@id": "https://w3id.org/traceability#FSMAShipment", + "@context": { + "product": { + "@id": "https://w3id.org/traceability#FSMAProduct" + }, + "from": { + "@id": "https://schema.org/fromLocation" + }, + "to": { + "@id": "https://schema.org/toLocation" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMAShippingCTE": { + "@id": "https://w3id.org/traceability#FSMAShippingCTE", + "@context": { + "shipment": { + "@id": "https://w3id.org/traceability#FSMAShipment" + }, + "dateShipped": { + "@id": "https://schema.org/startDate" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMATraceabilityLot": { + "@id": "https://w3id.org/traceability#FSMATraceabilityLot", + "@context": { + "lotCode": { + "@id": "https://www.gs1.org/voc/hasBatchLotNumber" + }, + "lotCodeAssignmentMethod": { + "@id": "https://schema.org/description" + }, + "lotCodeGeneratorLocation": { + "@id": "https://schema.org/location" + }, + "lotCodeGeneratorPOC": { + "@id": "https://schema.org/contactPoint" + }, + "lotType": { + "@id": "https://schema.org/additionalType" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FSMATransformingCTE": { + "@id": "https://w3id.org/traceability#FSMATransformingCTE", + "@context": { + "foodUsed": { + "@id": "https://w3id.org/traceability#FSMAProduct" + }, + "foodProduced": { + "@id": "https://w3id.org/traceability#FSMAProduct" + }, + "locationTransformed": { + "@id": "https://schema.org/location" + }, + "dateCompleted": { + "@id": "https://schema.org/endDate" + }, + "additionalData": { + "@id": "https://w3id.org/traceability#FSMAAbstractKDE" + } + } + }, + "FoodDefenseDeficiency": { + "@id": "https://w3id.org/traceability#FoodDefenseDeficiency", + "@context": { + "number": { + "@id": "https://schema.org/identifier" + }, + "description": { + "@id": "https://schema.org/description" + }, + "proposedCorrectionDate": { + "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" + }, + "dateCorrected": { + "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" + } + } + }, + "FoodDefenseInspection": { + "@id": "https://w3id.org/traceability#FoodDefenseInspection", + "@context": { + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "questions": { + "@id": "https://w3id.org/traceability#FoodDefenseQuestion" + }, + "deficiencies": { + "@id": "https://w3id.org/traceability#FoodDefenseDeficiency" + } + } + }, + "FoodDefenseQuestion": { + "@id": "https://w3id.org/traceability#FoodDefenseQuestion", + "@context": { + "number": { + "@id": "https://schema.org/identifier" + }, + "facility": { + "@id": "https://schema.org/location" + }, + "response": { + "@id": "https://vocabulary.uncefact.org/assertion" + }, + "rating": { + "@id": "https://vocabulary.uncefact.org/assertion" + } + } + }, + "FoodGradeInspection": { + "@id": "https://w3id.org/traceability#FoodGradeInspection", + "@context": { + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "loadingStatus": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "carrierTypeName": { + "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" + }, + "refrigerationUnitOn": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "doorsOpen": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "lots": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionLot" + }, + "generalRemarks": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "estimatedCharges": { + "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" + } + } + }, + "FoodGradeInspectionDefect": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionDefect", + "@context": { + "offsizeDefect": { + "@id": "https://vocabulary.uncefact.org/damageRemarks" + }, + "averageDefects": { + "@id": "https://qudt.org/vocab/unit/PERCENT" + }, + "damage": { + "@id": "https://qudt.org/vocab/unit/PERCENT" + }, + "seriousDamage": { + "@id": "https://qudt.org/vocab/unit/PERCENT" + }, + "verySeriousDamage": { + "@id": "https://qudt.org/vocab/unit/PERCENT" + } + } + }, + "FoodGradeInspectionLot": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionLot", + "@context": { + "agricultureProduct": { + "@id": "https://w3id.org/traceability#AgricultureProduct" + }, + "lotIdentifier": { + "@id": "https://www.gs1.org/voc/hasBatchLotNumber" + }, + "numberContainers": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "countInspected": { + "@id": "https://vocabulary.uncefact.org/remark" + }, + "brandMarkings": { + "@id": "https://vocabulary.uncefact.org/brandName" + }, + "samples": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionSample" + }, + "defects": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionDefect" + }, + "grade": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionResult" + }, + "remarks": { + "@id": "https://vocabulary.uncefact.org/remark" + }, + "minTemperature": { + "@id": "https://schema.org/measuredValue" + }, + "maxTemperature": { + "@id": "https://schema.org/measuredValue" + } + } + }, + "FoodGradeInspectionResult": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionResult", + "@context": { + "gradeInspected": { + "@id": "https://vocabulary.uncefact.org/standard" + }, + "requirementsMet": { + "@id": "https://vocabulary.uncefact.org/assertion" + }, + "details": { + "@id": "https://vocabulary.uncefact.org/additionalInformationNote" + } + } + }, + "FoodGradeInspectionSample": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionSample", + "@context": { + "sampleSizeValue": { + "@id": "https://vocabulary.uncefact.org/applicableQuantity" + }, + "sampleSizeUnits": { + "@id": "https://vocabulary.uncefact.org/applicableQuantityUnitTypeCode" + }, + "sampleProperties": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionSampleProperty" + } + } + }, + "FoodGradeInspectionSampleProperty": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionSampleProperty", + "@context": { + "propertyName": { + "@id": "https://vocabulary.uncefact.org/parameterValue" + }, + "propertyValue": { + "@id": "https://vocabulary.uncefact.org/measuredValue" + } + } + }, + "ForeignChargeDeclaration": { + "@id": "https://w3id.org/traceability#ForeignChargeDeclaration", + "@context": { + "foreignCurrencyConvertionRate": { + "@id": "https://schema.org/currentExchangeRate" + }, + "foreignChargesCurrency": { + "@id": "https://schema.org/currency" + }, + "foreignCharges": { + "@id": "https://schema.org/price" + } + } + }, + "FreightManifest": { + "@id": "https://vocabulary.uncefact.org/manifestRelatedDocument", + "@context": { + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "carrierCode": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" + }, + "transportMeans": { + "@id": "https://vocabulary.uncefact.org/transportMeans" + }, + "transportMeansId": { + "@id": "https://schema.org/identifier" + }, + "voyage": { + "@id": "https://vocabulary.uncefact.org/TransportMovement" + }, + "billsOfLading": { + "@id": "https://vocabulary.uncefact.org/manifestRelatedDocument" + } + } + }, + "GAPCorrectiveActionReport": { + "@id": "https://w3id.org/traceability#GAPCorrectiveActionReport", + "@context": { + "nonconformityDescription": { + "@id": "https://schema.org/description" + }, + "notifiedCompanyStaff": { + "@id": "https://schema.org/actionStatus" + }, + "correctiveAction": { + "@id": "https://schema.org/potentialAction" + }, + "affirmingRepresentative": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + } + } + }, + "GAPInspection": { + "@id": "https://w3id.org/traceability#GAPInspection", + "@context": { + "GAPPlus": { + "@id": "https://vocabulary.uncefact.org/documentTypeCode" + }, + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "usesLogo": { + "@id": "https://vocabulary.uncefact.org/assertion" + }, + "subjectToRule": { + "@id": "https://vocabulary.uncefact.org/regulationConformityId" + }, + "operationDescription": { + "@id": "https://schema.org/description" + }, + "harvestCompany": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "otherContractors": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "commoditiesCovered": { + "@id": "https://schema.org/ItemList" + }, + "commoditiesProduced": { + "@id": "https://schema.org/ItemList" + }, + "totalArea": { + "@id": "https://www.gs1.org/voc/grossArea" + }, + "fieldOpsHarvestingScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "postHarvestOpsScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "logoUseScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "tomatoProdHarvestingScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "tomatoPackinghouseScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "tomatoGreenhouseScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "tomatoPackingDistributionScope": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "personsInterviewed": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "requestedBy": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "distributeTo": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "additionalComments": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "reviewingOfficial": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "dateReviewed": { + "@id": "https://www.gs1.org/voc/certificationAuditDate" + }, + "meetsCriteria": { + "@id": "https://www.gs1.org/voc/certificationStatus" + }, + "requirementResults": { + "@id": "https://w3id.org/traceability#GAPRequirementResult" + } + } + }, + "GAPLocationCertification": { + "@id": "https://w3id.org/traceability#GAPLocationCertification", + "@context": { + "location": { + "@id": "https://www.gs1.org/voc/certificationSubject" + }, + "gapInspection": { + "@id": "https://www.gs1.org/voc/certification" + }, + "isCertified": { + "@id": "https://www.gs1.org/voc/certificationStatus" + } + } + }, + "GAPRequirementResult": { + "@id": "https://w3id.org/traceability#GAPRequirementResult", + "@context": { + "requirementNumber": { + "@id": "https://vocabulary.uncefact.org/standard" + }, + "resultCode": { + "@id": "https://vocabulary.uncefact.org/assertionCode" + }, + "auditorComments": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "correctiveActionReport": { + "@id": "https://w3id.org/traceability#GAPCorrectiveActionReport" + } + } + }, + "GeoCoordinates": { + "@id": "https://schema.org/GeoCoordinates", + "@context": { + "latitude": { + "@id": "https://schema.org/latitude" + }, + "longitude": { + "@id": "https://schema.org/longitude" + } + } + }, + "HouseBillOfLading": { + "@id": "https://w3id.org/traceability#HouseBillOfLading", + "@context": { + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "bookingNumber": { + "@id": "https://vocabulary.uncefact.org/carrierAssignedId" + }, + "shippersReferences": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "notifyParty": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "preCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" + }, + "mainCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" + }, + "onCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" + }, + "placeOfReceipt": { + "@id": "https://schema.org/Place" + }, + "portOfLoading": { + "@id": "https://vocabulary.uncefact.org/transshipmentLocation" + }, + "placeOfDelivery": { + "@id": "https://schema.org/Place" + }, + "portOfDischarge": { + "@id": "https://vocabulary.uncefact.org/unloadingLocation" + }, + "totalNumberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "transportEquipmentQuantity": { + "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" + }, + "includedConsignmentItems": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "freightAndCharges": { + "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" + }, + "declaredValue": { + "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" + }, + "termsAndConditions": { + "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" + } + } + }, + "IATAAirWaybill": { + "@id": "https://w3id.org/traceability#IATAAirWaybill", + "@context": { + "airWaybillNumber": { + "@id": "https://schema.org/orderNumber" + }, + "waybillType": { + "@id": "https://schema.org/DigitalDocument" + }, + "airlineCodeNumber": { + "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" + }, + "serialNumber": { + "@id": "https://schema.org/serialNumber" + }, + "airportOfDeparture": { + "@id": "https://onerecord.iata.org/cargo/Location#code" + }, + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "conditionsOfContract": { + "@id": "https://schema.org/termsOfService" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "shippersAccountNumber": { + "@id": "https://schema.org/accountId" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "consigneesAccountNumber": { + "@id": "https://schema.org/accountId" + }, + "issuingCarrierAgent": { + "@id": "https://vocabulary.uncefact.org/carrierAgentParty" + }, + "agentIATACode": { + "@id": "https://onerecord.iata.org/cargo/Company#iataCargoAgentCode" + }, + "agentAccountNumber": { + "@id": "https://schema.org/accountId" + }, + "requestedRouting": { + "@id": "https://schema.org/Trip" + }, + "destinationAirport": { + "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" + }, + "requestedFlight": { + "@id": "https://schema.org/Flight" + }, + "requestedDate": { + "@id": "https://w3id.org/traceability#requestDate" + }, + "accountingInformation": { + "@id": "https://vocabulary.uncefact.org/typeCode" + }, + "currency": { + "@id": "https://schema.org/currency" + }, + "chargeCodes": { + "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" + }, + "weightValuationChargesType": { + "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" + }, + "otherChargesType": { + "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" + }, + "declaredValueForCarriage": { + "@id": "https://schema.org/value" + }, + "declaredValueForCustoms": { + "@id": "https://vocabulary.uncefact.org/customsValueSpecifiedAmount" + }, + "amountOfInsurance": { + "@id": "https://schema.org/value" + }, + "insuranceClauses": { + "@id": "https://vocabulary.uncefact.org/contractualClause" + }, + "handlingInformation": { + "@id": "https://vocabulary.uncefact.org/handlingInstructions" + }, + "specialCustomsInformation": { + "@id": "https://vocabulary.uncefact.org/SpecifiedDeclaration" + }, + "consignmentRatingDetails": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "totalNumberOfPieces": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "totalGrossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "totalCharge": { + "@id": "https://schema.org/totalPrice" + }, + "otherCharges": { + "@id": "https://schema.org/price" + }, + "prepaidChargeDeclaration": { + "@id": "https://w3id.org/traceability#PrepaidChargeDeclaration" + }, + "prepaidTotal": { + "@id": "https://schema.org/totalPrice" + }, + "collectChargeDeclaration": { + "@id": "https://w3id.org/traceability#CollectChargeDeclaration" + }, + "destinationCollectChargeDeclaration": { + "@id": "https://w3id.org/traceability#DestinationCollectChargeDeclaration" + }, + "collectTotal": { + "@id": "https://schema.org/totalPrice" + }, + "shippersCertificationBox": { + "@id": "https://vocabulary.uncefact.org/CertificateTypeCodeList#2" + }, + "executedOn": { + "@id": "https://w3id.org/traceability#executionTime" + }, + "executedAt": { + "@id": "https://schema.org/Place" + } + } + }, + "ImporterSecurityFiling": { + "@id": "https://w3id.org/traceability#ImporterSecurityFiling", + "@context": { + "seller": { + "@id": "https://vocabulary.uncefact.org/sellerParty" + }, + "buyer": { + "@id": "https://vocabulary.uncefact.org/buyerParty" + }, + "importer": { + "@id": "https://vocabulary.uncefact.org/importerParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "shipToParty": { + "@id": "https://vocabulary.uncefact.org/shipToParty" + }, + "filingItems": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "containerStuffingLocation": { + "@id": "https://w3id.org/traceability#containerStuffingLocation" + }, + "consolidator": { + "@id": "https://vocabulary.uncefact.org/consolidatorParty" + } + } + }, + "Inbond": { + "@id": "https://w3id.org/traceability#Inbond", + "@context": { + "product": { + "@id": "https://www.gs1.org/voc/Product" + }, + "shipment": { + "@id": "https://schema.org/ParcelDelivery" + }, + "inBondNumber": { + "@id": "https://schema.org/identifier" + }, + "entryId": { + "@id": "https://schema.org/identifier" + }, + "ftzNo": { + "@id": "https://schema.org/identifier" + }, + "inBondType": { + "@id": "https://schema.org/identifier" + }, + "portOfEntry": { + "@id": "https://www.gs1.org/voc/Place" + }, + "portOfDestination": { + "@id": "https://www.gs1.org/voc/Place" + }, + "portOfArrival": { + "@id": "https://www.gs1.org/voc/Place" + }, + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "irsNumber": { + "@id": "https://schema.org/identifier" + }, + "recipient": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "billOfLadingNumber": { + "@id": "https://schema.org/identifier" + }, + "expectedDeliveryDate": { + "@id": "https://schema.org/DateTime" + }, + "valuePerItem": { + "@id": "https://schema.org/PriceSpecification" + }, + "totalOrderValue": { + "@id": "https://schema.org/PriceSpecification" + } + } + }, + "InspectionReport": { + "@id": "https://w3id.org/traceability#InspectionReport", + "@context": { + "comment": { + "@id": "https://schema.org/comment" + }, + "inspectors": { + "@id": "https://schema.org/Person" + }, + "place": { + "@id": "https://schema.org/Place" + }, + "chemicalObservation": { + "@id": "https://schema.org/ItemList" + }, + "mechanicalObservation": { + "@id": "https://schema.org/ItemList" + } + } + }, + "Inspector": { + "@id": "https://w3id.org/traceability#Inspector", + "@context": { + "person": { + "@id": "https://schema.org/Person" + }, + "qualification": { + "@id": "https://w3id.org/traceability#qualification" + } + } + }, + "Instructions": { + "@id": "https://vocabulary.uncefact.org/TransportInstructions", + "@context": { + "description": { + "@id": "https://schema.org/description" + } + } + }, + "IntellectualPropertyRights": { + "@id": "https://w3id.org/traceability#IntellectualPropertyRights", + "@context": { + "intellectualPropertyRightsOwner": { + "@id": "https://w3id.org/traceability#intellectualPropertyRightsOwner" + }, + "intellectualPropertyRightsType": { + "@id": "https://w3id.org/traceability#intellectualPropertyRightsType" + }, + "intellectualPropertyRightsProduct": { + "@id": "https://w3id.org/traceability#intellectualPropertyRightsProduct" + } + } + }, + "IntellectualPropertyRightsAffirmation": { + "@id": "https://w3id.org/traceability#IntellectualPropertyRightsAffirmation", + "@context": { + "affirmingParty": { + "@id": "https://w3id.org/traceability#affirmingParty" + }, + "intellectualPropertyRightsType": { + "@id": "https://w3id.org/traceability#intellectualPropertyRightsType" + }, + "evidenceDocumentUrl": { + "@id": "https://schema.org/url" + } + } + }, + "IntellectualPropertyRightsLicense": { + "@id": "https://w3id.org/traceability#IntellectualPropertyRightsLicense", + "@context": {} + }, + "IntentToImport": { + "@id": "https://w3id.org/traceability#IntentToImport", + "@context": { + "exporter": { + "@id": "https://vocabulary.uncefact.org/exporterParty" + }, + "importer": { + "@id": "https://vocabulary.uncefact.org/importerParty" + }, + "product": { + "@id": "https://www.gs1.org/voc/Product" + }, + "declarationDate": { + "@id": "https://schema.org/startDate" + } + } + }, + "Invoice": { + "@id": "https://schema.org/Invoice", + "@context": { + "identifier": { + "@id": "https://schema.org/identifier" + }, + "invoiceNumber": { + "@id": "https://vocabulary.uncefact.org/invoiceIssuerReference" + }, + "customerReferenceNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#CR" + }, + "referencesOrder": { + "@id": "https://schema.org/referencesOrder" + }, + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "letterOfCreditNumber": { + "@id": "https://vocabulary.uncefact.org/letterOfCreditDocument" + }, + "portOfEntry": { + "@id": "https://schema.org/Place" + }, + "originCountry": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "destinationCountry": { + "@id": "https://vocabulary.uncefact.org/destinationCountry" + }, + "invoiceDate": { + "@id": "https://vocabulary.uncefact.org/invoiceDateTime" + }, + "purchaseDate": { + "@id": "https://schema.org/paymentDueDate" + }, + "seller": { + "@id": "https://vocabulary.uncefact.org/sellerParty" + }, + "buyer": { + "@id": "https://vocabulary.uncefact.org/buyerParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "itemsShipped": { + "@id": "https://schema.org/itemShipped" + }, + "comments": { + "@id": "https://schema.org/Comment" + }, + "packageQuantity": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "totalWeight": { + "@id": "https://schema.org/weight" + }, + "termsOfDelivery": { + "@id": "https://vocabulary.uncefact.org/specifiedDeliveryTerms" + }, + "termsOfPayment": { + "@id": "https://vocabulary.uncefact.org/specifiedPaymentTerms" + }, + "termsOfSettlement": { + "@id": "https://schema.org/currency" + }, + "totalPaymentDue": { + "@id": "https://schema.org/totalPaymentDue" + }, + "discounts": { + "@id": "https://schema.org/discount" + }, + "deductions": { + "@id": "https://vocabulary.uncefact.org/deductionAmount" + }, + "tax": { + "@id": "https://vocabulary.uncefact.org/taxTotalAmount" + }, + "freightCost": { + "@id": "https://schema.org/DeliveryChargeSpecification" + }, + "insuranceCost": { + "@id": "https://vocabulary.uncefact.org/insuranceChargeTotalAmount" + } + } + }, + "LEIaddress": { + "@id": "https://w3id.org/traceability#LEIaddress", + "@context": { + "language": { + "@id": "https://schema.org/Language" + }, + "addressNumberWithinBuilding": { + "@id": "https://schema.org/value" + }, + "mailRouting": { + "@id": "https://schema.org/Trip" + }, + "city": { + "@id": "https://schema.org/addressLocality" + }, + "region": { + "@id": "https://schema.org/addressRegion" + }, + "country": { + "@id": "https://schema.org/addressCountry" + }, + "postalCode": { + "@id": "https://schema.org/postalCode" + } + } + }, + "LEIauthority": { + "@id": "https://w3id.org/traceability#LEIauthority", + "@context": { + "validationAuthorityID": { + "@id": "https://schema.org/identifier" + }, + "otherValidationAuthorityID": { + "@id": "https://schema.org/taxID" + }, + "validationAuthorityEntityID": { + "@id": "https://schema.org/leiCode" + } + } + }, + "LEIentity": { + "@id": "https://w3id.org/traceability#LEIentity", + "@context": { + "legalName": { + "@id": "https://schema.org/legalName" + }, + "legalNameLanguage": { + "@id": "https://schema.org/Language" + }, + "legalAddress": { + "@id": "https://w3id.org/traceability#LEIaddress" + }, + "headquartersAddress": { + "@id": "https://schema.org/PostalAddress" + }, + "registrationAuthority": { + "@id": "https://w3id.org/traceability#LEIauthority" + }, + "legalJurisdiction": { + "@id": "https://schema.org/countryOfOrigin" + }, + "entityCategory": { + "@id": "https://schema.org/category" + }, + "legalForm": { + "@id": "https://schema.org/additionalType" + }, + "associatedEntity": { + "@id": "https://schema.org/Organization" + }, + "status": { + "@id": "https://schema.org/status" + }, + "expirationDate": { + "@id": "https://schema.org/expires" + }, + "expirationReason": { + "@id": "https://schema.org/Answer" + }, + "successorEntity": { + "@id": "https://schema.org/Corporation" + }, + "otherAddresses": { + "@id": "https://schema.org/Place" + } + } + }, + "LEIevidenceDocument": { + "@id": "https://w3id.org/traceability#LEIevidenceDocument", + "@context": { + "lei": { + "@id": "https://www.gleif.org/en/about-lei/iso-17442-the-lei-code-structure#" + }, + "entity": { + "@id": "https://w3id.org/traceability#LEIentity" + }, + "registration": { + "@id": "https://w3id.org/traceability#LEIregistration" + } + } + }, + "LEIregistration": { + "@id": "https://w3id.org/traceability#LEIregistration", + "@context": { + "initialRegistrationDate": { + "@id": "https://schema.org/dateIssued" + }, + "lastUpdateDate": { + "@id": "https://schema.org/dateModified" + }, + "status": { + "@id": "https://schema.org/status" + }, + "nextRenewalDate": { + "@id": "https://schema.org/validThrough" + }, + "managingLou": { + "@id": "https://www.gleif.org/en/about-lei/iso-17442-the-lei-code-structure#" + }, + "validationSources": { + "@id": "https://schema.org/eventStatus" + }, + "validationAuthority": { + "@id": "https://w3id.org/traceability#LEIauthority" + } + } + }, + "LaceyActProductDeclaration": { + "@id": "https://w3id.org/traceability#LaceyActProductDeclaration", + "@context": { + "htsNumber": { + "@id": "https://vocabulary.uncefact.org/applicableRegulatoryProcedure" + }, + "enteredValue": { + "@id": "https://vocabulary.uncefact.org/customsValueSpecifiedAmount" + }, + "articleOrComponent": { + "@id": "https://vocabulary.uncefact.org/procedureCode" + }, + "plantScientificNames": { + "@id": "https://w3id.org/traceability#Taxonomy" + }, + "countryOfHarvest": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "quantityOfPlantMaterial": { + "@id": "https://vocabulary.uncefact.org/totalPackageSpecifiedQuantity" + }, + "percentRecycled": { + "@id": "https://qudt.org/vocab/unit/PERCENT" + } + } + }, + "LinkRole": { + "@id": "https://schema.org/LinkRole", + "@context": { + "target": { + "@id": "https://schema.org/target" + }, + "linkRelationship": { + "@id": "https://schema.org/linkRelationship" + } + } + }, + "MapResource": { + "@id": "https://w3id.org/traceability#MapResource", + "@context": { + "resourceType": { + "@id": "https://schema.org/additionalType" + }, + "external": { + "@id": "https://w3id.org/traceability#ExternalResource" + }, + "geoJson": { + "@id": "https://schema.org/geo" + } + } + }, + "MasterBillOfLading": { + "@id": "https://w3id.org/traceability#MasterBillOfLading", + "@context": { + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "bookingNumber": { + "@id": "https://vocabulary.uncefact.org/carrierAssignedId" + }, + "shippersReferences": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" + }, + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "forwardingAgent": { + "@id": "https://vocabulary.uncefact.org/freightForwarderParty" + }, + "notifyParty": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "preCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" + }, + "mainCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" + }, + "onCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" + }, + "placeOfReceipt": { + "@id": "https://schema.org/Place" + }, + "portOfLoading": { + "@id": "https://vocabulary.uncefact.org/transshipmentLocation" + }, + "placeOfDelivery": { + "@id": "https://schema.org/Place" + }, + "portOfDischarge": { + "@id": "https://vocabulary.uncefact.org/unloadingLocation" + }, + "totalNumberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "transportEquipmentQuantity": { + "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" + }, + "includedConsignmentItems": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "utilizedTransportEquipment": { + "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" + }, + "freightAndCharges": { + "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" + }, + "declaredValue": { + "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" + }, + "shippedOnBoardDate": { + "@id": "https://schema.org/Date" + }, + "termsAndConditions": { + "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" + } + } + }, + "MeasuredProperty": { + "@id": "https://w3id.org/traceability#MeasuredProperty", + "@context": {} + }, + "MeasuredValue": { + "@id": "https://schema.org/QuantitativeValue", + "@context": { + "value": { + "@id": "https://schema.org/value" + }, + "unitCode": { + "@id": "https://schema.org/unitCode" + } + } + }, + "MechanicalProperty": { + "@id": "https://w3id.org/traceability#MechanicalProperty", + "@context": { + "identifier": { + "@id": "https://schema.org/identifier" + }, + "name": { + "@id": "https://schema.org/name" + }, + "description": { + "@id": "https://schema.org/description" + } + } + }, + "MonetaryAmount": { + "@id": "https://schema.org/MonetaryAmount", + "@context": { + "value": { + "@id": "https://schema.org/value" + }, + "currency": { + "@id": "https://schema.org/currency" + } + } + }, + "MonthlyAdvanceManifest": { + "@id": "https://w3id.org/traceability#MonthlyAdvanceManifest", + "@context": { + "date": { + "@id": "https://schema.org/Date" + } + } + }, + "MonthlyDeliveryStatement": { + "@id": "https://w3id.org/traceability#MonthlyDeliveryStatement", + "@context": { + "itemsDelivered": { + "@id": "https://w3id.org/traceability#DeliveryStatement" + } + } + }, + "MultiModalBillOfLading": { + "@id": "https://w3id.org/traceability#MultiModalBillOfLading", + "@context": { + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "bookingNumber": { + "@id": "https://vocabulary.uncefact.org/carrierAssignedId" + }, + "shippersReferences": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#SI" + }, + "freightForwardersReferences": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "forwardingAgent": { + "@id": "https://vocabulary.uncefact.org/freightForwarderParty" + }, + "notifyParty": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "carrier": { + "@id": "https://vocabulary.uncefact.org/carrierParty" + }, + "preCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" + }, + "mainCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" + }, + "onCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" + }, + "placeOfReceipt": { + "@id": "https://schema.org/Place" + }, + "portOfLoading": { + "@id": "https://vocabulary.uncefact.org/loadingLocation" + }, + "transshipmentLocation": { + "@id": "https://vocabulary.uncefact.org/transshipmentLocation" + }, + "placeOfDelivery": { + "@id": "https://schema.org/Place" + }, + "portOfDischarge": { + "@id": "https://vocabulary.uncefact.org/unloadingLocation" + }, + "totalNumberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "transportEquipmentQuantity": { + "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" + }, + "particulars": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "utilizedTransportEquipment": { + "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" + }, + "freightAndCharges": { + "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" + }, + "declaredValue": { + "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" + }, + "shippedOnBoardDate": { + "@id": "https://schema.org/Date" + }, + "termsAndConditions": { + "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" + } + } + }, + "NAISMADateTime": { + "@id": "https://w3id.org/traceability#NAISMADateTime", + "@context": { + "collectionDate": { + "@id": "http://rs.tdwg.org/dwc/terms/eventDate" + }, + "dateAccuracyDays": { + "@id": "http://rs.tdwg.org/dwc/iri/measurementMethod" + } + } + }, + "NAISMAInfestation": { + "@id": "https://w3id.org/traceability#NAISMAInfestation", + "@context": { + "infestedArea": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "areaSurveyed": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "incidence": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "severity": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" + }, + "severityUnits": { + "@id": "https://schema.org/unitText" + }, + "organismQuantity": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "organismQuantityUnits": { + "@id": "https://schema.org/unitText" + } + } + }, + "NAISMAInformationSource": { + "@id": "https://w3id.org/traceability#NAISMAInformationSource", + "@context": { + "reference": { + "@id": "http://rs.tdwg.org/dwc/terms/associatedReferences" + }, + "examiner": { + "@id": "http://rs.tdwg.org/dwc/terms/recordedBy" + }, + "dataSource": { + "@id": "https://w3id.org/traceability#Entity" + } + } + }, + "NAISMALocation": { + "@id": "https://w3id.org/traceability#NAISMALocation", + "@context": { + "location": { + "@id": "https://w3id.org/traceability#Place" + }, + "description": { + "@id": "https://schema.org/description" + }, + "datum": { + "@id": "http://rs.tdwg.org/dwc/terms/geodeticDatum" + }, + "wellKnownText": { + "@id": "http://rs.tdwg.org/dwc/terms/footprintWKT" + }, + "centroidType": { + "@id": "https://schema.org/polygon" + }, + "dataType": { + "@id": "https://schema.org/additionalType" + }, + "coordinateUncertainty": { + "@id": "http://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters" + }, + "sourceOfLocation": { + "@id": "http://rs.tdwg.org/dwc/terms/georeferenceProtocol" + }, + "ecosystem": { + "@id": "http://rs.tdwg.org/dwc/terms/locationRemarks" + } + } + }, + "NAISMARecordLevelIdentifiers": { + "@id": "https://w3id.org/traceability#NAISMARecordLevelIdentifiers", + "@context": { + "uuid": { + "@id": "http://rs.tdwg.org/dwc/terms/resourceID" + }, + "pid": { + "@id": "https://schema.org/identifier" + }, + "catalogNumber": { + "@id": "http://rs.tdwg.org/dwc/terms/catalogNumber" + } + } + }, + "NAISMARecordStatus": { + "@id": "https://w3id.org/traceability#NAISMARecordStatus", + "@context": { + "occurrenceStatus": { + "@id": "https://schema.org/status" + }, + "populationStatus": { + "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" + }, + "managementStatus": { + "@id": "https://schema.org/status" + }, + "recordBasis": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" + }, + "recordType": { + "@id": "https://schema.org/description" + }, + "method": { + "@id": "http://rs.tdwg.org/dwc/terms/measurementMethod" + }, + "verificationMethod": { + "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" + } + } + }, + "NAISMASubject": { + "@id": "https://w3id.org/traceability#NAISMASubject", + "@context": { + "lifeStage": { + "@id": "http://rs.tdwg.org/dwc/terms/lifeStage" + }, + "sex": { + "@id": "http://rs.tdwg.org/dwc/terms/sex" + }, + "hostSpecies": { + "@id": "https://w3id.org/traceability#Taxonomy" + }, + "comments": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + } + } + }, + "NAISMATaxonomy": { + "@id": "https://w3id.org/traceability#NAISMATaxonomy", + "@context": { + "speciesName": { + "@id": "https://w3id.org/traceability#Taxonomy" + }, + "commonName": { + "@id": "http://rs.tdwg.org/dwc/terms/vernacularName" + }, + "taxonomicSerialNumber": { + "@id": "http://rs.tdwg.org/dwc/terms/taxonID" + } + } + }, + "Observation": { + "@id": "https://schema.org/Observation", + "@context": { + "property": { + "@id": "https://schema.org/measuredProperty" + }, + "measurement": { + "@id": "https://w3id.org/traceability#MeasuredValue" + }, + "date": { + "@id": "https://schema.org/observationDate" + } + } + }, + "OilAndGasDeliveryTicket": { + "@id": "https://w3id.org/traceability#OilAndGasDeliveryTicket", + "@context": { + "createdDate": { + "@id": "https://schema.org/dateIssued" + }, + "openDate": { + "@id": "https://schema.org/startDate" + }, + "closeDate": { + "@id": "https://schema.org/endDate" + }, + "transporter": { + "@id": "https://schema.org/agent" + }, + "consignor": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "ticketControlNumber": { + "@id": "https://schema.org/ticketNumber" + }, + "batchNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BT" + }, + "place": { + "@id": "https://schema.org/toLocation" + }, + "product": { + "@id": "https://www.gs1.org/voc/Product" + }, + "observation": { + "@id": "https://w3id.org/traceability#observation" + } + } + }, + "OilAndGasProduct": { + "@id": "https://w3id.org/traceability#OilAndGasProduct", + "@context": { + "product": { + "@id": "https://www.gs1.org/voc/Product" + }, + "facility": { + "@id": "https://www.gs1.org/voc/Place" + }, + "UWI": { + "@id": "https://schema.org/identifier" + }, + "productionDate": { + "@id": "https://schema.org/DateTime" + }, + "observation": { + "@id": "https://w3id.org/traceability#observation" + } + } + }, + "Order": { + "@id": "https://schema.org/Order", + "@context": { + "orderNumber": { + "@id": "https://schema.org/orderNumber" + }, + "orderedItems": { + "@id": "https://schema.org/orderedItem" + } + } + }, + "OrderItem": { + "@id": "https://schema.org/OrderItem", + "@context": { + "marketplace": { + "@id": "https://vocabulary.uncefact.org/Marketplace" + }, + "fulfillmentCenter": { + "@id": "https://vocabulary.uncefact.org/logisticsServiceProviderParty" + }, + "orderedItem": { + "@id": "https://schema.org/orderedItem" + }, + "orderedQuantity": { + "@id": "https://schema.org/orderQuantity" + } + } + }, + "OrganicCertification": { + "@id": "https://w3id.org/traceability#OrganicCertification", + "@context": { + "countryOfIssuance": { + "@id": "https://www.gs1.org/voc/countryCode" + }, + "certifiedOperation": { + "@id": "https://www.gs1.org/voc/certificationSubject" + }, + "certifyingAgent": { + "@id": "https://www.gs1.org/voc/certificationAgency" + }, + "effectiveDate": { + "@id": "https://www.gs1.org/voc/certificationStartDate" + }, + "issueDate": { + "@id": "https://www.gs1.org/voc/initialCertificationDate" + }, + "anniversaryDate": { + "@id": "https://www.gs1.org/voc/certificationEndDate" + }, + "operationCategory": { + "@id": "https://www.gs1.org/voc/certificationStatement" + }, + "organicProducts": { + "@id": "https://www.gs1.org/voc/certificationStatement" + } + } + }, + "OrganicInspection": { + "@id": "https://w3id.org/traceability#OrganicInspection", + "@context": { + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "applicantCertificationNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "authorizedOperationContacts": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "peoplePresent": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "newApplicant": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "continuingCertification": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "newLocationActivity": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "reinstatement": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "announcedInspection": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "estimatedHarvestDate": { + "@id": "https://www.gs1.org/voc/harvestDate" + }, + "pesticideResidueSampling": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "samplingDetails": { + "@id": "https://vocabulary.uncefact.org/content" + }, + "introductionOperationDescription": { + "@id": "https://schema.org/description" + }, + "resolutionIssuesActionItems": { + "@id": "https://schema.org/description" + }, + "issuesRequests": { + "@id": "https://vocabulary.uncefact.org/additionalDescription" + }, + "attachments": { + "@id": "https://vocabulary.uncefact.org/additionalDocument" + }, + "OSPSectionReviews": { + "@id": "https://w3id.org/traceability#OrganicOSPSectionReview" + } + } + }, + "OrganicOSPSectionReview": { + "@id": "https://w3id.org/traceability#OrganicOSPSectionReview", + "@context": { + "OSPSectionCode": { + "@id": "https://vocabulary.uncefact.org/standard" + }, + "resultCode": { + "@id": "https://vocabulary.uncefact.org/assertionCode" + }, + "verificationExplanations": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "attachments": { + "@id": "https://vocabulary.uncefact.org/additionalDocument" + } + } + }, + "OrganicProductCertification": { + "@id": "https://w3id.org/traceability#OrganicProductCertification", + "@context": { + "agricultureProduct": { + "@id": "https://www.gs1.org/voc/certificationSubject" + }, + "organicCertification": { + "@id": "https://www.gs1.org/voc/certification" + }, + "isCertified": { + "@id": "https://www.gs1.org/voc/certificationStatus" + } + } + }, + "OrganicReview": { + "@id": "https://w3id.org/traceability#OrganicReview", + "@context": { + "inspectionReport": { + "@id": "https://w3id.org/traceability#OrganicInspection" + }, + "reviewer": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "decisionMaker": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "certificationDecision": { + "@id": "https://www.gs1.org/voc/certificationStatus" + }, + "additionalInformation": { + "@id": "https://vocabulary.uncefact.org/content" + } + } + }, + "Organization": { + "@id": "https://schema.org/Organization", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "legalName": { + "@id": "https://schema.org/legalName" + }, + "leiCode": { + "@id": "https://schema.org/leiCode" + }, + "url": { + "@id": "https://schema.org/url" + }, + "description": { + "@id": "https://schema.org/description" + }, + "globalLocationNumber": { + "@id": "https://schema.org/globalLocationNumber" + }, + "location": { + "@id": "https://schema.org/location" + }, + "email": { + "@id": "https://schema.org/email" + }, + "phoneNumber": { + "@id": "https://schema.org/telephone" + }, + "logo": { + "@id": "https://schema.org/logo" + }, + "faxNumber": { + "@id": "https://schema.org/faxNumber" + }, + "contactPoint": { + "@id": "https://schema.org/ContactPoint" + }, + "taxId": { + "@id": "https://schema.org/taxID" + }, + "iataCarrierCode": { + "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" + }, + "scac": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" + } + } + }, + "PGAShipmentStatus": { + "@id": "https://w3id.org/traceability#PGAShipmentStatus", + "@context": { + "recordNo": { + "@id": "https://w3id.org/traceability#recordNo" + }, + "entryNo": { + "@id": "https://w3id.org/traceability#entryNo" + }, + "entryLineSequence": { + "@id": "https://w3id.org/traceability#entryLineSequence" + }, + "statusCode": { + "@id": "https://w3id.org/traceability#statusCode" + }, + "statusCodeDescription": { + "@id": "https://w3id.org/traceability#statusCodeDescription" + }, + "validCodeReason": { + "@id": "https://w3id.org/traceability#validCodeReason" + }, + "validCodeReasonDescription": { + "@id": "https://w3id.org/traceability#validCodeReasonDescription" + }, + "subReasonCode": { + "@id": "https://w3id.org/traceability#subReasonCode" + }, + "subReasonCodeDescription": { + "@id": "https://w3id.org/traceability#subReasonCodeDescription" + } + } + }, + "PGAShipmentStatusList": { + "@id": "https://w3id.org/traceability#PGAShipmentStatusList", + "@context": { + "pgaShipmentStatusItems": { + "@id": "https://schema.org/ItemList" + } + } + }, + "Package": { + "@id": "https://vocabulary.uncefact.org/Package", + "@context": { + "physicalShippingMarks": { + "@id": "https://vocabulary.uncefact.org/physicalShippingMarks" + }, + "packagingType": { + "@id": "https://www.gs1.org/voc/packagingMaterial" + }, + "perPackageUnitQuantity": { + "@id": "https://vocabulary.uncefact.org/perPackageUnitQuantity" + }, + "includedTradeLineItems": { + "@id": "https://vocabulary.uncefact.org/specifiedTradeLineItem" + }, + "netWeight": { + "@id": "https://vocabulary.uncefact.org/netWeightMeasure" + }, + "grossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "height": { + "@id": "https://schema.org/height" + }, + "width": { + "@id": "https://schema.org/width" + }, + "depth": { + "@id": "https://schema.org/depth" + }, + "grossVolume": { + "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" + } + } + }, + "PackingList": { + "@id": "https://w3id.org/traceability#PackingList", + "@context": { + "seller": { + "@id": "https://vocabulary.uncefact.org/sellerParty" + }, + "buyer": { + "@id": "https://vocabulary.uncefact.org/buyerParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "shipFromParty": { + "@id": "https://vocabulary.uncefact.org/shipFromParty" + }, + "shipToParty": { + "@id": "https://vocabulary.uncefact.org/shipToParty" + }, + "orderNumber": { + "@id": "https://schema.org/orderNumber" + }, + "invoiceId": { + "@id": "https://schema.org/identifier" + }, + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "trackingNumber": { + "@id": "https://schema.org/trackingNumber" + }, + "deliveryStatus": { + "@id": "https://schema.org/deliveryStatus" + }, + "estimatedTimeOfArrival": { + "@id": "https://schema.org/arrivalTime" + }, + "hasDeliveryMethod": { + "@id": "https://schema.org/hasDeliveryMethod" + }, + "handlingInstructions": { + "@id": "https://vocabulary.uncefact.org/handlingInstructions" + }, + "items": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "totalNetWeight": { + "@id": "https://vocabulary.uncefact.org/netWeightMeasure" + }, + "totalGrossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "totalGrossVolume": { + "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" + }, + "totalNumberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "totalItemQuantity": { + "@id": "https://vocabulary.uncefact.org/tradeLineItemQuantity" + } + } + }, + "ParcelDelivery": { + "@id": "https://schema.org/ParcelDelivery", + "@context": { + "deliveryAddress": { + "@id": "https://schema.org/deliveryAddress" + }, + "originAddress": { + "@id": "https://schema.org/originAddress" + }, + "deliveryMethod": { + "@id": "https://schema.org/DeliveryMethod" + }, + "trackingNumber": { + "@id": "https://schema.org/trackingNumber" + }, + "expectedArrival": { + "@id": "https://schema.org/expectedArrivalFrom" + }, + "specialInstructions": { + "@id": "https://schema.org/comment" + }, + "consignee": { + "@id": "https://schema.org/Organization" + }, + "item": { + "@id": "https://schema.org/itemShipped" + }, + "partOfOrder": { + "@id": "https://schema.org/partOfOrder" + } + } + }, + "PartOfOrder": { + "@id": "https://schema.org/OrderItem", + "@context": { + "manufacturer": { + "@id": "https://schema.org/Organization" + }, + "orderNumber": { + "@id": "https://schema.org/orderNumber" + }, + "transportPackages": { + "@id": "https://vocabulary.uncefact.org/Package" + }, + "netWeight": { + "@id": "https://vocabulary.uncefact.org/netWeightMeasure" + }, + "grossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "grossVolume": { + "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" + }, + "packageQuantity": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "itemQuantity": { + "@id": "https://vocabulary.uncefact.org/tradeLineItemQuantity" + } + } + }, + "Person": { + "@id": "https://schema.org/Person", + "@context": { + "firstName": { + "@id": "https://schema.org/givenName" + }, + "lastName": { + "@id": "https://schema.org/familyName" + }, + "email": { + "@id": "https://schema.org/email" + }, + "phoneNumber": { + "@id": "https://schema.org/telephone" + }, + "worksFor": { + "@id": "https://schema.org/worksFor" + }, + "jobTitle": { + "@id": "https://schema.org/jobTitle" + }, + "taxId": { + "@id": "https://schema.org/taxID" + } + } + }, + "PestDetermination": { + "@id": "https://w3id.org/traceability#PestDetermination", + "@context": { + "final": { + "@id": "https://dwc.tdwg.org/list/#dwc_identificationVerificationStatus" + }, + "determination": { + "@id": "https://w3id.org/traceability#Taxonomy" + }, + "notes": { + "@id": "https://dwc.tdwg.org/list/#dwc_identificationRemarks" + }, + "method": { + "@id": "https://dwc.tdwg.org/list/#dwc_measurementMethod" + }, + "reportable": { + "@id": "https://dwc.tdwg.org/list/#dwc_occurrenceStatus" + }, + "determinedBy": { + "@id": "https://dwc.tdwg.org/list/#dwc_identifiedBy" + }, + "date": { + "@id": "https://dwc.tdwg.org/list/#dwc_dateIdentified" + } + } + }, + "PestSample": { + "@id": "https://w3id.org/traceability#PestSample", + "@context": { + "hostName": { + "@id": "https://w3id.org/traceability#Taxonomy" + }, + "hostQuantity": { + "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" + }, + "affected": { + "@id": "https://dwc.tdwg.org/list/#dwc_measurementValue" + }, + "plantDistribution": { + "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" + }, + "plantPartsAffected": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + }, + "pestDistribution": { + "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" + }, + "pestProximity": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + }, + "pestType": { + "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" + }, + "aliveLarvae": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "alivePupae": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "aliveAdults": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "aliveEggs": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "aliveNymphs": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "aliveJuveniles": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "aliveCysts": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadLarvae": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadPupae": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadAdults": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadEggs": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadNymphs": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadJuveniles": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "deadCysts": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "castSkins": { + "@id": "http://rs.tdwg.org/dwc/terms/individualCount" + }, + "samplingMethod": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" + }, + "trapLureType": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" + }, + "trapNumber": { + "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" + } + } + }, + "Phytosanitary": { + "@id": "https://w3id.org/traceability/Phytosanitary", + "@context": { + "certificateNumber": { + "@id": "https://schema.org/identifier" + }, + "plantOrg": { + "@id": "https://www.gs1.org/voc/Organization" + }, + "distinguishingMarks": { + "@id": "https://www.gs1.org/voc/variantDescription" + }, + "portOfEntry": { + "@id": "https://w3id.org/traceability#portOfEntry" + }, + "additionalDeclaration": { + "@id": "https://schema.org/Comment" + }, + "disinfectionDate": { + "@id": "https://schema.org/validFrom" + }, + "disinfectionTreatment": { + "@id": "https://w3id.org/traceability#disinfectionTreatment" + }, + "disinfectionChemical": { + "@id": "https://schema.org/activeIngredient" + }, + "disinfectionDuration": { + "@id": "https://schema.org/duration" + }, + "disinfectionTemperature": { + "@id": "https://schema.org/MeasuredValue" + }, + "disinfectionConcentration": { + "@id": "https://w3id.org/traceability#disinfectionConcentration" + }, + "signatureDate": { + "@id": "https://schema.org/DateTime" + }, + "facility": { + "@id": "https://www.gs1.org/voc/Place" + }, + "inspector": { + "@id": "https://w3id.org/traceability#Inspector" + }, + "shipment": { + "@id": "https://schema.org/AgricultureParcelDelivery" + }, + "agriculturePackage": { + "@id": "https://w3id.org/traceability#AgriculturePackage" + }, + "applicant": { + "@id": "https://w3c-ccg.github.io/traceability-vocab/#dfn-entities" + }, + "inspectionDate": { + "@id": "https://schema.org/DateTime" + }, + "inspectionType": { + "@id": "https://vocabulary.uncefact.org/inspectionStandard" + }, + "notes": { + "@id": "https://schema.org/Comment" + }, + "observation": { + "@id": "https://schema.org/ItemList" + } + } + }, + "Place": { + "@id": "https://schema.org/Place", + "@context": { + "globalLocationNumber": { + "@id": "https://schema.org/globalLocationNumber" + }, + "geo": { + "@id": "https://schema.org/GeoCoordinates" + }, + "address": { + "@id": "https://schema.org/PostalAddress" + }, + "unLocode": { + "@id": "https://vocabulary.uncefact.org/Location" + }, + "iataAirportCode": { + "@id": "https://onerecord.iata.org/cargo/Location#code" + }, + "locationName": { + "@id": "https://schema.org/name" + }, + "usPortCode": { + "@id": "https://w3id.org/traceability#usPortCode" + }, + "firmsCode": { + "@id": "https://w3id.org/traceability#firmsCode" + } + } + }, + "PlantSystemsInspection": { + "@id": "https://w3id.org/traceability#PlantSystemsInspection", + "@context": { + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "productsPacked": { + "@id": "https://vocabulary.uncefact.org/specifiedProduct" + }, + "summaryOfDeficiencies": { + "@id": "https://schema.org/description" + }, + "observationsImprovements": { + "@id": "https://schema.org/description" + }, + "questions": { + "@id": "https://w3id.org/traceability#PlantSystemsQuestion" + }, + "additionalViolations": { + "@id": "https://schema.org/description" + } + } + }, + "PlantSystemsQuestion": { + "@id": "https://w3id.org/traceability#PlantSystemsQuestion", + "@context": { + "code": { + "@id": "https://schema.org/identifier" + }, + "pointsWorth": { + "@id": "https://schema.org/ratingValue" + }, + "pointsDeducted": { + "@id": "https://schema.org/ratingValue" + } + } + }, + "PostalAddress": { + "@id": "https://schema.org/PostalAddress", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "streetAddress": { + "@id": "https://schema.org/streetAddress" + }, + "addressLocality": { + "@id": "https://schema.org/addressLocality" + }, + "addressRegion": { + "@id": "https://schema.org/addressRegion" + }, + "addressCountry": { + "@id": "https://schema.org/addressCountry" + }, + "crossStreet": { + "@id": "https://gs1.org/voc/crossStreet" + }, + "countyCode": { + "@id": "https://gs1.org/voc/countyCode" + }, + "postalCode": { + "@id": "https://schema.org/postalCode" + }, + "postOfficeBoxNumber": { + "@id": "https://schema.org/postOfficeBoxNumber" + }, + "plantOrSiteName": { + "@id": "https://vocabulary.uncefact.org/buildingName" + } + } + }, + "PostmanCollection": { + "@id": "https://w3id.org/traceability#PostmanCollection", + "@context": {} + }, + "PriceSpecification": { + "@id": "https://schema.org/PriceSpecification", + "@context": { + "price": { + "@id": "https://schema.org/price" + }, + "priceCurrency": { + "@id": "https://schema.org/priceCurrency" + } + } + }, + "Product": { + "@id": "https://schema.org/Product", + "@context": { + "gtin": { + "@id": "https://schema.org/gtin" + }, + "manufacturer": { + "@id": "https://schema.org/manufacturer" + }, + "countryOfOrigin": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "name": { + "@id": "https://schema.org/name" + }, + "description": { + "@id": "https://schema.org/description" + }, + "category": { + "@id": "https://schema.org/category" + }, + "sizeOrAmount": { + "@id": "https://schema.org/size" + }, + "weight": { + "@id": "https://schema.org/weight" + }, + "depth": { + "@id": "https://schema.org/depth" + }, + "width": { + "@id": "https://schema.org/width" + }, + "height": { + "@id": "https://schema.org/height" + }, + "productPrice": { + "@id": "https://schema.org/priceSpecification" + }, + "sku": { + "@id": "https://schema.org/sku" + }, + "batchNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BT" + }, + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "seller": { + "@id": "https://vocabulary.uncefact.org/sellerParty" + }, + "images": { + "@id": "https://schema.org/image" + }, + "imageUrl": { + "@id": "https://schema.org/url" + }, + "imageHash": { + "@id": "https://schema.org/sha256" + }, + "htsCode": { + "@id": "https://service.unece.org/trade/uncefact/vocabulary/uncefact/#applicableTax" + } + } + }, + "Purchase": { + "@id": "https://w3id.org/traceability#Purchase", + "@context": { + "customer": { + "@id": "https://w3id.org/traceability#Entity" + }, + "invoice": { + "@id": "https://w3id.org/traceability#Invoice" + }, + "invoiceNo": { + "@id": "https://schema.org/identifier" + }, + "internalCertificateNo": { + "@id": "https://schema.org/identifier" + }, + "purchaseOrderNo": { + "@id": "https://schema.org/identifier" + } + } + }, + "PurchaseOrder": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#105", + "@context": { + "purchaseOrderNo": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AUJ" + }, + "orderDate": { + "@id": "https://vocabulary.uncefact.org/buyerOrderDateTime" + }, + "buyer": { + "@id": "https://vocabulary.uncefact.org/buyerParty" + }, + "seller": { + "@id": "https://vocabulary.uncefact.org/sellerParty" + }, + "shipToParty": { + "@id": "https://vocabulary.uncefact.org/shipToParty" + }, + "itemsOrdered": { + "@id": "https://vocabulary.uncefact.org/SupplyChainTradeLineItem" + }, + "comments": { + "@id": "https://schema.org/Comment" + }, + "totalWeight": { + "@id": "https://schema.org/weight" + }, + "termsOfDelivery": { + "@id": "https://vocabulary.uncefact.org/specifiedDeliveryTerms" + }, + "termsOfPayment": { + "@id": "https://vocabulary.uncefact.org/specifiedPaymentTerms" + }, + "totalPaymentDue": { + "@id": "https://schema.org/totalPaymentDue" + }, + "discounts": { + "@id": "https://vocabulary.uncefact.org/deductionAmount" + }, + "tax": { + "@id": "https://vocabulary.uncefact.org/taxTotalAmount" + }, + "freightCost": { + "@id": "https://schema.org/DeliveryChargeSpecification" + }, + "insuranceCost": { + "@id": "https://vocabulary.uncefact.org/insuranceChargeTotalAmount" + }, + "totalOrderAmount": { + "@id": "https://vocabulary.uncefact.org/grandTotalAmount" + } + } + }, + "Qualification": { + "@id": "https://schema.org/qualifications", + "@context": { + "qualificationCategory": { + "@id": "https://schema.org/credentialCategory" + }, + "qualificationValue": { + "@id": "https://schema.org/hasCredential" + } + } + }, + "QuantitativeValue": { + "@id": "https://schema.org/QuantitativeValue", + "@context": { + "unitCode": { + "@id": "https://schema.org/unitCode" + }, + "value": { + "@id": "https://schema.org/value" + } + } + }, + "RawMaterial": { + "@id": "https://w3id.org/traceability#RawMaterial", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "inchiKey": { + "@id": "https://w3id.org/traceability#inchiKey" + } + } + }, + "RevocationList2020Status": { + "@id": "https://w3id.org/traceability#RevocationList2020Status", + "@context": { + "revocationListIndex": { + "@id": "https://schema.org/itemListElement" + }, + "revocationListCredential": { + "@id": "https://schema.org/LinkRole" + } + } + }, + "RoutingInfo": { + "@id": "https://w3id.org/traceability#RoutingInfo", + "@context": { + "code": { + "@id": "https://w3id.org/traceability#routingInfoCode" + }, + "value": { + "@id": "https://w3id.org/traceability#routingInfoValue" + } + } + }, + "SIMASteelImportLicense": { + "@id": "https://w3id.org/traceability#SIMASteelImportLicense", + "@context": { + "licenseNumber": { + "@id": "https://schema.org/identifier" + }, + "licensedCompany": { + "@id": "https://vocabulary.uncefact.org/grantedParty" + }, + "customsEntryNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" + }, + "importer": { + "@id": "https://vocabulary.uncefact.org/importerParty" + }, + "exporter": { + "@id": "https://vocabulary.uncefact.org/exporterParty" + }, + "manufacturer": { + "@id": "https://vocabulary.uncefact.org/manufacturerParty" + }, + "countryOfOrigin": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "countryOfExportation": { + "@id": "https://vocabulary.uncefact.org/exportCountry" + }, + "expectedPortOfEntry": { + "@id": "https://vocabulary.uncefact.org/LocationFunctionCodeList#24" + }, + "expectedDateOfExport": { + "@id": "https://vocabulary.uncefact.org/DateTimePeriodFunctionCodeList#129" + }, + "expectedDateOfImport": { + "@id": "https://vocabulary.uncefact.org/DateTimePeriodFunctionCodeList#151" + }, + "productInformation": { + "@id": "https://w3id.org/traceability#productInformation" + } + } + }, + "SIMASteelImportProductSpecifier": { + "@id": "https://w3id.org/traceability#SIMASteelImportProductSpecifier", + "@context": { + "productCategory": { + "@id": "https://w3id.org/traceability#ProductCategory" + }, + "countryOfMeltAndPour": { + "@id": "https://w3id.org/traceability#countryOfMeltAndPour" + }, + "customsValue": { + "@id": "https://vocabulary.uncefact.org/declaredValueForCustomsAmount" + } + } + }, + "OssfScorecard": { + "@id": "https://w3id.org/traceability#OssfScorecard", + "@context": {} + }, + "SeaCargoManifest": { + "@id": "https://w3id.org/traceability#SeaCargoManifest", + "@context": { + "vesselName": { + "@id": "https://vocabulary.uncefact.org/transportMeans" + }, + "vesselNumber": { + "@id": "https://schema.org/identifier" + }, + "voyageNumber": { + "@id": "https://vocabulary.uncefact.org/TransportMovement" + }, + "registrationCountry": { + "@id": "https://vocabulary.uncefact.org/registrationCountry" + }, + "plannedDepartureDateTime": { + "@id": "https://schema.org/Date" + }, + "plannedArrivalDateTime": { + "@id": "https://schema.org/DateTime" + }, + "portOfDeparture": { + "@id": "https://schema.org/Place" + }, + "portOfArrival": { + "@id": "https://schema.org/Place" + }, + "netTonnage": { + "@id": "https://vocabulary.uncefact.org/netWeightMeasure" + }, + "grossTonnage": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "totalNumberOfTransportDocuments": { + "@id": "https://schema.org/Number" + }, + "transportEquipmentQuantity": { + "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" + }, + "totalNumberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "transportDocumentInformation": { + "@id": "https://vocabulary.uncefact.org/transportContractDocument" + } + } + }, + "Seal": { + "@id": "https://vocabulary.uncefact.org/Seal", + "@context": { + "sealNumber": { + "@id": "https://vocabulary.uncefact.org/identifier" + }, + "sealSource": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/sealSource" + }, + "sealType": { + "@id": "https://vocabulary.uncefact.org/logisticsSealTypeCode" + } + } + }, + "ServiceCharge": { + "@id": "https://vocabulary.uncefact.org/ServiceCharge", + "@context": { + "chargeCode": { + "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" + }, + "paymentTerm": { + "@id": "https://vocabulary.uncefact.org/PaymentTerms" + }, + "chargeText": { + "@id": "https://schema.org/description" + }, + "rate": { + "@id": "https://vocabulary.uncefact.org/unitPrice" + }, + "calculationBasis": { + "@id": "https://vocabulary.uncefact.org/calculationBasis" + }, + "appliedAmount": { + "@id": "https://vocabulary.uncefact.org/appliedAmount" + } + } + }, + "ShippingDetails": { + "@id": "https://w3id.org/traceability#ShippingDetails", + "@context": { + "containerNumber": { + "@id": "https://w3id.org/traceability#containerNumber" + }, + "masterBillOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/uncl1153#MB" + }, + "manufacturerAddress": { + "@id": "https://w3id.org/traceability#manufacturerAddress" + }, + "customerAddress": { + "@id": "https://w3id.org/traceability#customerAddress" + } + } + }, + "ShippingInstructions": { + "@id": "https://w3id.org/traceability#ShippingInstructions", + "@context": { + "billOfLadingNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" + }, + "bookingNumber": { + "@id": "https://vocabulary.uncefact.org/carrierAssignedId" + }, + "shippersReferences": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" + }, + "shipper": { + "@id": "https://vocabulary.uncefact.org/consignorParty" + }, + "consignee": { + "@id": "https://vocabulary.uncefact.org/consigneeParty" + }, + "notifyParty": { + "@id": "https://vocabulary.uncefact.org/notifiedParty" + }, + "preCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" + }, + "mainCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" + }, + "onCarriageTransportMovement": { + "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" + }, + "placeOfReceipt": { + "@id": "https://schema.org/Place" + }, + "portOfLoading": { + "@id": "https://vocabulary.uncefact.org/transshipmentLocation" + }, + "placeOfDelivery": { + "@id": "https://schema.org/Place" + }, + "portOfDischarge": { + "@id": "https://vocabulary.uncefact.org/unloadingLocation" + }, + "totalNumberOfPackages": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "transportEquipmentQuantity": { + "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" + }, + "includedConsignmentItems": { + "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" + }, + "utilizedTransportEquipment": { + "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" + }, + "declaredValue": { + "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" + } + } + }, + "SoftwareBillOfMaterials": { + "@id": "https://w3id.org/traceability#SoftwareBillOfMaterials", + "@context": {} + }, + "SteelProduct": { + "@id": "https://w3id.org/traceability#SteelProduct", + "@context": { + "heatNumber": { + "@id": "https://schema.org/identifier" + }, + "specification": { + "@id": "https://schema.org/identifier" + }, + "grade": { + "@id": "https://schema.org/Rating" + }, + "weight": { + "@id": "https://schema.org/weight" + }, + "weightUnit": { + "@id": "http://qudt.org/schema/qudt/Unit" + }, + "originalCountryOfMeltAndPour": { + "@id": "https://schema.org/addressCountry" + }, + "commodity": { + "@id": "https://w3id.org/traceability#Commodity" + }, + "inspection": { + "@id": "https://w3id.org/traceability#Inspection" + } + } + }, + "Taxonomy": { + "@id": "https://w3id.org/traceability#Taxonomy", + "@context": { + "kingdom": { + "@id": "http://rs.tdwg.org/dwc/terms/kingdom" + }, + "phylum": { + "@id": "http://rs.tdwg.org/dwc/terms/phylum" + }, + "class": { + "@id": "http://rs.tdwg.org/dwc/terms/class" + }, + "order": { + "@id": "http://rs.tdwg.org/dwc/terms/order" + }, + "family": { + "@id": "http://rs.tdwg.org/dwc/terms/family" + }, + "genus": { + "@id": "http://rs.tdwg.org/dwc/terms/genus" + }, + "species": { + "@id": "http://rs.tdwg.org/dwc/terms/specificEpithet" + }, + "subspecies": { + "@id": "http://rs.tdwg.org/dwc/terms/infraspecificEpithet" + }, + "variety": { + "@id": "http://rs.tdwg.org/dwc/terms/cultivarEpithet" + } + } + }, + "TemperatureReading": { + "@id": "https://w3id.org/traceability#TemperatureReading", + "@context": { + "bulbNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "tests": { + "@id": "https://vocabulary.uncefact.org/actualMeasure" + } + } + }, + "Template": { + "@id": "https://w3id.org/traceability#Template", + "@context": { + "image": { + "@id": "https://schema.org/image" + } + } + }, + "Thing": { + "@id": "https://schema.org/Thing", + "@context": {} + }, + "TraceabilityAPI": { + "@id": "https://w3id.org/traceability#TraceabilityAPI", + "@context": {} + }, + "TradeLineItem": { + "@id": "https://vocabulary.uncefact.org/SupplyChainTradeLineItem", + "@context": { + "name": { + "@id": "https://schema.org/name" + }, + "purchaseOrderNumber": { + "@id": "https://schema.org/orderNumber" + }, + "itemCount": { + "@id": "https://vocabulary.uncefact.org/despatchedQuantity" + }, + "description": { + "@id": "https://schema.org/description" + }, + "packageQuantity": { + "@id": "https://vocabulary.uncefact.org/packageQuantity" + }, + "product": { + "@id": "https://schema.org/Product" + }, + "countryOfOrigin": { + "@id": "https://vocabulary.uncefact.org/originCountry" + }, + "shipToParty": { + "@id": "https://vocabulary.uncefact.org/shipToParty" + }, + "netWeight": { + "@id": "https://vocabulary.uncefact.org/netWeightMeasure" + }, + "grossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "priceSpecification": { + "@id": "https://schema.org/priceSpecification" + } + } + }, + "TransferEvent": { + "@id": "https://w3id.org/traceability#TransferEvent", + "@context": { + "place": { + "@id": "https://schema.org/Place" + }, + "price": { + "@id": "https://schema.org/price" + }, + "products": { + "@id": "https://schema.org/Product" + }, + "organization": { + "@id": "https://w3id.org/traceability#Organization" + }, + "identifier": { + "@id": "https://schema.org/identifier" + }, + "addressCountry": { + "@id": "https://schema.org/addressCountry" + } + } + }, + "TransformEvent": { + "@id": "https://w3id.org/traceability#TransformEvent", + "@context": { + "place": { + "@id": "https://schema.org/Place" + }, + "organization": { + "@id": "https://w3id.org/traceability#Organization" + }, + "newProducts": { + "@id": "https://w3c-ccg.github.io/hashlink/#hl-url-params" + }, + "consumedProducts": { + "@id": "https://w3c-ccg.github.io/hashlink/#hl-url-params" + } + } + }, + "Transport": { + "@id": "https://w3id.org/traceability#Transport", + "@context": { + "arrivalLocation": { + "@id": "https://schema.org/toLocation" + }, + "departureDate": { + "@id": "https://schema.org/departureTime" + }, + "arrivalDate": { + "@id": "https://schema.org/arrivalTime" + }, + "modeOfTransport": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/modeOfTransport" + }, + "carrier": { + "@id": "https://schema.org/carrier" + }, + "vesselNumber": { + "@id": "https://vocabulary.uncefact.org/identifier" + }, + "voyageNumber": { + "@id": "https://vocabulary.uncefact.org/identifier" + }, + "path": { + "@id": "https://schema.org/line" + } + } + }, + "TransportDocument": { + "@id": "https://w3id.org/traceability#TransportDocument", + "@context": {} + }, + "TransportEquipment": { + "@id": "https://vocabulary.uncefact.org/LogisticsTransportEquipment", + "@context": { + "equipmentReference": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "ISOEquipmentCode": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/ISOEquipmentCode" + }, + "tareWeight": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/tareWeight" + }, + "tareWeightUnit": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/weightUnit" + }, + "cargoGrossWeight": { + "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" + }, + "cargoGrossWeightUnit": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/weightUnit" + }, + "isShipperOwned": { + "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/isShipperOwned" + }, + "seals": { + "@id": "https://vocabulary.uncefact.org/affixedSeal" + } + } + }, + "TransportEvent": { + "@id": "https://w3id.org/traceability#TransportEvent", + "@context": { + "place": { + "@id": "https://schema.org/Place" + }, + "organization": { + "@id": "https://w3id.org/traceability#Organization" + }, + "products": { + "@id": "https://schema.org/Product" + }, + "deliveryMethod": { + "@id": "https://schema.org/DeliveryMethod" + }, + "trackingNumber": { + "@id": "https://schema.org/trackingNumber" + } + } + }, + "USDAPPQ203ForeignSiteInspection": { + "@id": "https://w3id.org/traceability#USDAPPQ203ForeignSiteInspection", + "@context": { + "certificateNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "commonInfo": { + "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" + }, + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "signatureDate": { + "@id": "https://www.gs1.org/voc/certificationAuditDate" + }, + "inspectionType": { + "@id": "https://www.gs1.org/voc/certificationType" + }, + "observations": { + "@id": "https://vocabulary.uncefact.org/relatedObservation" + } + } + }, + "USDAPPQ309APestInterceptionRecord": { + "@id": "https://w3id.org/traceability#USDAPPQ309APestInterceptionRecord", + "@context": { + "interceptionNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "shippingStop": { + "@id": "https://vocabulary.uncefact.org/itineraryStopEvent" + }, + "forwardTo": { + "@id": "https://vocabulary.uncefact.org/recipientAssignedId" + }, + "priority": { + "@id": "https://vocabulary.uncefact.org/priorityCode" + }, + "interceptionDate": { + "@id": "https://vocabulary.uncefact.org/actualOccurrenceDateTime" + }, + "inspector": { + "@id": "https://vocabulary.uncefact.org/inspectionParty" + }, + "overtime": { + "@id": "https://vocabulary.uncefact.org/information" + }, + "pathway": { + "@id": "https://vocabulary.uncefact.org/mode" + }, + "modeOfTransportation": { + "@id": "https://vocabulary.uncefact.org/mode" + }, + "materialFor": { + "@id": "https://vocabulary.uncefact.org/intendedUse" + }, + "narp": { + "@id": "https://vocabulary.uncefact.org/statementNote" + }, + "importedAs": { + "@id": "https://schema.org/description" + }, + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "whereIntercepted": { + "@id": "https://vocabulary.uncefact.org/AttachedTransportEquipment" + }, + "PestSample": { + "@id": "http://rs.tdwg.org/dwc/terms/materialSampleID" + }, + "pestDeterminations": { + "@id": "https://dwc.tdwg.org/list/#dwc_identificationID" + }, + "quarantineStatus": { + "@id": "https://vocabulary.uncefact.org/conditionCode" + }, + "remarks": { + "@id": "https://vocabulary.uncefact.org/remark" + } + } + }, + "USDAPPQ368NoticeOfArrival": { + "@id": "https://w3id.org/traceability#USDAPPQ368NoticeOfArrival", + "@context": { + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "arrivalDate": { + "@id": "https://vocabulary.uncefact.org/actualArrivalRelatedDateTime" + }, + "permitNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "customsEntryNumber": { + "@id": "https://vocabulary.uncefact.org/customsId" + }, + "presentLocation": { + "@id": "https://vocabulary.uncefact.org/consignmentDestinationSpecifiedLocation" + }, + "locationGrown": { + "@id": "https://vocabulary.uncefact.org/originLocation" + }, + "ITNumber": { + "@id": "https://vocabulary.uncefact.org/customsId" + }, + "productDisposition": { + "@id": "https://vocabulary.uncefact.org/dispositionDocument" + }, + "ppqOfficial": { + "@id": "https://vocabulary.uncefact.org/inspectionParty" + }, + "signatureDate": { + "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" + } + } + }, + "USDAPPQ391SpecimensForDetermination": { + "@id": "https://w3id.org/traceability#USDAPPQ391SpecimensForDetermination", + "@context": { + "priority": { + "@id": "https://vocabulary.uncefact.org/priorityCode" + }, + "priorityExplanation": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "collectionNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "submissionDate": { + "@id": "https://vocabulary.uncefact.org/reportSubmissionDateTime" + }, + "collectionDate": { + "@id": "https://vocabulary.uncefact.org/actualOccurrenceDateTime" + }, + "submittingAgency": { + "@id": "https://vocabulary.uncefact.org/agencyId" + }, + "submitter": { + "@id": "https://vocabulary.uncefact.org/PartyRoleCodeList#TB" + }, + "collector": { + "@id": "https://vocabulary.uncefact.org/inspectionParty" + }, + "interceptionSite": { + "@id": "https://vocabulary.uncefact.org/occurrenceLocation" + }, + "identificationReason": { + "@id": "https://vocabulary.uncefact.org/reasonCode" + }, + "remarks": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "tentativeDetermination": { + "@id": "https://dwc.tdwg.org/list/#dwc_identificationID" + }, + "finalDetermination": { + "@id": "https://dwc.tdwg.org/list/#dwc_identificationID" + }, + "sampleDisposition": { + "@id": "https://dwc.tdwg.org/list/#dwc_disposition" + }, + "signatureDate": { + "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" + }, + "lab": { + "@id": "https://vocabulary.uncefact.org/lodgementLocation" + }, + "labConformationNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "dateReceived": { + "@id": "https://vocabulary.uncefact.org/acceptanceDateTime" + } + } + }, + "USDAPPQ429FumigationRecord": { + "@id": "https://w3id.org/traceability#USDAPPQ429FumigationRecord", + "@context": { + "tarpaulin": { + "@id": "https://vocabulary.uncefact.org/value" + }, + "stationReporting": { + "@id": "https://vocabulary.uncefact.org/relevantLocation" + }, + "pest": { + "@id": "https://schema.org/description" + }, + "interceptionRecord": { + "@id": "https://w3id.org/traceability#USDAPPQ309APestInterceptionRecord.yml" + }, + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "fumigationContractor": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "dateFumigationOrdered": { + "@id": "https://vocabulary.uncefact.org/actualDateTime" + }, + "fumigationSite": { + "@id": "https://vocabulary.uncefact.org/occurrenceLocation" + }, + "dateFumigated": { + "@id": "https://vocabulary.uncefact.org/actualOccurrenceDateTime" + }, + "fumigantAndTreatmentSchedule": { + "@id": "https://vocabulary.uncefact.org/regulationName" + }, + "temperatureOfSpace": { + "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" + }, + "temperatureOfCommodity": { + "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" + }, + "gasAnalyzer": { + "@id": "https://schema.org/description" + }, + "enclosure": { + "@id": "https://schema.org/description" + }, + "weatherConditions": { + "@id": "https://schema.org/description" + }, + "cubicCapacity": { + "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" + }, + "section18Exemption": { + "@id": "https://vocabulary.uncefact.org/value" + }, + "numberOfFans": { + "@id": "https://vocabulary.uncefact.org/unitQuantity" + }, + "totalCFMOfFans": { + "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" + }, + "timeFansOperated": { + "@id": "https://vocabulary.uncefact.org/durationMeasure" + }, + "foodOrFeedCommodity": { + "@id": "https://vocabulary.uncefact.org/functionDescription" + }, + "gasIntroductionStart": { + "@id": "https://vocabulary.uncefact.org/startDateTime" + }, + "gasIntroductionFinish": { + "@id": "https://vocabulary.uncefact.org/endDateTime" + }, + "totalGasIntroduced": { + "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" + }, + "residueSampleTaken": { + "@id": "https://vocabulary.uncefact.org/value" + }, + "residueSampleNumber": { + "@id": "https://schema.org/description" + }, + "gasConcentrations": { + "@id": "https://vocabulary.uncefact.org/relatedObservation" + }, + "detectorTubeReadings": { + "@id": "https://vocabulary.uncefact.org/relatedObservation" + }, + "remarks": { + "@id": "https://vocabulary.uncefact.org/remark" + }, + "inspector": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "reviewer": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "fumigatorMaterials": { + "@id": "https://schema.org/description" + }, + "ppqMaterials": { + "@id": "https://schema.org/description" + }, + "preparationProcedures": { + "@id": "https://schema.org/description" + } + } + }, + "USDAPPQ449RTemperatureCalibration": { + "@id": "https://w3id.org/traceability#USDAPPQ449RTemperatureCalibration", + "@context": { + "vesselName": { + "@id": "https://vocabulary.uncefact.org/name" + }, + "ppqDutyStation": { + "@id": "https://vocabulary.uncefact.org/transitCustomsOfficeSpecifiedLocation" + }, + "inspectionDate": { + "@id": "https://vocabulary.uncefact.org/performanceDateTime" + }, + "inspectionPoint": { + "@id": "https://vocabulary.uncefact.org/transitLocation" + }, + "hullNumberDockyard": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "imoNumber": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "flagCode": { + "@id": "https://vocabulary.uncefact.org/identification" + }, + "shipsOfficer": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "ownerOperator": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "instrument1MakeModel": { + "@id": "https://vocabulary.uncefact.org/AttachedTransportEquipment" + }, + "instrument2MakeModel": { + "@id": "https://vocabulary.uncefact.org/AttachedTransportEquipment" + }, + "locationsDiagramMatchSatisfactory": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "sensorsBoxesLabelingSatisfactory": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "cableLengthSatisfactory": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "reactionTimeSatisfactory": { + "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" + }, + "temperatureReadings": { + "@id": "https://vocabulary.uncefact.org/transportTemperature" + }, + "participatingOfficials": { + "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" + }, + "remarks": { + "@id": "https://vocabulary.uncefact.org/remarks" + }, + "company": { + "@id": "https://vocabulary.uncefact.org/specifiedOrganization" + }, + "signatureDate": { + "@id": "https://vocabulary.uncefact.org/performanceDateTime" + } + } + }, + "USDAPPQ505PlantDeclaration": { + "@id": "https://w3id.org/traceability#USDAPPQ505PlantDeclaration", + "@context": { + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "productDeclarations": { + "@id": "https://w3id.org/traceability#LaceyActProductDeclaration" + }, + "preparer": { + "@id": "https://vocabulary.uncefact.org/declarantParty" + }, + "date": { + "@id": "https://vocabulary.uncefact.org/issueDateTime" + } + } + }, + "USDAPPQ519ComplianceAgreement": { + "@id": "https://w3id.org/traceability#USDAPPQ519ComplianceAgreement", + "@context": { + "person": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "firm": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "regulatedArticles": { + "@id": "https://www.gs1.org/voc/regulatedProductName" + }, + "quarantinesRegulations": { + "@id": "https://vocabulary.uncefact.org/applicableRegulatoryProcedure" + }, + "agreement": { + "@id": "https://vocabulary.uncefact.org/guarantee" + }, + "signatureDate": { + "@id": "https://vocabulary.uncefact.org/issueDateTime" + }, + "ppqCbpOfficial": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "usAgencyOfficial": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "agreementNumber": { + "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AJS" + }, + "agreementDate": { + "@id": "https://vocabulary.uncefact.org/issueDateTime" + } + } + }, + "USDAPPQ587PlantImportApplication": { + "@id": "https://w3id.org/traceability#USDAPPQ587PlantImportApplication", + "@context": { + "applicant": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "plantProductsImported": { + "@id": "https://vocabulary.uncefact.org/specifiedProduct" + }, + "intendedUse": { + "@id": "https://vocabulary.uncefact.org/intendedUse" + }, + "meansOfTransportation": { + "@id": "https://vocabulary.uncefact.org/usedTransportMeans" + }, + "date": { + "@id": "https://vocabulary.uncefact.org/creationDateTime" + } + } + }, + "USDAPPQ587PlantImportPermit": { + "@id": "https://w3id.org/traceability#USDAPPQ587PlantImportPermit", + "@context": { + "applicant": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "shipment": { + "@id": "https://vocabulary.uncefact.org/transportPackage" + }, + "intendedUse": { + "@id": "https://vocabulary.uncefact.org/intendedUse" + }, + "signatureDate": { + "@id": "https://vocabulary.uncefact.org/issueDateTime" + } + } + }, + "USDASpecialtyCrops237AForm": { + "@id": "https://w3id.org/traceability#USDASpecialtyCrops237AForm", + "@context": { + "requestDate": { + "@id": "https://vocabulary.uncefact.org/reportSubmissionDateTime" + }, + "anticipatedAuditDate": { + "@id": "https://www.gs1.org/voc/certificationAuditDate" + }, + "auditee": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "applicant": { + "@id": "https://vocabulary.uncefact.org/associatedParty" + }, + "billingAccountNumber": { + "@id": "https://schema.org/accountId" + }, + "locations": { + "@id": "https://schema.org/location" + }, + "totalArea": { + "@id": "https://www.gs1.org/voc/grossArea" + }, + "commoditiesCovered": { + "@id": "https://www.gs1.org/voc/certificationSubject" + }, + "auditProgramsRequested": { + "@id": "https://www.gs1.org/voc/certificationType" + }, + "countByInspector": { + "@id": "https://vocabulary.uncefact.org/applicableSpecifiedAction" + }, + "additionalRemarks": { + "@id": "https://vocabulary.uncefact.org/remarks" + } + } + }, + "USMCACertifier": { + "@id": "https://w3id.org/traceability/USMCACertifier", + "@context": { + "role": { + "@id": "https://w3id.org/traceability#certifierRole" + }, + "certifierDetails": { + "@id": "https://w3id.org/traceability#certifierDetails" + } + } + }, + "USMCAClaims": { + "@id": "https://w3id.org/traceability/USMCAClaims", + "@context": { + "producerDetails": { + "@id": "https://schema.org/manufacturer" + }, + "producerConfidential": { + "@id": "https://w3id.org/traceability#producerConfidential" + }, + "importerDetails": { + "@id": "https://w3id.org/traceability#importerDetails" + }, + "importerUnknown": { + "@id": "https://w3id.org/traceability#importerUnknown" + }, + "exporterDetails": { + "@id": "https://w3id.org/traceability#exporterDetails" + }, + "goods": { + "@id": "https://schema.org/Product" + } + } + }, + "USMCAProduct": { + "@id": "https://w3id.org/traceability/USMCAProduct", + "@context": { + "commodityCode": { + "@id": "https://w3id.org/traceability#commodityCode" + }, + "commodityCodeType": { + "@id": "https://w3id.org/traceability#commodityCodeType" + }, + "originCriterion": { + "@id": "https://w3id.org/traceability#originCriterion" + }, + "countryOfOrigin": { + "@id": "https://w3id.org/traceability#countryOfOrigin" + } + } + }, + "UsdaSc6": { + "@id": "https://w3id.org/traceability#UsdaSc6", + "@context": { + "serialNumber": { + "@id": "https://w3id.org/traceability#serialNumber" + }, + "customsEntryNumber": { + "@id": "https://w3id.org/traceability#customsEntryNumber" + }, + "tariffCodeNumber": { + "@id": "https://w3id.org/traceability#tariffCodeNumber" + }, + "carrierId": { + "@id": "https://w3id.org/traceability#carrierId" + }, + "lotId": { + "@id": "https://w3id.org/traceability#lotId" + }, + "dateOfEntry": { + "@id": "https://w3id.org/traceability#dateOfEntry" + }, + "signatureDate": { + "@id": "https://w3id.org/traceability#signatureDate" + }, + "facility": { + "@id": "https://www.gs1.org/voc/Place" + }, + "inspector": { + "@id": "https://w3id.org/traceability#Inspector" + }, + "shipment": { + "@id": "https://w3id.org/traceability#AgricultureParcelDelivery" + }, + "applicant": { + "@id": "https://w3id.org/traceability#applicant" + }, + "importerSignatureDate": { + "@id": "https://w3id.org/traceability#importerSignatureDate" + }, + "inspectionDate": { + "@id": "https://schema.org/DateTime" + }, + "intendedUse": { + "@id": "https://w3id.org/traceability#intendedUse" + }, + "intendedUseCert": { + "@id": "https://w3id.org/traceability#intendedUseCert" + } + } + }, + "ActivityPubActorCard": { + "@id": "https://w3id.org/traceability#ActivityPubActorCard", + "@context": {} + }, + "AgricultureCanineCard": { + "@id": "https://w3id.org/traceability#AgricultureCanineCard", + "@context": {} + }, + "BankAccountCredential": { + "@id": "https://w3id.org/traceability#BankAccountCredential", + "@context": {} + }, + "BillOfLadingCredential": { + "@id": "https://w3id.org/traceability#BillOfLadingCredential", + "@context": {} + }, + "CBP3461EntryCredential": { + "@id": "https://w3id.org/traceability#CBP3461EntryCredential", + "@context": {} + }, + "CBP7501EntrySummaryCredential": { + "@id": "https://w3id.org/traceability#CBP7501EntrySummaryCredential", + "@context": {} + }, + "CBPEntryType86Credential": { + "@id": "https://w3id.org/traceability#CBPEntryType86Credential", + "@context": {} + }, + "CBPSection321DeMinimisDeMinimisCredential": { + "@id": "https://w3id.org/traceability#CBPSection321DeMinimisCredential", + "@context": {} + }, + "CTPATCertificate": { + "@id": "https://w3id.org/traceability#CTPATCertificate", + "@context": {} + }, + "CTPATEIPApplicationCredential": { + "@id": "https://w3id.org/traceability#CTPATEIPApplicationCredential", + "@context": {} + }, + "CTPATEIPFulfillmentCredential": { + "@id": "https://w3id.org/traceability#CTPATEIPFulfillmentCredential", + "@context": {} + }, + "CTPATEIPMarketplaceCredential": { + "@id": "https://w3id.org/traceability#CTPATEIPMarketplaceCredential", + "@context": {} + }, + "CTPATEIPSellerCredential": { + "@id": "https://w3id.org/traceability#CTPATEIPSellerCredential", + "@context": {} + }, + "CertificationOfOrigin": { + "@id": "https://w3id.org/traceability#CertificationOfOrigin", + "@context": {} + }, + "CommercialInvoiceCredential": { + "@id": "https://w3id.org/traceability#CommercialInvoiceCredential", + "@context": {} + }, + "DCSAShippingInstructionCredential": { + "@id": "https://w3id.org/traceability#DCSAShippingInstructionCredential", + "@context": {} + }, + "DCSATransportDocumentCredential": { + "@id": "https://w3id.org/traceability#DCSATransportDocumentCredential", + "@context": {} + }, + "DeliveryScheduleCredential": { + "@id": "https://w3id.org/traceability#DeliveryScheduleCredential", + "@context": {} + }, + "DeliveryStatementCredential": { + "@id": "https://w3id.org/traceability#DeliveryStatementCredential", + "@context": {} + }, + "DigitalProductPassportCredential": { + "@id": "https://w3id.org/traceability#DigitalProductPassportCredential", + "@context": {} + }, + "DigitalProductPassportDataCarrierCredential": { + "@id": "https://w3id.org/traceability#DigitalProductPassportDataCarrierCredential", + "@context": {} + }, + "EntryNumberCredential": { + "@id": "https://w3id.org/traceability#EntryNumberCredential", + "@context": {} + }, + "FSMACreatingCTECredential": { + "@id": "https://w3id.org/traceability#FSMACreatingCTECredential", + "@context": {} + }, + "FSMAFirstReceiverDataCredential": { + "@id": "https://w3id.org/traceability#FSMAFirstReceiverDataCredential", + "@context": {} + }, + "FSMAGrowingCTECredential": { + "@id": "https://w3id.org/traceability#FSMAGrowingCTECredential", + "@context": {} + }, + "FSMAReceivingCTECredential": { + "@id": "https://w3id.org/traceability#FSMAReceivingCTECredential", + "@context": {} + }, + "FSMAShippingCTECredential": { + "@id": "https://w3id.org/traceability#FSMAShippingCTECredential", + "@context": {} + }, + "FSMATransformingCTECredential": { + "@id": "https://w3id.org/traceability#FSMATransformingCTECredential", + "@context": {} + }, + "FoodDefenseInspectionCredential": { + "@id": "https://w3id.org/traceability#FoodDefenseInspectionCredential", + "@context": {} + }, + "FoodGradeInspectionCredential": { + "@id": "https://w3id.org/traceability#FoodGradeInspectionCredential", + "@context": {} + }, + "FreightManifestCredential": { + "@id": "https://w3id.org/traceability#FreightManifestCredential", + "@context": {} + }, + "FulfillmentRegistrationCredential": { + "@id": "https://w3id.org/traceability#FulfillmentRegistrationCredential", + "@context": {} + }, + "GAPInspectionCredential": { + "@id": "https://w3id.org/traceability#GAPInspectionCredential", + "@context": {} + }, + "GS18PrefixLicenseCredential": { + "@id": "https://w3id.org/traceability#GS18PrefixLicenseCredential", + "@context": {} + }, + "GS1CompanyPrefixLicenseCredential": { + "@id": "https://w3id.org/traceability#GS1CompanyPrefixLicenseCredential", + "@context": {} + }, + "GS1DataCredential": { + "@id": "https://w3id.org/traceability#GS1DataCredential", + "@context": {} + }, + "GS1DelegationCredential": { + "@id": "https://w3id.org/traceability#GS1DelegationCredential", + "@context": {} + }, + "GS1IdentificationKeyLicenseCredential": { + "@id": "https://w3id.org/traceability#GS1IdentificationKeyLicenseCredential", + "@context": {} + }, + "GS1KeyCredential": { + "@id": "https://w3id.org/traceability#GS1KeyCredential", + "@context": {} + }, + "GS1PrefixLicenseCredential": { + "@id": "https://w3id.org/traceability#GS1PrefixLicenseCredential", + "@context": {} + }, + "HouseBillOfLadingCredential": { + "@id": "https://w3id.org/traceability#HouseBillOfLadingCredential", + "@context": {} + }, + "IATAAirWaybillCredential": { + "@id": "https://w3id.org/traceability#IATAAirWaybillCredential", + "@context": {} + }, + "ImporterSecurityFilingCredential": { + "@id": "https://w3id.org/traceability#ImporterSecurityFilingCredential", + "@context": {} + }, + "IntellectualPropertyRightsCredential": { + "@id": "https://w3id.org/traceability#IntellectualPropertyRightsCredential", + "@context": {} + }, + "IntellectualPropertyRightsLicenseCredential": { + "@id": "https://w3id.org/traceability#IntellectualPropertyRightsLicenseCredential", + "@context": {} + }, + "IntentToImportCredential": { + "@id": "https://w3id.org/traceability#IntentToImportCredential", + "@context": {} + }, + "InventoryRegistrationCredential": { + "@id": "https://w3id.org/traceability#InventoryRegistrationCredential", + "@context": {} + }, + "MasterBillOfLadingCredential": { + "@id": "https://w3id.org/traceability#MasterBillOfLadingCredential", + "@context": {} + }, + "MexicoEInvoiceCredential": { + "@id": "https://w3id.org/traceability#MexicoEInvoiceCredential", + "@context": {} + }, + "MillTestReportCredential": { + "@id": "https://w3id.org/traceability#MillTestReportCredential", + "@context": {} + }, + "MonthlyAdvanceManifestCredential": { + "@id": "https://w3id.org/traceability#MonthlyAdvanceManifestCredential", + "@context": {} + }, + "MultiModalBillOfLadingCredential": { + "@id": "https://w3id.org/traceability#MultiModalBillOfLadingCredential", + "@context": {} + }, + "OilAndGasDeliveryTicketCredential": { + "@id": "https://w3id.org/traceability#OilAndGasDeliveryTicketCredential", + "@context": {} + }, + "OilAndGasProductCredential": { + "@id": "https://w3id.org/traceability#OilAndGasProductCredential", + "@context": {} + }, + "OrderConfirmationCredential": { + "@id": "https://w3id.org/traceability#OrderConfirmationCredential", + "@context": {} + }, + "OrganicCertificationCredential": { + "@id": "https://w3id.org/traceability#OrganicCertificationCredential", + "@context": {} + }, + "PGAShipmentStatusCredential": { + "@id": "https://w3id.org/traceability#PGAShipmentStatusCredential", + "@context": {} + }, + "PackingListCredential": { + "@id": "https://w3id.org/traceability#PackingListCredential", + "@context": {} + }, + "PlantSystemsInspectionCredential": { + "@id": "https://w3id.org/traceability#PlantSystemsInspectionCredential", + "@context": {} + }, + "PowerOfAttorneyCredential": { + "@id": "https://spec.edmcouncil.org/fibo/ontology/BE/LegalEntities/LegalPersons/PowerOfAttorney", + "@context": {} + }, + "ProductRegistrationCredential": { + "@id": "https://w3id.org/traceability#ProductRegistrationCredential", + "@context": {} + }, + "PurchaseOrderCredential": { + "@id": "https://w3id.org/traceability#PurchaseOrderCredential", + "@context": {} + }, + "SIMASteelImportLicenseApplicationCredential": { + "@id": "https://w3id.org/traceability#SIMASteelImportLicenseApplicationCredential", + "@context": {} + }, + "SIMASteelImportLicenseCredential": { + "@id": "https://w3id.org/traceability#SIMASteelImportLicenseCredential", + "@context": {} + }, + "SeaCargoManifestCredential": { + "@id": "https://w3id.org/traceability#SeaCargoManifestCredential", + "@context": {} + }, + "SellerRegistrationCredential": { + "@id": "https://w3id.org/traceability#SellerRegistrationCredential", + "@context": {} + }, + "ShippingInstructionsCredential": { + "@id": "https://w3id.org/traceability#ShippingInstructionsCredential", + "@context": {} + }, + "SoftwareBillofMaterialsCredential": { + "@id": "https://w3id.org/traceability#SoftwareBillOfMaterialsCredential", + "@context": {} + }, + "ThingCredential": { + "@id": "https://w3id.org/traceability#ThingCredential", + "@context": {} + }, + "USMCACertificationOfOrigin": { + "@id": "https://w3id.org/traceability#USMCACertificationOfOrigin", + "@context": {} + }, + "VerifiableBusinessCard": { + "@id": "https://w3id.org/traceability#VerifiableBusinessCard", + "@context": {} + }, + "VerifiablePostmanCollection": { + "@id": "https://w3id.org/traceability#VerifiablePostmanCollection", + "@context": {} + }, + "VerifiableScorecard": { + "@id": "https://w3id.org/traceability#VerifiableScorecard", + "@context": {} + } + } + } \ No newline at end of file From 70a0b660137cbab2d2251f9733739b0a224f4340 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 10:04:04 -0500 Subject: [PATCH 02/26] added vc-api routes, improved presentation models, added prove funcitonality to ld_vc manager Signed-off-by: pstlouis --- aries_cloudagent/config/default_context.py | 1 + aries_cloudagent/vc/vc_ld/manager.py | 38 ++- .../vc/vc_ld/models/presentation.py | 310 ++++++++++++++++-- aries_cloudagent/vc_api/__init__.py | 0 aries_cloudagent/vc_api/example.py | 186 +++++++++++ aries_cloudagent/vc_api/routes.py | 187 +++++++++++ open-api/openapi.json | 7 + open-api/swagger.json | 7 + 8 files changed, 701 insertions(+), 35 deletions(-) create mode 100644 aries_cloudagent/vc_api/__init__.py create mode 100644 aries_cloudagent/vc_api/example.py create mode 100644 aries_cloudagent/vc_api/routes.py diff --git a/aries_cloudagent/config/default_context.py b/aries_cloudagent/config/default_context.py index 18e5c4a8ca..9645b18fbe 100644 --- a/aries_cloudagent/config/default_context.py +++ b/aries_cloudagent/config/default_context.py @@ -142,6 +142,7 @@ async def load_plugins(self, context: InjectionContext): plugin_registry.register_plugin("aries_cloudagent.resolver") plugin_registry.register_plugin("aries_cloudagent.settings") plugin_registry.register_plugin("aries_cloudagent.vc") + plugin_registry.register_plugin("aries_cloudagent.vc_api") plugin_registry.register_plugin("aries_cloudagent.wallet") if wallet_type == "askar-anoncreds": plugin_registry.register_plugin("aries_cloudagent.anoncreds") diff --git a/aries_cloudagent/vc/vc_ld/manager.py b/aries_cloudagent/vc/vc_ld/manager.py index 89f11e9ebc..9e584c52ca 100644 --- a/aries_cloudagent/vc/vc_ld/manager.py +++ b/aries_cloudagent/vc/vc_ld/manager.py @@ -1,7 +1,7 @@ """Manager for performing Linked Data Proof signatures over JSON-LD formatted W3C VCs.""" -from typing import Dict, Optional, Type +from typing import Dict, Optional, Type, Union from ...core.profile import Profile from ...wallet.base import BaseWallet @@ -27,6 +27,7 @@ from ..vc_ld.models.presentation import VerifiablePresentation from ..vc_ld.validation_result import PresentationVerificationResult from .issue import issue as ldp_issue +from .prove import sign_presentation from .models.credential import VerifiableCredential from .models.linked_data_proof import LDProof from .models.options import LDProofVCOptions @@ -266,10 +267,16 @@ async def prepare_credential( return credential - async def _get_suite_for_credential( - self, credential: VerifiableCredential, options: LDProofVCOptions + async def _get_suite_for_document( + self, document: Union[VerifiableCredential, VerifiablePresentation], options: LDProofVCOptions ) -> LinkedDataProof: - issuer_id = credential.issuer_id + document_type = document.type[0] + + if document_type == 'VerifiableCredential': + issuer_id = document.issuer_id + if document_type == 'VerifiablePresentation': + issuer_id = document.holder_id + proof_type = options.proof_type if not issuer_id: @@ -345,6 +352,29 @@ async def issue( ) return VerifiableCredential.deserialize(vc) + async def prove( + self, presentation: VerifiablePresentation, options: LDProofVCOptions + ) -> VerifiablePresentation: + """Sign a VP with a Linked Data Proof.""" + presentation = await self.prepare_presentation(presentation, options) + + # Get signature suite, proof purpose and document loader + suite = await self._get_suite_for_document(presentation, options) + proof_purpose = self._get_proof_purpose( + proof_purpose=options.proof_purpose, + challenge=options.challenge, + domain=options.domain, + ) + document_loader = self.profile.inject(DocumentLoader) + + vp = await sign_presentation( + presentation=presentation.serialize(), + suite=suite, + document_loader=document_loader, + purpose=proof_purpose, + ) + return VerifiablePresentation.deserialize(vp) + async def verify_presentation( self, vp: VerifiablePresentation, options: LDProofVCOptions ) -> PresentationVerificationResult: diff --git a/aries_cloudagent/vc/vc_ld/models/presentation.py b/aries_cloudagent/vc/vc_ld/models/presentation.py index 0e467c9fa5..1a91b922ce 100644 --- a/aries_cloudagent/vc/vc_ld/models/presentation.py +++ b/aries_cloudagent/vc/vc_ld/models/presentation.py @@ -1,11 +1,35 @@ """Verifiable Presentation model.""" -from typing import Optional, Sequence, Union +from typing import List, Optional, Sequence, Union -from marshmallow import INCLUDE, fields +from marshmallow import INCLUDE, ValidationError, fields, post_dump from ....messaging.models.base import BaseModel, BaseModelSchema -from ....messaging.valid import UUID4_EXAMPLE, UUID4_VALIDATE, StrOrDictField -from .linked_data_proof import LinkedDataProofSchema +from ....messaging.valid import ( + UUID4_EXAMPLE, + UUID4_VALIDATE, + CREDENTIAL_CONTEXT_EXAMPLE, + CREDENTIAL_CONTEXT_VALIDATE, + CREDENTIAL_SUBJECT_EXAMPLE, + CREDENTIAL_SUBJECT_VALIDATE, + CREDENTIAL_TYPE_EXAMPLE, + CREDENTIAL_TYPE_VALIDATE, + RFC3339_DATETIME_EXAMPLE, + RFC3339_DATETIME_VALIDATE, + DictOrDictListField, + DIDKey, + StrOrDictField, + Uri, + UriOrDictField, + ) +from ...ld_proofs.constants import ( + CREDENTIALS_CONTEXT_V1_URL, + VERIFIABLE_PRESENTATION_TYPE, + VERIFIABLE_CREDENTIAL_TYPE, +) +from .linked_data_proof import LDProof, LinkedDataProofSchema +from .credential import ( + VerifiableCredential +) class VerifiablePresentation(BaseModel): @@ -14,52 +38,276 @@ class VerifiablePresentation(BaseModel): class Meta: """VerifiablePresentation metadata.""" - schema_class = "VerifiablePresentationSchema" - unknown = INCLUDE + schema_class = "PresentationSchema" def __init__( self, - *, + context: Optional[List[Union[str, dict]]] = None, id: Optional[str] = None, - contexts: Optional[Sequence[Union[str, dict]]] = None, - types: Optional[Sequence[str]] = None, - credentials: Optional[Sequence[dict]] = None, - proof: Optional[Sequence[dict]] = None, + type: Optional[List[str]] = None, + holder: Optional[Union[dict, str]] = None, + verifiable_credential: Optional[List[dict]] = None, + proof: Optional[Union[dict, LDProof]] = None, **kwargs, - ): + ) -> None: """Initialize VerifiablePresentation.""" - super().__init__() - self.id = id - self.contexts = contexts - self.types = types - self.credentials = credentials - self.proof = proof + self._context = context or [CREDENTIALS_CONTEXT_V1_URL] + self._id = id + self._holder = holder + self._type = type or [VERIFIABLE_PRESENTATION_TYPE] + self._verifiable_credential = verifiable_credential + self._proof = proof -class VerifiablePresentationSchema(BaseModelSchema): - """Single Verifiable Presentation Schema.""" + self.extra = kwargs + + @property + def context(self): + """Getter for context.""" + return self._context + + @context.setter + def context(self, context: List[Union[str, dict]]): + """Setter for context. + + First item must be credentials v1 url + """ + assert context[0] == CREDENTIALS_CONTEXT_V1_URL + + self._context = context + + def add_context(self, context: Union[str, dict]): + """Add a context to this presentation.""" + self._context.append(context) + + @property + def context_urls(self) -> List[str]: + """Getter for context urls.""" + return [context for context in self.context if isinstance(context, str)] + + @property + def type(self) -> List[str]: + """Getter for type.""" + return self._type + + @type.setter + def type(self, type: List[str]): + """Setter for type. + + First item must be VerifiablePresentation + """ + assert VERIFIABLE_PRESENTATION_TYPE in type + + self._type = type + + def add_type(self, type: str): + """Add a type to this presentation.""" + self._type.append(type) + + @property + def id(self): + """Getter for id.""" + return self._id + + @id.setter + def id(self, id: Union[str, None]): + """Setter for id.""" + if id: + uri_validator = Uri() + uri_validator(id) + + self._id = id + + @property + def holder_id(self) -> Optional[str]: + """Getter for holder id.""" + if not self._holder: + return None + elif isinstance(self._holder, str): + return self._holder + + return self._holder.get("id") + + @holder_id.setter + def holder_id(self, holder_id: str): + """Setter for holder id.""" + uri_validator = Uri() + uri_validator(holder_id) + + # Use simple string variant if possible + if not self._holder or isinstance(self._holder, str): + self._holder = holder_id + else: + self._holder["id"] = holder_id + + @property + def holder(self): + """Getter for holder.""" + return self._holder + + @holder.setter + def holder(self, holder: Union[str, dict]): + """Setter for holder.""" + uri_validator = Uri() + + holder_id = holder if isinstance(holder, str) else holder.get("id") + + if not holder_id: + raise ValidationError("Holder id is required") + uri_validator(holder_id) + + self._holder = holder + + @property + def verifiable_credential(self): + """Getter for verifiable credential.""" + return self._verifiable_credential + + @verifiable_credential.setter + def verifiable_credential(self, verifiable_credential: List[dict]): + """Setter for verifiable credential.""" + + uri_validator = Uri() + + self._verifiable_credential = verifiable_credential + + @property + def proof(self): + """Getter for proof.""" + return self._proof + + @proof.setter + def proof(self, proof: LDProof): + """Setter for proof.""" + self._proof = proof + + def __eq__(self, o: object) -> bool: + """Check equalness.""" + if isinstance(o, VerifiablePresentation): + return ( + self.context == o.context + and self.id == o.id + and self.type == o.type + and self.holder == o.holder + and self.verifiable_credentials == o.verifiable_credentials + and self.proof == o.proof + and self.extra == o.extra + ) + + return False + + +class PresentationSchema(BaseModelSchema): + """Linked data presentation schema. + + Based on https://www.w3.org/TR/vc-data-model + + """ class Meta: - """VerifiablePresentationSchema metadata.""" + """Accept parameter overload.""" - model_class = VerifiablePresentation unknown = INCLUDE + model_class = VerifiablePresentation + + context = fields.List( + UriOrDictField(required=True), + data_key="@context", + required=True, + validate=CREDENTIAL_CONTEXT_VALIDATE, + metadata={ + "description": "The JSON-LD context of the presentation", + "example": [CREDENTIALS_CONTEXT_V1_URL], + }, + ) id = fields.Str( required=False, - validate=UUID4_VALIDATE, - metadata={"description": "ID", "example": UUID4_EXAMPLE}, + validate=Uri(), + metadata={ + "desscription": "The ID of the presentation", + "example": "http://example.edu/presentations/1872", + }, ) - contexts = fields.List(StrOrDictField(), data_key="@context") - types = fields.List( - fields.Str(required=False, metadata={"description": "Types"}), data_key="type" + + type = fields.List( + fields.Str(required=True), + required=True, + # validate=PRESENTATION_TYPE_VALIDATE, + metadata={ + "description": "The JSON-LD type of the presentation", + "example": [VERIFIABLE_PRESENTATION_TYPE], + }, ) - credentials = fields.List( - fields.Dict(required=False, metadata={"description": "Credentials"}), + + holder = StrOrDictField( + required=True, + metadata={ + "description": ( + "The JSON-LD Verifiable Credential Holder. Either string of object with" + " id field." + ), + "example": DIDKey.EXAMPLE, + }, + ) + + verifiable_credential = fields.List( + fields.Dict(required=True), + required=True, data_key="verifiableCredential", + # validate=VERIFIABLE_CREDENTIAL_VALIDATE, + metadata={}, ) + proof = fields.Nested( LinkedDataProofSchema(), - required=True, - metadata={"description": "The proof of the credential"}, + required=False, + metadata={ + "description": "The proof of the presentation", + "example": { + "type": "Ed25519Signature2018", + "verificationMethod": ( + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38Ee" + "fXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + ), + "created": "2019-12-11T03:50:55", + "proofPurpose": "assertionMethod", + "jws": ( + "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0JiNjQiXX0..lKJU0Df_k" + "eblRKhZAS9Qq6zybm-HqUXNVZ8vgEPNTAjQKBhQDxvXNo7nvtUBb_Eq1Ch6YBKY5qBQ" + ), + }, + }, ) + + @post_dump(pass_original=True) + def add_unknown_properties(self, data: dict, original, **kwargs): + """Add back unknown properties before outputting.""" + + data.update(original.extra) + + return data + +class VerifiablePresentationSchema(PresentationSchema): + """Single Verifiable Presentation Schema.""" + + proof = fields.Nested( + LinkedDataProofSchema(), + required=True, + metadata={ + "description": "The proof of the presentation", + "example": { + "type": "Ed25519Signature2018", + "verificationMethod": ( + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38Ee" + "fXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + ), + "created": "2019-12-11T03:50:55", + "proofPurpose": "assertionMethod", + "jws": ( + "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0JiNjQiXX0..lKJU0Df_k" + "eblRKhZAS9Qq6zybm-HqUXNVZ8vgEPNTAjQKBhQDxvXNo7nvtUBb_Eq1Ch6YBKY5qBQ" + ), + }, + }, + ) \ No newline at end of file diff --git a/aries_cloudagent/vc_api/__init__.py b/aries_cloudagent/vc_api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aries_cloudagent/vc_api/example.py b/aries_cloudagent/vc_api/example.py new file mode 100644 index 0000000000..49802652a8 --- /dev/null +++ b/aries_cloudagent/vc_api/example.py @@ -0,0 +1,186 @@ +from marshmallow import Schema, fields + +class IssueCredentialRequest(Schema): + credential = fields.Dict( + metadata={ + "example": { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "type": [ + "VerifiableCredential" + ] + } + } + ) + options = fields.Dict( + metadata={ + "example": {} + } + ) + +class IssueCredentialResponse(Schema): + verifiableCredential = fields.Dict( + metadata={ + "example": { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": [ + "VerifiableCredential" + ], + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuanceDate": "2010-01-01T19:23:24Z", + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T20:04:36+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg" + } + } + } + ) + +VerifyCredentialRequest = IssueCredentialResponse() + +class VerifyCredentialResponse(Schema): + verified = fields.Bool( + metadata={ + "example": True + } + ) + document = fields.Dict( + metadata={ + "example": {} + } + ) + # results = fields.List( + # metadata={ + # "example": [{ + # "verified": True, + # "proof": {}, + # "purpose_result": { + # "valid": True, + # "controller": {} + # } + # }] + # } + # ) + +class ProvePresentationRequest(Schema): + presentation = fields.Dict( + metadata={ + "example": { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": [ + "VerifiablePresentation" + ], + "holder": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "verifiableCredential": [{ + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": [ + "VerifiableCredential" + ], + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuanceDate": "2010-01-01T19:23:24Z", + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T20:04:36+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg" + } + }] + } + } + ) + options = fields.Dict( + metadata={ + "example": {} + } + ) + +class ProvePresentationResponse(Schema): + verifiablePresentation = fields.Dict( + metadata={ + "example": { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": [ + "VerifiablePresentation" + ], + "holder": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "verifiableCredential": [ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "type": [ + "VerifiableCredential" + ], + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T18:33:31+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..6pZj4jcXbE4hCzdRYULsJO37A-19Od3ynLpZJsDB6tjDgYqrKhuOcbulE2yVCOwS8YSlpjO46F-c8a5NcVsXDQ" + } + } + ], + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T22:03:36+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..k55LG1o_-vcURKx8sSlAc7h_jtot3Zp18lukljF9B0esj1UL18hBBcunUoZxT9hT6zrFOGDPoQqpTHXj2a6QAw" + } + } + } + ) + +VerifyPresentationRequest = ProvePresentationResponse() + +class VerifyPresentationResponse(Schema): + verified = fields.Bool( + metadata={ + "example": True + } + ) + presentation_result = fields.Dict( + metadata={ + "example": { + "verified": True, + "document": {}, + } + } + ) + # credential_results = fields.List( + # metadata={ + # "example": [{ + # "verified": True, + # "document": {}, + # }] + # } + # ) \ No newline at end of file diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py new file mode 100644 index 0000000000..b2ffb0113f --- /dev/null +++ b/aries_cloudagent/vc_api/routes.py @@ -0,0 +1,187 @@ +"""VC-API Routes.""" + +from aiohttp import web +from aiohttp_apispec import docs, request_schema, response_schema + +from marshmallow import ValidationError, fields, validates_schema + +from uuid import uuid4 + +from ..admin.request_context import AdminRequestContext +from ..config.base import InjectionError +from ..resolver.base import ResolverError +from ..wallet.error import WalletError +from ..messaging.models.openapi import OpenAPISchema +from ..protocols.issue_credential.v2_0.manager import V20CredManager, V20CredManagerError +from ..protocols.issue_credential.v2_0.formats.ld_proof.handler import LDProofCredFormatHandler +from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError +from ..vc.ld_proofs import ( + CredentialIssuancePurpose, + ProofPurpose, + AssertionProofPurpose, + AuthenticationProofPurpose, +) +from ..vc.vc_ld.validation_result import ( + PresentationVerificationResultSchema, +) +from ..vc.vc_ld.models.credential import ( + CredentialSchema, + VerifiableCredential, + VerifiableCredentialSchema, +) +from ..vc.vc_ld.models.presentation import ( + PresentationSchema, + VerifiablePresentation, + VerifiablePresentationSchema, +) +from ..vc.vc_ld.models.options import ( + LDProofVCOptions, + LDProofVCOptionsSchema, + CredentialStatusOptionsSchema, +) +from ..vc.vc_ld.models.linked_data_proof import ( + LDProof, + LinkedDataProofSchema, +) +from .service import store_credential +from .tests import vcplayground_test_suite +from .examples import ( + IssueCredentialRequest, + IssueCredentialResponse, + VerifyCredentialRequest, + VerifyCredentialResponse, + ProvePresentationRequest, + ProvePresentationResponse, + VerifyPresentationRequest, + VerifyPresentationResponse, +) + +"""CREDENTIALS""" + +@docs(tags=["vc-api"], summary="Issue a credential") +@request_schema(IssueCredentialRequest) +@response_schema(IssueCredentialResponse, 201) +async def issue_credential(request: web.BaseRequest): + context: AdminRequestContext = request["context"] + body = await request.json() + credential = VerifiableCredential.deserialize(body["credential"]) + options = {"proofType": "Ed25519Signature2018"} + options = LDProofVCOptions.deserialize(options) + try: + manager = VcLdpManager(context.profile) + vc = await manager.issue(credential, options) + except VcLdpManagerError as err: + return web.json_response({"message": str(err)}, status=400) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return web.json_response({"verifiableCredential": vc.serialize()}, status=201) + +# @docs(tags=["vc-api"], summary="Store a credential") +# async def store_credential(request: web.BaseRequest): +# context: AdminRequestContext = request["context"] +# body = await request.json() +# vc = VerifiableCredential.deserialize(body["verifiableCredential"]) +# options = LDProofVCOptions.deserialize(body["options"]) + +# try: +# manager = V20CredManager(context.profile) +# await store_credential(manager, context.profile, vc) +# except V20CredManagerError as err: +# return web.json_response({"error": str(err)}, status=400) +# except (WalletError, InjectionError): +# raise web.HTTPForbidden(reason="Bad credential") +# return web.json_response({"message": "Credential stored"}, status=200) + + +@docs(tags=["vc-api"], summary="Verify a credential") +@request_schema(VerifyCredentialRequest) +@response_schema(VerifyCredentialResponse, 200) +async def verify_credential(request: web.BaseRequest): + context: AdminRequestContext = request["context"] + body = await request.json() + vc = VerifiableCredential.deserialize(body.get("verifiableCredential")) + try: + manager = VcLdpManager(context.profile) + result = await manager.verify_credential(vc) + return web.json_response(result.serialize()) + except (VcLdpManagerError, ResolverError, ValueError) as error: + raise web.HTTPBadRequest(reason=str(error)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + + + +"""PRESENTATIONS""" + +@docs(tags=["vc-api"], summary="Prove a presentation") +@request_schema(ProvePresentationRequest) +@response_schema(ProvePresentationResponse, 201) +async def prove_presentation(request: web.BaseRequest): + context: AdminRequestContext = request["context"] + body = await request.json() + presentation = VerifiablePresentation.deserialize(body["presentation"]) + options = {"proofType": "Ed25519Signature2018"} + options = LDProofVCOptions.deserialize(options) + + try: + manager = VcLdpManager(context.profile) + vp = await manager.prove(presentation, options) + except VcLdpManagerError as err: + return web.json_response({"error": str(err)}, status=400) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return web.json_response({"verifiablePresentation": vp.serialize()}, status=201) + + +@docs(tags=["vc-api"], summary="Verify a presentation") +@request_schema(VerifyPresentationRequest) +@response_schema(VerifyPresentationResponse, 201) +async def verify_presentation(request: web.BaseRequest): + context: AdminRequestContext = request["context"] + body = await request.json() + vp = VerifiablePresentation.deserialize(body.get("verifiablePresentation")) + options = {"challenge": str(uuid4())} + options = LDProofVCOptions.deserialize(options) + try: + manager = VcLdpManager(context.profile) + + # # TODO: improve the purpose selection + # purpose = AssertionProofPurpose() + result = await manager.verify_presentation(vp, options) + return web.json_response(result.serialize()) + except (VcLdpManagerError, ResolverError, ValueError) as error: + raise web.HTTPBadRequest(reason=str(error)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + + + +async def register(app: web.Application): + """Register routes.""" + + app.add_routes( + [ + web.post("/credentials/issue", issue_credential), + # web.post("/credentials/store", store_credential), + web.post("/credentials/verify", verify_credential), + web.post("/presentations/prove", prove_presentation), + web.post("/presentations/verify", verify_presentation), + ] + ) + + +def post_process_routes(app: web.Application): + """Amend swagger API.""" + # Add top-level tags description + if "tags" not in app._state["swagger_dict"]: + app._state["swagger_dict"]["tags"] = [] + app._state["swagger_dict"]["tags"].append( + { + "name": "vc-api", + "description": "Manage W3C credentials and presentations", + "externalDocs": { + "description": "Specification", + "url": "https://w3c-ccg.github.io/vc-api", + }, + } + ) \ No newline at end of file diff --git a/open-api/openapi.json b/open-api/openapi.json index 24b5192062..ea48b0c585 100644 --- a/open-api/openapi.json +++ b/open-api/openapi.json @@ -96,6 +96,13 @@ "url" : "https://www.w3.org/TR/vc-data-model/" }, "name" : "ldp-vc" + }, { + "description" : "Manage credentials and presentations", + "externalDocs" : { + "description" : "Specification", + "url" : "https://w3c-ccg.github.io/vc-api" + }, + "name" : "vc-api" }, { "description" : "Interaction with ledger", "externalDocs" : { diff --git a/open-api/swagger.json b/open-api/swagger.json index b8ed3fd87a..96f6acf509 100644 --- a/open-api/swagger.json +++ b/open-api/swagger.json @@ -90,6 +90,13 @@ "description" : "Specification", "url" : "https://www.w3.org/TR/vc-data-model/" } + }, { + "description" : "Manage credentials and presentations", + "externalDocs" : { + "description" : "Specification", + "url" : "https://w3c-ccg.github.io/vc-api" + }, + "name" : "vc-api" }, { "name" : "ledger", "description" : "Interaction with ledger", From 56edbc3c1a3dbbcb48cdba6d7a07e00524f7a45a Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 17:00:17 +0000 Subject: [PATCH 03/26] enabled assertionMethod purpose for verifying presentation Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/manager.py | 21 +++++-- .../vc/vc_ld/models/credential.py | 8 +++ .../vc/vc_ld/models/presentation.py | 16 +---- .../vc_api/{example.py => examples.py} | 0 aries_cloudagent/vc_api/routes.py | 59 +++++-------------- 5 files changed, 41 insertions(+), 63 deletions(-) rename aries_cloudagent/vc_api/{example.py => examples.py} (100%) diff --git a/aries_cloudagent/vc/vc_ld/manager.py b/aries_cloudagent/vc/vc_ld/manager.py index 9e584c52ca..a23e785097 100644 --- a/aries_cloudagent/vc/vc_ld/manager.py +++ b/aries_cloudagent/vc/vc_ld/manager.py @@ -17,6 +17,7 @@ from ..ld_proofs.document_loader import DocumentLoader from ..ld_proofs.purposes.authentication_proof_purpose import AuthenticationProofPurpose from ..ld_proofs.purposes.credential_issuance_purpose import CredentialIssuancePurpose +from ..ld_proofs.purposes.assertion_proof_purpose import AssertionProofPurpose from ..ld_proofs.purposes.proof_purpose import ProofPurpose from ..ld_proofs.suites.bbs_bls_signature_2020 import BbsBlsSignature2020 from ..ld_proofs.suites.bbs_bls_signature_proof_2020 import BbsBlsSignatureProof2020 @@ -267,7 +268,7 @@ async def prepare_credential( return credential - async def _get_suite_for_document( + async def _get_signature_suite( self, document: Union[VerifiableCredential, VerifiablePresentation], options: LDProofVCOptions ) -> LinkedDataProof: document_type = document.type[0] @@ -336,7 +337,7 @@ async def issue( credential = await self.prepare_credential(credential, options) # Get signature suite, proof purpose and document loader - suite = await self._get_suite_for_credential(credential, options) + suite = await self._get_signature_suite(credential, options) proof_purpose = self._get_proof_purpose( proof_purpose=options.proof_purpose, challenge=options.challenge, @@ -356,10 +357,9 @@ async def prove( self, presentation: VerifiablePresentation, options: LDProofVCOptions ) -> VerifiablePresentation: """Sign a VP with a Linked Data Proof.""" - presentation = await self.prepare_presentation(presentation, options) # Get signature suite, proof purpose and document loader - suite = await self._get_suite_for_document(presentation, options) + suite = await self._get_signature_suite(presentation, options) proof_purpose = self._get_proof_purpose( proof_purpose=options.proof_purpose, challenge=options.challenge, @@ -379,7 +379,17 @@ async def verify_presentation( self, vp: VerifiablePresentation, options: LDProofVCOptions ) -> PresentationVerificationResult: """Verify a VP with a Linked Data Proof.""" - if not options.challenge: + + if vp.proof.proof_purpose == 'assertionMethod': + purpose = AssertionProofPurpose() + return await verify_presentation( + presentation=vp.serialize(), + suites=await self._get_all_suites(), + document_loader=self.profile.inject(DocumentLoader), + purpose=purpose, + ) + + elif not options.challenge: raise VcLdpManagerError("Challenge is required for verifying a VP") return await verify_presentation( @@ -387,6 +397,7 @@ async def verify_presentation( suites=await self._get_all_suites(), document_loader=self.profile.inject(DocumentLoader), challenge=options.challenge, + purpose=purpose, ) async def verify_credential( diff --git a/aries_cloudagent/vc/vc_ld/models/credential.py b/aries_cloudagent/vc/vc_ld/models/credential.py index 101568a687..76945a88b6 100644 --- a/aries_cloudagent/vc/vc_ld/models/credential.py +++ b/aries_cloudagent/vc/vc_ld/models/credential.py @@ -47,6 +47,7 @@ def __init__( issuance_date: Optional[str] = None, expiration_date: Optional[str] = None, credential_subject: Optional[Union[dict, List[dict]]] = None, + credential_status: Optional[Union[dict, List[dict]]] = None, proof: Optional[Union[dict, LDProof]] = None, **kwargs, ) -> None: @@ -56,6 +57,7 @@ def __init__( self._type = type or [VERIFIABLE_CREDENTIAL_TYPE] self._issuer = issuer self._credential_subject = credential_subject + self._credential_status = credential_status # TODO: proper date parsing self._issuance_date = issuance_date @@ -232,6 +234,11 @@ def credential_subject(self, credential_subject: Union[dict, List[dict]]): self._credential_subject = credential_subject + @property + def credential_status(self): + """Getter for credential status.""" + return self._credential_status + @property def proof(self): """Getter for proof.""" @@ -253,6 +260,7 @@ def __eq__(self, o: object) -> bool: and self.issuance_date == o.issuance_date and self.expiration_date == o.expiration_date and self.credential_subject == o.credential_subject + and self.credential_status == o.credential_status and self.proof == o.proof and self.extra == o.extra ) diff --git a/aries_cloudagent/vc/vc_ld/models/presentation.py b/aries_cloudagent/vc/vc_ld/models/presentation.py index 1a91b922ce..298a7b1688 100644 --- a/aries_cloudagent/vc/vc_ld/models/presentation.py +++ b/aries_cloudagent/vc/vc_ld/models/presentation.py @@ -1,21 +1,11 @@ """Verifiable Presentation model.""" -from typing import List, Optional, Sequence, Union +from typing import List, Optional, Union from marshmallow import INCLUDE, ValidationError, fields, post_dump from ....messaging.models.base import BaseModel, BaseModelSchema from ....messaging.valid import ( - UUID4_EXAMPLE, - UUID4_VALIDATE, - CREDENTIAL_CONTEXT_EXAMPLE, CREDENTIAL_CONTEXT_VALIDATE, - CREDENTIAL_SUBJECT_EXAMPLE, - CREDENTIAL_SUBJECT_VALIDATE, - CREDENTIAL_TYPE_EXAMPLE, - CREDENTIAL_TYPE_VALIDATE, - RFC3339_DATETIME_EXAMPLE, - RFC3339_DATETIME_VALIDATE, - DictOrDictListField, DIDKey, StrOrDictField, Uri, @@ -24,12 +14,8 @@ from ...ld_proofs.constants import ( CREDENTIALS_CONTEXT_V1_URL, VERIFIABLE_PRESENTATION_TYPE, - VERIFIABLE_CREDENTIAL_TYPE, ) from .linked_data_proof import LDProof, LinkedDataProofSchema -from .credential import ( - VerifiableCredential -) class VerifiablePresentation(BaseModel): diff --git a/aries_cloudagent/vc_api/example.py b/aries_cloudagent/vc_api/examples.py similarity index 100% rename from aries_cloudagent/vc_api/example.py rename to aries_cloudagent/vc_api/examples.py diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index b2ffb0113f..8c6925b2b4 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -3,48 +3,16 @@ from aiohttp import web from aiohttp_apispec import docs, request_schema, response_schema -from marshmallow import ValidationError, fields, validates_schema - -from uuid import uuid4 - from ..admin.request_context import AdminRequestContext from ..config.base import InjectionError from ..resolver.base import ResolverError from ..wallet.error import WalletError -from ..messaging.models.openapi import OpenAPISchema -from ..protocols.issue_credential.v2_0.manager import V20CredManager, V20CredManagerError -from ..protocols.issue_credential.v2_0.formats.ld_proof.handler import LDProofCredFormatHandler +# from ..protocols.issue_credential.v2_0.manager import V20CredManager, V20CredManagerError +# from ..protocols.issue_credential.v2_0.formats.ld_proof.handler import LDProofCredFormatHandler from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError -from ..vc.ld_proofs import ( - CredentialIssuancePurpose, - ProofPurpose, - AssertionProofPurpose, - AuthenticationProofPurpose, -) -from ..vc.vc_ld.validation_result import ( - PresentationVerificationResultSchema, -) -from ..vc.vc_ld.models.credential import ( - CredentialSchema, - VerifiableCredential, - VerifiableCredentialSchema, -) -from ..vc.vc_ld.models.presentation import ( - PresentationSchema, - VerifiablePresentation, - VerifiablePresentationSchema, -) -from ..vc.vc_ld.models.options import ( - LDProofVCOptions, - LDProofVCOptionsSchema, - CredentialStatusOptionsSchema, -) -from ..vc.vc_ld.models.linked_data_proof import ( - LDProof, - LinkedDataProofSchema, -) -from .service import store_credential -from .tests import vcplayground_test_suite +from ..vc.vc_ld.models.credential import VerifiableCredential +from ..vc.vc_ld.models.presentation import VerifiablePresentation +from ..vc.vc_ld.models.options import LDProofVCOptions from .examples import ( IssueCredentialRequest, IssueCredentialResponse, @@ -65,7 +33,10 @@ async def issue_credential(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() credential = VerifiableCredential.deserialize(body["credential"]) - options = {"proofType": "Ed25519Signature2018"} + + options = {} if 'options' not in body else body['options'] + # Default to Ed25519Signature2018 if no proof type was provided + options['proofType'] = "Ed25519Signature2018" if 'proofType' not in options else options['proofType'] options = LDProofVCOptions.deserialize(options) try: manager = VcLdpManager(context.profile) @@ -120,7 +91,10 @@ async def prove_presentation(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() presentation = VerifiablePresentation.deserialize(body["presentation"]) - options = {"proofType": "Ed25519Signature2018"} + + options = {} if 'options' not in body else body['options'] + # Default to Ed25519Signature2018 if no proof type was provided + options['proofType'] = "Ed25519Signature2018" if 'proofType' not in options else options['proofType'] options = LDProofVCOptions.deserialize(options) try: @@ -140,13 +114,12 @@ async def verify_presentation(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() vp = VerifiablePresentation.deserialize(body.get("verifiablePresentation")) - options = {"challenge": str(uuid4())} + + options = {} if 'options' not in body else body['options'] options = LDProofVCOptions.deserialize(options) try: manager = VcLdpManager(context.profile) - - # # TODO: improve the purpose selection - # purpose = AssertionProofPurpose() + result = await manager.verify_presentation(vp, options) return web.json_response(result.serialize()) except (VcLdpManagerError, ResolverError, ValueError) as error: From 7ad285e13603767c5a71250c41438d73f997a6d5 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 17:13:33 +0000 Subject: [PATCH 04/26] fix linting Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/manager.py | 16 +- .../vc/vc_ld/models/presentation.py | 5 +- aries_cloudagent/vc_api/examples.py | 192 +++++++----------- aries_cloudagent/vc_api/routes.py | 32 +-- 4 files changed, 110 insertions(+), 135 deletions(-) diff --git a/aries_cloudagent/vc/vc_ld/manager.py b/aries_cloudagent/vc/vc_ld/manager.py index a23e785097..ec24898a84 100644 --- a/aries_cloudagent/vc/vc_ld/manager.py +++ b/aries_cloudagent/vc/vc_ld/manager.py @@ -269,15 +269,17 @@ async def prepare_credential( return credential async def _get_signature_suite( - self, document: Union[VerifiableCredential, VerifiablePresentation], options: LDProofVCOptions + self, + document: Union[VerifiableCredential, VerifiablePresentation], + options: LDProofVCOptions, ) -> LinkedDataProof: document_type = document.type[0] - - if document_type == 'VerifiableCredential': + + if document_type == "VerifiableCredential": issuer_id = document.issuer_id - if document_type == 'VerifiablePresentation': + if document_type == "VerifiablePresentation": issuer_id = document.holder_id - + proof_type = options.proof_type if not issuer_id: @@ -379,8 +381,8 @@ async def verify_presentation( self, vp: VerifiablePresentation, options: LDProofVCOptions ) -> PresentationVerificationResult: """Verify a VP with a Linked Data Proof.""" - - if vp.proof.proof_purpose == 'assertionMethod': + + if vp.proof.proof_purpose == "assertionMethod": purpose = AssertionProofPurpose() return await verify_presentation( presentation=vp.serialize(), diff --git a/aries_cloudagent/vc/vc_ld/models/presentation.py b/aries_cloudagent/vc/vc_ld/models/presentation.py index 298a7b1688..fd52127794 100644 --- a/aries_cloudagent/vc/vc_ld/models/presentation.py +++ b/aries_cloudagent/vc/vc_ld/models/presentation.py @@ -10,7 +10,7 @@ StrOrDictField, Uri, UriOrDictField, - ) +) from ...ld_proofs.constants import ( CREDENTIALS_CONTEXT_V1_URL, VERIFIABLE_PRESENTATION_TYPE, @@ -274,6 +274,7 @@ def add_unknown_properties(self, data: dict, original, **kwargs): return data + class VerifiablePresentationSchema(PresentationSchema): """Single Verifiable Presentation Schema.""" @@ -296,4 +297,4 @@ class VerifiablePresentationSchema(PresentationSchema): ), }, }, - ) \ No newline at end of file + ) diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 49802652a8..4ecd729cb7 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -1,68 +1,52 @@ from marshmallow import Schema, fields + class IssueCredentialRequest(Schema): credential = fields.Dict( metadata={ "example": { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" - }, - "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "type": [ - "VerifiableCredential" - ] - } - } - ) - options = fields.Dict( - metadata={ - "example": {} + "@context": ["https://www.w3.org/2018/credentials/v1"], + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "type": ["VerifiableCredential"], + } } ) + options = fields.Dict(metadata={"example": {}}) + class IssueCredentialResponse(Schema): verifiableCredential = fields.Dict( metadata={ "example": { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": [ - "VerifiableCredential" - ], - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" - }, - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "created": "2024-01-14T20:04:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg" - } - } + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiableCredential"], + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuanceDate": "2010-01-01T19:23:24Z", + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T20:04:36+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", + }, + } } ) + VerifyCredentialRequest = IssueCredentialResponse() + class VerifyCredentialResponse(Schema): - verified = fields.Bool( - metadata={ - "example": True - } - ) - document = fields.Dict( - metadata={ - "example": {} - } - ) + verified = fields.Bool(metadata={"example": True}) + document = fields.Dict(metadata={"example": {}}) # results = fields.List( # metadata={ # "example": [{ @@ -76,98 +60,80 @@ class VerifyCredentialResponse(Schema): # } # ) + class ProvePresentationRequest(Schema): presentation = fields.Dict( metadata={ "example": { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": [ - "VerifiablePresentation" - ], + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiablePresentation"], "holder": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "verifiableCredential": [{ - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": [ - "VerifiableCredential" - ], - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" - }, - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "created": "2024-01-14T20:04:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg" + "verifiableCredential": [ + { + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiableCredential"], + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuanceDate": "2010-01-01T19:23:24Z", + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T20:04:36+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", + }, } - }] + ], } } ) - options = fields.Dict( - metadata={ - "example": {} - } - ) + options = fields.Dict(metadata={"example": {}}) + class ProvePresentationResponse(Schema): verifiablePresentation = fields.Dict( metadata={ "example": { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": [ - "VerifiablePresentation" - ], + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiablePresentation"], "holder": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" - }, - "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "type": [ - "VerifiableCredential" - ], - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "created": "2024-01-14T18:33:31+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..6pZj4jcXbE4hCzdRYULsJO37A-19Od3ynLpZJsDB6tjDgYqrKhuOcbulE2yVCOwS8YSlpjO46F-c8a5NcVsXDQ" + { + "@context": ["https://www.w3.org/2018/credentials/v1"], + "credentialSubject": { + "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + }, + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "type": ["VerifiableCredential"], + "proof": { + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T18:33:31+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..6pZj4jcXbE4hCzdRYULsJO37A-19Od3ynLpZJsDB6tjDgYqrKhuOcbulE2yVCOwS8YSlpjO46F-c8a5NcVsXDQ", + }, } - } ], "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", - "created": "2024-01-14T22:03:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..k55LG1o_-vcURKx8sSlAc7h_jtot3Zp18lukljF9B0esj1UL18hBBcunUoZxT9hT6zrFOGDPoQqpTHXj2a6QAw" - } + "type": "Ed25519Signature2018", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "created": "2024-01-14T22:03:36+00:00", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..k55LG1o_-vcURKx8sSlAc7h_jtot3Zp18lukljF9B0esj1UL18hBBcunUoZxT9hT6zrFOGDPoQqpTHXj2a6QAw", + }, } } ) + VerifyPresentationRequest = ProvePresentationResponse() + class VerifyPresentationResponse(Schema): - verified = fields.Bool( - metadata={ - "example": True - } - ) + verified = fields.Bool(metadata={"example": True}) presentation_result = fields.Dict( metadata={ "example": { @@ -183,4 +149,4 @@ class VerifyPresentationResponse(Schema): # "document": {}, # }] # } - # ) \ No newline at end of file + # ) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index 8c6925b2b4..fe041780e2 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -7,6 +7,7 @@ from ..config.base import InjectionError from ..resolver.base import ResolverError from ..wallet.error import WalletError + # from ..protocols.issue_credential.v2_0.manager import V20CredManager, V20CredManagerError # from ..protocols.issue_credential.v2_0.formats.ld_proof.handler import LDProofCredFormatHandler from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError @@ -26,6 +27,7 @@ """CREDENTIALS""" + @docs(tags=["vc-api"], summary="Issue a credential") @request_schema(IssueCredentialRequest) @response_schema(IssueCredentialResponse, 201) @@ -33,10 +35,12 @@ async def issue_credential(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() credential = VerifiableCredential.deserialize(body["credential"]) - - options = {} if 'options' not in body else body['options'] + + options = {} if "options" not in body else body["options"] # Default to Ed25519Signature2018 if no proof type was provided - options['proofType'] = "Ed25519Signature2018" if 'proofType' not in options else options['proofType'] + options["proofType"] = ( + "Ed25519Signature2018" if "proofType" not in options else options["proofType"] + ) options = LDProofVCOptions.deserialize(options) try: manager = VcLdpManager(context.profile) @@ -47,13 +51,14 @@ async def issue_credential(request: web.BaseRequest): raise web.HTTPForbidden(reason="No wallet available") return web.json_response({"verifiableCredential": vc.serialize()}, status=201) + # @docs(tags=["vc-api"], summary="Store a credential") # async def store_credential(request: web.BaseRequest): # context: AdminRequestContext = request["context"] # body = await request.json() # vc = VerifiableCredential.deserialize(body["verifiableCredential"]) # options = LDProofVCOptions.deserialize(body["options"]) - + # try: # manager = V20CredManager(context.profile) # await store_credential(manager, context.profile, vc) @@ -81,9 +86,9 @@ async def verify_credential(request: web.BaseRequest): raise web.HTTPForbidden(reason="No wallet available") - """PRESENTATIONS""" + @docs(tags=["vc-api"], summary="Prove a presentation") @request_schema(ProvePresentationRequest) @response_schema(ProvePresentationResponse, 201) @@ -91,10 +96,12 @@ async def prove_presentation(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() presentation = VerifiablePresentation.deserialize(body["presentation"]) - - options = {} if 'options' not in body else body['options'] + + options = {} if "options" not in body else body["options"] # Default to Ed25519Signature2018 if no proof type was provided - options['proofType'] = "Ed25519Signature2018" if 'proofType' not in options else options['proofType'] + options["proofType"] = ( + "Ed25519Signature2018" if "proofType" not in options else options["proofType"] + ) options = LDProofVCOptions.deserialize(options) try: @@ -114,12 +121,12 @@ async def verify_presentation(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() vp = VerifiablePresentation.deserialize(body.get("verifiablePresentation")) - - options = {} if 'options' not in body else body['options'] + + options = {} if "options" not in body else body["options"] options = LDProofVCOptions.deserialize(options) try: manager = VcLdpManager(context.profile) - + result = await manager.verify_presentation(vp, options) return web.json_response(result.serialize()) except (VcLdpManagerError, ResolverError, ValueError) as error: @@ -128,7 +135,6 @@ async def verify_presentation(request: web.BaseRequest): raise web.HTTPForbidden(reason="No wallet available") - async def register(app: web.Application): """Register routes.""" @@ -157,4 +163,4 @@ def post_process_routes(app: web.Application): "url": "https://w3c-ccg.github.io/vc-api", }, } - ) \ No newline at end of file + ) From 896262537065d5c25026d4a37b25ed9e95c31406 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 17:20:49 +0000 Subject: [PATCH 05/26] add docstring Signed-off-by: pstlouis --- aries_cloudagent/vc_api/routes.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index fe041780e2..17d0bd1346 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -32,6 +32,12 @@ @request_schema(IssueCredentialRequest) @response_schema(IssueCredentialResponse, 201) async def issue_credential(request: web.BaseRequest): + """Request handler for signing a jsonld doc. + + Args: + request: aiohttp request object + + """ context: AdminRequestContext = request["context"] body = await request.json() credential = VerifiableCredential.deserialize(body["credential"]) @@ -54,6 +60,12 @@ async def issue_credential(request: web.BaseRequest): # @docs(tags=["vc-api"], summary="Store a credential") # async def store_credential(request: web.BaseRequest): + # """Request handler for storing a jsonld doc. + + # Args: + # request: aiohttp request object + + # """ # context: AdminRequestContext = request["context"] # body = await request.json() # vc = VerifiableCredential.deserialize(body["verifiableCredential"]) @@ -73,6 +85,12 @@ async def issue_credential(request: web.BaseRequest): @request_schema(VerifyCredentialRequest) @response_schema(VerifyCredentialResponse, 200) async def verify_credential(request: web.BaseRequest): + """Request handler for verifying a jsonld doc. + + Args: + request: aiohttp request object + + """ context: AdminRequestContext = request["context"] body = await request.json() vc = VerifiableCredential.deserialize(body.get("verifiableCredential")) @@ -93,6 +111,12 @@ async def verify_credential(request: web.BaseRequest): @request_schema(ProvePresentationRequest) @response_schema(ProvePresentationResponse, 201) async def prove_presentation(request: web.BaseRequest): + """Request handler for signing a jsonld doc. + + Args: + request: aiohttp request object + + """ context: AdminRequestContext = request["context"] body = await request.json() presentation = VerifiablePresentation.deserialize(body["presentation"]) @@ -118,6 +142,12 @@ async def prove_presentation(request: web.BaseRequest): @request_schema(VerifyPresentationRequest) @response_schema(VerifyPresentationResponse, 201) async def verify_presentation(request: web.BaseRequest): + """Request handler for verifying a jsonld doc. + + Args: + request: aiohttp request object + + """ context: AdminRequestContext = request["context"] body = await request.json() vp = VerifiablePresentation.deserialize(body.get("verifiablePresentation")) From 84f8a81a08bab01f74b4ecd2180029fce87d316a Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 17:21:58 +0000 Subject: [PATCH 06/26] linting Signed-off-by: pstlouis --- aries_cloudagent/vc_api/routes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index 17d0bd1346..75cab085f0 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -60,12 +60,12 @@ async def issue_credential(request: web.BaseRequest): # @docs(tags=["vc-api"], summary="Store a credential") # async def store_credential(request: web.BaseRequest): - # """Request handler for storing a jsonld doc. +# """Request handler for storing a jsonld doc. - # Args: - # request: aiohttp request object +# Args: +# request: aiohttp request object - # """ +# """ # context: AdminRequestContext = request["context"] # body = await request.json() # vc = VerifiableCredential.deserialize(body["verifiableCredential"]) From 78a44a32b49a01ab6fc8efd7eea2bbeefceabb57 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 19:10:02 +0000 Subject: [PATCH 07/26] fix code lenght & change manager context injection Signed-off-by: pstlouis --- .../vc/vc_ld/models/presentation.py | 2 -- aries_cloudagent/vc_api/routes.py | 34 +++---------------- 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/aries_cloudagent/vc/vc_ld/models/presentation.py b/aries_cloudagent/vc/vc_ld/models/presentation.py index fd52127794..205bc5a2a7 100644 --- a/aries_cloudagent/vc/vc_ld/models/presentation.py +++ b/aries_cloudagent/vc/vc_ld/models/presentation.py @@ -153,8 +153,6 @@ def verifiable_credential(self): def verifiable_credential(self, verifiable_credential: List[dict]): """Setter for verifiable credential.""" - uri_validator = Uri() - self._verifiable_credential = verifiable_credential @property diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index 75cab085f0..4357f8899c 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -8,8 +8,6 @@ from ..resolver.base import ResolverError from ..wallet.error import WalletError -# from ..protocols.issue_credential.v2_0.manager import V20CredManager, V20CredManagerError -# from ..protocols.issue_credential.v2_0.formats.ld_proof.handler import LDProofCredFormatHandler from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError from ..vc.vc_ld.models.credential import VerifiableCredential from ..vc.vc_ld.models.presentation import VerifiablePresentation @@ -49,7 +47,7 @@ async def issue_credential(request: web.BaseRequest): ) options = LDProofVCOptions.deserialize(options) try: - manager = VcLdpManager(context.profile) + manager = context.inject(VcLdpManager) vc = await manager.issue(credential, options) except VcLdpManagerError as err: return web.json_response({"message": str(err)}, status=400) @@ -58,29 +56,6 @@ async def issue_credential(request: web.BaseRequest): return web.json_response({"verifiableCredential": vc.serialize()}, status=201) -# @docs(tags=["vc-api"], summary="Store a credential") -# async def store_credential(request: web.BaseRequest): -# """Request handler for storing a jsonld doc. - -# Args: -# request: aiohttp request object - -# """ -# context: AdminRequestContext = request["context"] -# body = await request.json() -# vc = VerifiableCredential.deserialize(body["verifiableCredential"]) -# options = LDProofVCOptions.deserialize(body["options"]) - -# try: -# manager = V20CredManager(context.profile) -# await store_credential(manager, context.profile, vc) -# except V20CredManagerError as err: -# return web.json_response({"error": str(err)}, status=400) -# except (WalletError, InjectionError): -# raise web.HTTPForbidden(reason="Bad credential") -# return web.json_response({"message": "Credential stored"}, status=200) - - @docs(tags=["vc-api"], summary="Verify a credential") @request_schema(VerifyCredentialRequest) @response_schema(VerifyCredentialResponse, 200) @@ -95,7 +70,7 @@ async def verify_credential(request: web.BaseRequest): body = await request.json() vc = VerifiableCredential.deserialize(body.get("verifiableCredential")) try: - manager = VcLdpManager(context.profile) + manager = context.inject(VcLdpManager) result = await manager.verify_credential(vc) return web.json_response(result.serialize()) except (VcLdpManagerError, ResolverError, ValueError) as error: @@ -129,7 +104,7 @@ async def prove_presentation(request: web.BaseRequest): options = LDProofVCOptions.deserialize(options) try: - manager = VcLdpManager(context.profile) + manager = context.inject(VcLdpManager) vp = await manager.prove(presentation, options) except VcLdpManagerError as err: return web.json_response({"error": str(err)}, status=400) @@ -155,7 +130,7 @@ async def verify_presentation(request: web.BaseRequest): options = {} if "options" not in body else body["options"] options = LDProofVCOptions.deserialize(options) try: - manager = VcLdpManager(context.profile) + manager = context.inject(VcLdpManager) result = await manager.verify_presentation(vp, options) return web.json_response(result.serialize()) @@ -171,7 +146,6 @@ async def register(app: web.Application): app.add_routes( [ web.post("/credentials/issue", issue_credential), - # web.post("/credentials/store", store_credential), web.post("/credentials/verify", verify_credential), web.post("/presentations/prove", prove_presentation), web.post("/presentations/verify", verify_presentation), From 074e53b2405035c9beebce8a2110d6a39be39e1e Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 19:23:50 +0000 Subject: [PATCH 08/26] add missing docstring Signed-off-by: pstlouis --- .../vc/vc_ld/models/presentation.py | 4 +-- aries_cloudagent/vc_api/examples.py | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/aries_cloudagent/vc/vc_ld/models/presentation.py b/aries_cloudagent/vc/vc_ld/models/presentation.py index 205bc5a2a7..2fee51c5de 100644 --- a/aries_cloudagent/vc/vc_ld/models/presentation.py +++ b/aries_cloudagent/vc/vc_ld/models/presentation.py @@ -225,7 +225,7 @@ class Meta: ) holder = StrOrDictField( - required=True, + required=False, metadata={ "description": ( "The JSON-LD Verifiable Credential Holder. Either string of object with" @@ -237,7 +237,7 @@ class Meta: verifiable_credential = fields.List( fields.Dict(required=True), - required=True, + required=False, data_key="verifiableCredential", # validate=VERIFIABLE_CREDENTIAL_VALIDATE, metadata={}, diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 4ecd729cb7..330379166c 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -2,6 +2,11 @@ class IssueCredentialRequest(Schema): + """Issue credential request. + + Based on https://w3c-ccg.github.io/vc-api/#issue-credential + + """ credential = fields.Dict( metadata={ "example": { @@ -19,6 +24,11 @@ class IssueCredentialRequest(Schema): class IssueCredentialResponse(Schema): + """Issue credential response. + + Based on https://w3c-ccg.github.io/vc-api/#issue-credential + + """ verifiableCredential = fields.Dict( metadata={ "example": { @@ -45,6 +55,11 @@ class IssueCredentialResponse(Schema): class VerifyCredentialResponse(Schema): + """Verify credential response. + + Based on https://w3c-ccg.github.io/vc-api/#verify-credential + + """ verified = fields.Bool(metadata={"example": True}) document = fields.Dict(metadata={"example": {}}) # results = fields.List( @@ -62,6 +77,11 @@ class VerifyCredentialResponse(Schema): class ProvePresentationRequest(Schema): + """Prove presentation request. + + Based on https://w3c-ccg.github.io/vc-api/#prove-presentation + + """ presentation = fields.Dict( metadata={ "example": { @@ -93,6 +113,11 @@ class ProvePresentationRequest(Schema): class ProvePresentationResponse(Schema): + """Prove presentation response. + + Based on https://w3c-ccg.github.io/vc-api/#prove-presentation + + """ verifiablePresentation = fields.Dict( metadata={ "example": { @@ -133,6 +158,11 @@ class ProvePresentationResponse(Schema): class VerifyPresentationResponse(Schema): + """Verify presentation response. + + Based on https://w3c-ccg.github.io/vc-api/#verify-presentation + + """ verified = fields.Bool(metadata={"example": True}) presentation_result = fields.Dict( metadata={ From 563ddebc78767ba990f9a9dd6f560fde7c920bce Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 19:25:32 +0000 Subject: [PATCH 09/26] linting Signed-off-by: pstlouis --- aries_cloudagent/vc_api/examples.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 330379166c..787f0cc4d9 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -7,6 +7,7 @@ class IssueCredentialRequest(Schema): Based on https://w3c-ccg.github.io/vc-api/#issue-credential """ + credential = fields.Dict( metadata={ "example": { @@ -29,6 +30,7 @@ class IssueCredentialResponse(Schema): Based on https://w3c-ccg.github.io/vc-api/#issue-credential """ + verifiableCredential = fields.Dict( metadata={ "example": { @@ -60,6 +62,7 @@ class VerifyCredentialResponse(Schema): Based on https://w3c-ccg.github.io/vc-api/#verify-credential """ + verified = fields.Bool(metadata={"example": True}) document = fields.Dict(metadata={"example": {}}) # results = fields.List( @@ -82,6 +85,7 @@ class ProvePresentationRequest(Schema): Based on https://w3c-ccg.github.io/vc-api/#prove-presentation """ + presentation = fields.Dict( metadata={ "example": { @@ -118,6 +122,7 @@ class ProvePresentationResponse(Schema): Based on https://w3c-ccg.github.io/vc-api/#prove-presentation """ + verifiablePresentation = fields.Dict( metadata={ "example": { @@ -163,6 +168,7 @@ class VerifyPresentationResponse(Schema): Based on https://w3c-ccg.github.io/vc-api/#verify-presentation """ + verified = fields.Bool(metadata={"example": True}) presentation_result = fields.Dict( metadata={ From d195077d264a901214bb6c35c8bc278b73b3dd4a Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 19:39:25 +0000 Subject: [PATCH 10/26] shorter lines in examples Signed-off-by: pstlouis --- aries_cloudagent/vc_api/examples.py | 42 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 787f0cc4d9..97479f8bcd 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -1,5 +1,7 @@ from marshmallow import Schema, fields +SUBJECT_DID = 'did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i' +ISSUER_DID = 'did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i' class IssueCredentialRequest(Schema): """Issue credential request. @@ -13,10 +15,10 @@ class IssueCredentialRequest(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + "id": SUBJECT_DID }, "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuer": ISSUER_DID, "type": ["VerifiableCredential"], } } @@ -36,17 +38,18 @@ class IssueCredentialResponse(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential"], - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuer": ISSUER_DID, "issuanceDate": "2010-01-01T19:23:24Z", "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + "id": SUBJECT_DID }, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', "created": "2024-01-14T20:04:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ + Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", }, } } @@ -91,22 +94,23 @@ class ProvePresentationRequest(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], - "holder": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "holder": ISSUER_DID, "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential"], - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuer": ISSUER_DID, "issuanceDate": "2010-01-01T19:23:24Z", "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + "id": SUBJECT_DID }, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', "created": "2024-01-14T20:04:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ + Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", }, } ], @@ -128,31 +132,33 @@ class ProvePresentationResponse(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], - "holder": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "holder": ISSUER_DID, "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], "credentialSubject": { - "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" + "id": SUBJECT_DID }, "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "issuer": ISSUER_DID, "type": ["VerifiableCredential"], "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', "created": "2024-01-14T18:33:31+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..6pZj4jcXbE4hCzdRYULsJO37A-19Od3ynLpZJsDB6tjDgYqrKhuOcbulE2yVCOwS8YSlpjO46F-c8a5NcVsXDQ", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ + 6pZj4jcXbE4hCzdRYULsJO37A-19Od3ynLpZJsDB6tjDgYqrKhuOcbulE2yVCOwS8YSlpjO46F-c8a5NcVsXDQ", }, } ], "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i#z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i", + "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', "created": "2024-01-14T22:03:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..k55LG1o_-vcURKx8sSlAc7h_jtot3Zp18lukljF9B0esj1UL18hBBcunUoZxT9hT6zrFOGDPoQqpTHXj2a6QAw", + "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ + k55LG1o_-vcURKx8sSlAc7h_jtot3Zp18lukljF9B0esj1UL18hBBcunUoZxT9hT6zrFOGDPoQqpTHXj2a6QAw", }, } } From fbdd6e16f006cba910824c08e591d106f28bf262 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 19:44:48 +0000 Subject: [PATCH 11/26] remove long examples lines (did and proofs) Signed-off-by: pstlouis --- aries_cloudagent/vc_api/examples.py | 43 ++++++++++++----------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 97479f8bcd..165e14e83c 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -1,8 +1,5 @@ from marshmallow import Schema, fields -SUBJECT_DID = 'did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i' -ISSUER_DID = 'did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i' - class IssueCredentialRequest(Schema): """Issue credential request. @@ -15,10 +12,10 @@ class IssueCredentialRequest(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "credentialSubject": { - "id": SUBJECT_DID + "id": "did:key:..." }, "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": ISSUER_DID, + "issuer": "did:key:...", "type": ["VerifiableCredential"], } } @@ -38,18 +35,17 @@ class IssueCredentialResponse(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential"], - "issuer": ISSUER_DID, + "issuer": "did:key:...", "issuanceDate": "2010-01-01T19:23:24Z", "credentialSubject": { - "id": SUBJECT_DID + "id": "did:key:..." }, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', + "verificationMethod": "did:key:...#...", "created": "2024-01-14T20:04:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ - Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", + "jws": "ey...", }, } } @@ -94,23 +90,22 @@ class ProvePresentationRequest(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], - "holder": ISSUER_DID, + "holder": "did:key:...", "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential"], - "issuer": ISSUER_DID, + "issuer": "did:key:...", "issuanceDate": "2010-01-01T19:23:24Z", "credentialSubject": { - "id": SUBJECT_DID + "id": "did:key:..." }, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', + "verificationMethod": "did:key:...#...", "created": "2024-01-14T20:04:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ - Bzqa-eV0PfmTzWV0Gh0EMZwdpZ8w08TFKcVy0XD5HKvcPvkovL6bfERVgYEAnE72HQoVE3H7o3LxCGlJ4wQ5Dg", + "jws": "ey...", }, } ], @@ -132,33 +127,31 @@ class ProvePresentationResponse(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], - "holder": ISSUER_DID, + "holder": "did:key:...", "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], "credentialSubject": { - "id": SUBJECT_DID + "id": "did:key:..." }, "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": ISSUER_DID, + "issuer": "did:key:...", "type": ["VerifiableCredential"], "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', + "verificationMethod": "did:key:...#...", "created": "2024-01-14T18:33:31+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ - 6pZj4jcXbE4hCzdRYULsJO37A-19Od3ynLpZJsDB6tjDgYqrKhuOcbulE2yVCOwS8YSlpjO46F-c8a5NcVsXDQ", + "jws": "ey...", }, } ], "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f'{ISSUER_DID}#{ISSUER_DID.split(":")[-1]}', + "verificationMethod": "did:key:...#...", "created": "2024-01-14T22:03:36+00:00", - "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ - k55LG1o_-vcURKx8sSlAc7h_jtot3Zp18lukljF9B0esj1UL18hBBcunUoZxT9hT6zrFOGDPoQqpTHXj2a6QAw", + "jws": "ey...", }, } } From 2cbd7154237fd98256b79038144a40cb0bcbd227 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 19:48:32 +0000 Subject: [PATCH 12/26] linting... Signed-off-by: pstlouis --- aries_cloudagent/vc_api/examples.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 165e14e83c..3de3d8915e 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -1,5 +1,6 @@ from marshmallow import Schema, fields + class IssueCredentialRequest(Schema): """Issue credential request. @@ -11,9 +12,7 @@ class IssueCredentialRequest(Schema): metadata={ "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], - "credentialSubject": { - "id": "did:key:..." - }, + "credentialSubject": {"id": "did:key:..."}, "issuanceDate": "2010-01-01T19:23:24Z", "issuer": "did:key:...", "type": ["VerifiableCredential"], @@ -37,9 +36,7 @@ class IssueCredentialResponse(Schema): "type": ["VerifiableCredential"], "issuer": "did:key:...", "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": { - "id": "did:key:..." - }, + "credentialSubject": {"id": "did:key:..."}, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", @@ -97,9 +94,7 @@ class ProvePresentationRequest(Schema): "type": ["VerifiableCredential"], "issuer": "did:key:...", "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": { - "id": "did:key:..." - }, + "credentialSubject": {"id": "did:key:..."}, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", @@ -131,9 +126,7 @@ class ProvePresentationResponse(Schema): "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], - "credentialSubject": { - "id": "did:key:..." - }, + "credentialSubject": {"id": "did:key:..."}, "issuanceDate": "2010-01-01T19:23:24Z", "issuer": "did:key:...", "type": ["VerifiableCredential"], From 0c0e32d6739e88352f9fb9b24aadd0a6e96b4ff5 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 21:20:47 +0000 Subject: [PATCH 13/26] revert manager changes for verifying a presentation without challenge Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/manager.py | 19 ++-------- aries_cloudagent/vc_api/examples.py | 44 +++++++++++++--------- aries_cloudagent/vc_api/routes.py | 55 ++++++++++++++++++++-------- 3 files changed, 70 insertions(+), 48 deletions(-) diff --git a/aries_cloudagent/vc/vc_ld/manager.py b/aries_cloudagent/vc/vc_ld/manager.py index ec24898a84..850ce695ba 100644 --- a/aries_cloudagent/vc/vc_ld/manager.py +++ b/aries_cloudagent/vc/vc_ld/manager.py @@ -17,7 +17,6 @@ from ..ld_proofs.document_loader import DocumentLoader from ..ld_proofs.purposes.authentication_proof_purpose import AuthenticationProofPurpose from ..ld_proofs.purposes.credential_issuance_purpose import CredentialIssuancePurpose -from ..ld_proofs.purposes.assertion_proof_purpose import AssertionProofPurpose from ..ld_proofs.purposes.proof_purpose import ProofPurpose from ..ld_proofs.suites.bbs_bls_signature_2020 import BbsBlsSignature2020 from ..ld_proofs.suites.bbs_bls_signature_proof_2020 import BbsBlsSignatureProof2020 @@ -268,7 +267,7 @@ async def prepare_credential( return credential - async def _get_signature_suite( + async def _get_suite_for_credential( self, document: Union[VerifiableCredential, VerifiablePresentation], options: LDProofVCOptions, @@ -339,7 +338,7 @@ async def issue( credential = await self.prepare_credential(credential, options) # Get signature suite, proof purpose and document loader - suite = await self._get_signature_suite(credential, options) + suite = await self._get_suite_for_credential(credential, options) proof_purpose = self._get_proof_purpose( proof_purpose=options.proof_purpose, challenge=options.challenge, @@ -361,7 +360,7 @@ async def prove( """Sign a VP with a Linked Data Proof.""" # Get signature suite, proof purpose and document loader - suite = await self._get_signature_suite(presentation, options) + suite = await self._get_suite_for_credential(presentation, options) proof_purpose = self._get_proof_purpose( proof_purpose=options.proof_purpose, challenge=options.challenge, @@ -382,16 +381,7 @@ async def verify_presentation( ) -> PresentationVerificationResult: """Verify a VP with a Linked Data Proof.""" - if vp.proof.proof_purpose == "assertionMethod": - purpose = AssertionProofPurpose() - return await verify_presentation( - presentation=vp.serialize(), - suites=await self._get_all_suites(), - document_loader=self.profile.inject(DocumentLoader), - purpose=purpose, - ) - - elif not options.challenge: + if not options.challenge: raise VcLdpManagerError("Challenge is required for verifying a VP") return await verify_presentation( @@ -399,7 +389,6 @@ async def verify_presentation( suites=await self._get_all_suites(), document_loader=self.profile.inject(DocumentLoader), challenge=options.challenge, - purpose=purpose, ) async def verify_credential( diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 3de3d8915e..dab3bdf474 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -1,5 +1,13 @@ +"""VC-API requests and responses examples""" + from marshmallow import Schema, fields +EXAMPLE_DID = "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i" +EXAMPLE_CRED_PROOF = "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ +SCPQDsbwaEo7aZ28hrpWOPa8vu3CHqM0do6UkVNVM8hM0__1rryDnzeU-V7_lvjxrhqs998rhnojE4UuOLZTDw" +EXAMPLE_PRES_PROOF = "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ +eqWrb_JcMPM1m1tBotnI01WPaV5_cQLUJslkT2oPD00MBb5xUZqIIzxCWdkYHhBo4IVDYCL3RkG5WDWdQ8AyBw" + class IssueCredentialRequest(Schema): """Issue credential request. @@ -12,9 +20,9 @@ class IssueCredentialRequest(Schema): metadata={ "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], - "credentialSubject": {"id": "did:key:..."}, + "credentialSubject": {"id": EXAMPLE_DID}, "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": "did:key:...", + "issuer": EXAMPLE_DID, "type": ["VerifiableCredential"], } } @@ -34,15 +42,15 @@ class IssueCredentialResponse(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential"], - "issuer": "did:key:...", + "issuer": EXAMPLE_DID, "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": {"id": "did:key:..."}, + "credentialSubject": {"id": EXAMPLE_DID}, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:...#...", + "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", "created": "2024-01-14T20:04:36+00:00", - "jws": "ey...", + "jws": EXAMPLE_CRED_PROOF, }, } } @@ -87,20 +95,20 @@ class ProvePresentationRequest(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], - "holder": "did:key:...", + "holder": EXAMPLE_DID, "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential"], - "issuer": "did:key:...", + "issuer": EXAMPLE_DID, "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": {"id": "did:key:..."}, + "credentialSubject": {"id": EXAMPLE_DID}, "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:...#...", + "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", "created": "2024-01-14T20:04:36+00:00", - "jws": "ey...", + "jws": EXAMPLE_CRED_PROOF, }, } ], @@ -122,29 +130,29 @@ class ProvePresentationResponse(Schema): "example": { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiablePresentation"], - "holder": "did:key:...", + "holder": EXAMPLE_DID, "verifiableCredential": [ { "@context": ["https://www.w3.org/2018/credentials/v1"], - "credentialSubject": {"id": "did:key:..."}, + "credentialSubject": {"id": EXAMPLE_DID}, "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": "did:key:...", + "issuer": EXAMPLE_DID, "type": ["VerifiableCredential"], "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:...#...", + "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", "created": "2024-01-14T18:33:31+00:00", - "jws": "ey...", + "jws": EXAMPLE_CRED_PROOF, }, } ], "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": "did:key:...#...", + "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", "created": "2024-01-14T22:03:36+00:00", - "jws": "ey...", + "jws": EXAMPLE_PRES_PROOF, }, } } diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index 4357f8899c..28fa1be7bf 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -8,10 +8,17 @@ from ..resolver.base import ResolverError from ..wallet.error import WalletError +from ..vc.ld_proofs.document_loader import DocumentLoader +from ..vc.ld_proofs.purposes.assertion_proof_purpose import AssertionProofPurpose + +from ..vc.vc_ld.verify import verify_credential, verify_presentation +from ..vc.vc_ld.issue import issue as issue_credential +from ..vc.vc_ld.prove import sign_presentation from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError from ..vc.vc_ld.models.credential import VerifiableCredential from ..vc.vc_ld.models.presentation import VerifiablePresentation from ..vc.vc_ld.models.options import LDProofVCOptions + from .examples import ( IssueCredentialRequest, IssueCredentialResponse, @@ -29,7 +36,7 @@ @docs(tags=["vc-api"], summary="Issue a credential") @request_schema(IssueCredentialRequest) @response_schema(IssueCredentialResponse, 201) -async def issue_credential(request: web.BaseRequest): +async def issue_credential_route(request: web.BaseRequest): """Request handler for signing a jsonld doc. Args: @@ -48,18 +55,23 @@ async def issue_credential(request: web.BaseRequest): options = LDProofVCOptions.deserialize(options) try: manager = context.inject(VcLdpManager) - vc = await manager.issue(credential, options) + vc = await issue_credential( + credential=credential.serialize(), + suite=await manager._get_suite_for_credential(credential, options), + document_loader=manager.profile.inject(DocumentLoader), + purpose=AssertionProofPurpose(), + ) except VcLdpManagerError as err: return web.json_response({"message": str(err)}, status=400) except (WalletError, InjectionError): raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"verifiableCredential": vc.serialize()}, status=201) + return web.json_response({"verifiableCredential": vc}, status=201) @docs(tags=["vc-api"], summary="Verify a credential") @request_schema(VerifyCredentialRequest) @response_schema(VerifyCredentialResponse, 200) -async def verify_credential(request: web.BaseRequest): +async def verify_credential_route(request: web.BaseRequest): """Request handler for verifying a jsonld doc. Args: @@ -71,7 +83,11 @@ async def verify_credential(request: web.BaseRequest): vc = VerifiableCredential.deserialize(body.get("verifiableCredential")) try: manager = context.inject(VcLdpManager) - result = await manager.verify_credential(vc) + result = await verify_credential( + credential=vc.serialize(), + suites=await manager._get_all_suites(), + document_loader=manager.profile.inject(DocumentLoader), + ) return web.json_response(result.serialize()) except (VcLdpManagerError, ResolverError, ValueError) as error: raise web.HTTPBadRequest(reason=str(error)) @@ -85,7 +101,7 @@ async def verify_credential(request: web.BaseRequest): @docs(tags=["vc-api"], summary="Prove a presentation") @request_schema(ProvePresentationRequest) @response_schema(ProvePresentationResponse, 201) -async def prove_presentation(request: web.BaseRequest): +async def prove_presentation_route(request: web.BaseRequest): """Request handler for signing a jsonld doc. Args: @@ -105,18 +121,23 @@ async def prove_presentation(request: web.BaseRequest): try: manager = context.inject(VcLdpManager) - vp = await manager.prove(presentation, options) + vp = await sign_presentation( + presentation=presentation.serialize(), + suite=await manager._get_suite_for_credential(presentation, options), + document_loader=manager.profile.inject(DocumentLoader), + purpose=AssertionProofPurpose(), + ) except VcLdpManagerError as err: return web.json_response({"error": str(err)}, status=400) except (WalletError, InjectionError): raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"verifiablePresentation": vp.serialize()}, status=201) + return web.json_response({"verifiablePresentation": vp}, status=201) @docs(tags=["vc-api"], summary="Verify a presentation") @request_schema(VerifyPresentationRequest) @response_schema(VerifyPresentationResponse, 201) -async def verify_presentation(request: web.BaseRequest): +async def verify_presentation_route(request: web.BaseRequest): """Request handler for verifying a jsonld doc. Args: @@ -131,8 +152,12 @@ async def verify_presentation(request: web.BaseRequest): options = LDProofVCOptions.deserialize(options) try: manager = context.inject(VcLdpManager) - - result = await manager.verify_presentation(vp, options) + result = await verify_presentation( + presentation=vp.serialize(), + suites=await manager._get_all_suites(), + document_loader=manager.profile.inject(DocumentLoader), + purpose=AssertionProofPurpose(), + ) return web.json_response(result.serialize()) except (VcLdpManagerError, ResolverError, ValueError) as error: raise web.HTTPBadRequest(reason=str(error)) @@ -145,10 +170,10 @@ async def register(app: web.Application): app.add_routes( [ - web.post("/credentials/issue", issue_credential), - web.post("/credentials/verify", verify_credential), - web.post("/presentations/prove", prove_presentation), - web.post("/presentations/verify", verify_presentation), + web.post("/credentials/issue", issue_credential_route), + web.post("/credentials/verify", verify_credential_route), + web.post("/presentations/prove", prove_presentation_route), + web.post("/presentations/verify", verify_presentation_route), ] ) From 3bbcd93441a88293cf007e4b9f5947418c17f013 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 21:27:38 +0000 Subject: [PATCH 14/26] added dot to docstring and credential status field Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/models/credential.py | 7 +++++++ aries_cloudagent/vc_api/examples.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/aries_cloudagent/vc/vc_ld/models/credential.py b/aries_cloudagent/vc/vc_ld/models/credential.py index 76945a88b6..698b34f97e 100644 --- a/aries_cloudagent/vc/vc_ld/models/credential.py +++ b/aries_cloudagent/vc/vc_ld/models/credential.py @@ -349,6 +349,13 @@ class Meta: metadata={"example": CREDENTIAL_SUBJECT_EXAMPLE}, ) + credential_status = DictOrDictListField( + required=False, + data_key="credentialStatus", + # validate=CREDENTIAL_STATUS_VALIDATE, + # metadata={"example": CREDENTIAL_STATUS_EXAMPLE}, + ) + proof = fields.Nested( LinkedDataProofSchema(), required=False, diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index dab3bdf474..9750b1713d 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -1,4 +1,4 @@ -"""VC-API requests and responses examples""" +"""VC-API requests and responses examples.""" from marshmallow import Schema, fields From e2316a494573467ee148f3f57913f3b16dc85773 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 15 Jan 2024 21:37:48 +0000 Subject: [PATCH 15/26] shorten example lines Signed-off-by: pstlouis --- aries_cloudagent/vc_api/examples.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py index 9750b1713d..7db1454847 100644 --- a/aries_cloudagent/vc_api/examples.py +++ b/aries_cloudagent/vc_api/examples.py @@ -3,6 +3,7 @@ from marshmallow import Schema, fields EXAMPLE_DID = "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i" +EXAMPLE_VERIFICATION_METHOD = f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}" EXAMPLE_CRED_PROOF = "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ SCPQDsbwaEo7aZ28hrpWOPa8vu3CHqM0do6UkVNVM8hM0__1rryDnzeU-V7_lvjxrhqs998rhnojE4UuOLZTDw" EXAMPLE_PRES_PROOF = "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ @@ -48,7 +49,7 @@ class IssueCredentialResponse(Schema): "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", + "verificationMethod": EXAMPLE_VERIFICATION_METHOD, "created": "2024-01-14T20:04:36+00:00", "jws": EXAMPLE_CRED_PROOF, }, @@ -106,7 +107,7 @@ class ProvePresentationRequest(Schema): "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", + "verificationMethod": EXAMPLE_VERIFICATION_METHOD, "created": "2024-01-14T20:04:36+00:00", "jws": EXAMPLE_CRED_PROOF, }, @@ -141,7 +142,7 @@ class ProvePresentationResponse(Schema): "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", + "verificationMethod": EXAMPLE_VERIFICATION_METHOD, "created": "2024-01-14T18:33:31+00:00", "jws": EXAMPLE_CRED_PROOF, }, @@ -150,7 +151,7 @@ class ProvePresentationResponse(Schema): "proof": { "type": "Ed25519Signature2018", "proofPurpose": "assertionMethod", - "verificationMethod": f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}", + "verificationMethod": EXAMPLE_VERIFICATION_METHOD, "created": "2024-01-14T22:03:36+00:00", "jws": EXAMPLE_PRES_PROOF, }, From 25dc8b6bbb712123ba9d7e38420d81a4d170dce8 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Tue, 16 Jan 2024 00:40:46 +0000 Subject: [PATCH 16/26] add a method to store VC Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/store.py | 44 ++++++++++++++++++++++++++++++ aries_cloudagent/vc_api/routes.py | 32 ++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 aries_cloudagent/vc/vc_ld/store.py diff --git a/aries_cloudagent/vc/vc_ld/store.py b/aries_cloudagent/vc/vc_ld/store.py new file mode 100644 index 0000000000..007a0ea9fb --- /dev/null +++ b/aries_cloudagent/vc/vc_ld/store.py @@ -0,0 +1,44 @@ +from ...admin.request_context import AdminRequestContext +from ...storage.vc_holder.base import VCHolder +from ...storage.vc_holder.vc_record import VCRecord +from ...vc.vc_ld import VerifiableCredential +from ...vc.ld_proofs import DocumentLoader +from pyld import jsonld +from pyld.jsonld import JsonLdProcessor + + +async def store_credential( + credential: VerifiableCredential, + document_loader: DocumentLoader, + context: AdminRequestContext, + cred_id: str = None, +): + """ + Store a verifiable credential. + + """ + # Saving expanded type as a cred_tag + expanded = jsonld.expand( + credential.serialize(), options={"documentLoader": document_loader} + ) + types = JsonLdProcessor.get_values( + expanded[0], + "@type", + ) + vc_record = VCRecord( + contexts=credential.context_urls, + expanded_types=types, + issuer_id=credential.issuer_id, + subject_ids=credential.credential_subject_ids, + schema_ids=[], # Schemas not supported yet + proof_types=[credential.proof.type], + cred_value=credential.serialize(), + given_id=credential.id, + record_id=cred_id, + cred_tags=None, # Tags should be derived from credential values + ) + + async with context.profile.session() as session: + vc_holder = session.inject(VCHolder) + + await vc_holder.store_credential(vc_record) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index 28fa1be7bf..3a6c33c632 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -14,6 +14,7 @@ from ..vc.vc_ld.verify import verify_credential, verify_presentation from ..vc.vc_ld.issue import issue as issue_credential from ..vc.vc_ld.prove import sign_presentation +from ..vc.vc_ld.store import store_credential from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError from ..vc.vc_ld.models.credential import VerifiableCredential from ..vc.vc_ld.models.presentation import VerifiablePresentation @@ -68,6 +69,36 @@ async def issue_credential_route(request: web.BaseRequest): return web.json_response({"verifiableCredential": vc}, status=201) +@docs(tags=["vc-api"], summary="Store a credential") +@request_schema(VerifyCredentialRequest) +@response_schema(VerifyCredentialResponse, 200) +async def store_credential_route(request: web.BaseRequest): + """Request handler for storing a jsonld VC. + + Args: + request: aiohttp request object + + """ + context: AdminRequestContext = request["context"] + body = await request.json() + vc = VerifiableCredential.deserialize(body["verifiableCredential"]) + + try: + manager = context.inject(VcLdpManager) + await manager.verify_credential(vc) + await store_credential( + credential=vc, + document_loader=manager.profile.inject(DocumentLoader), + context=context, + cred_id=None, + ) + except VcLdpManagerError as err: + return web.json_response({"error": str(err)}, status=400) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="Bad credential") + return web.json_response({"message": "Credential stored"}, status=200) + + @docs(tags=["vc-api"], summary="Verify a credential") @request_schema(VerifyCredentialRequest) @response_schema(VerifyCredentialResponse, 200) @@ -171,6 +202,7 @@ async def register(app: web.Application): app.add_routes( [ web.post("/credentials/issue", issue_credential_route), + web.post("/credentials/store", store_credential_route), web.post("/credentials/verify", verify_credential_route), web.post("/presentations/prove", prove_presentation_route), web.post("/presentations/verify", verify_presentation_route), From 0232c4dce9ddd981e235ffade312befed83f4e19 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Tue, 16 Jan 2024 00:46:34 +0000 Subject: [PATCH 17/26] one line docstring Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/store.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/aries_cloudagent/vc/vc_ld/store.py b/aries_cloudagent/vc/vc_ld/store.py index 007a0ea9fb..80f3dfb42d 100644 --- a/aries_cloudagent/vc/vc_ld/store.py +++ b/aries_cloudagent/vc/vc_ld/store.py @@ -13,10 +13,7 @@ async def store_credential( context: AdminRequestContext, cred_id: str = None, ): - """ - Store a verifiable credential. - - """ + """Store a verifiable credential.""" # Saving expanded type as a cred_tag expanded = jsonld.expand( credential.serialize(), options={"documentLoader": document_loader} From 9f314244752e1e7e931826567b410685099eec61 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Tue, 16 Jan 2024 00:54:28 +0000 Subject: [PATCH 18/26] yet another missing docstring Signed-off-by: pstlouis --- aries_cloudagent/vc/vc_ld/store.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aries_cloudagent/vc/vc_ld/store.py b/aries_cloudagent/vc/vc_ld/store.py index 80f3dfb42d..8974d3e198 100644 --- a/aries_cloudagent/vc/vc_ld/store.py +++ b/aries_cloudagent/vc/vc_ld/store.py @@ -1,3 +1,4 @@ +"""Verifiable Credential storage methods.""" from ...admin.request_context import AdminRequestContext from ...storage.vc_holder.base import VCHolder from ...storage.vc_holder.vc_record import VCRecord From 018e8f057fee78494883f6900e6a1577ce594d0f Mon Sep 17 00:00:00 2001 From: pstlouis Date: Wed, 17 Jan 2024 14:57:19 +0000 Subject: [PATCH 19/26] pre-merge Signed-off-by: pstlouis --- aries_cloudagent/vc_api/routes.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py index 3a6c33c632..4f359297fd 100644 --- a/aries_cloudagent/vc_api/routes.py +++ b/aries_cloudagent/vc_api/routes.py @@ -44,7 +44,6 @@ async def issue_credential_route(request: web.BaseRequest): request: aiohttp request object """ - context: AdminRequestContext = request["context"] body = await request.json() credential = VerifiableCredential.deserialize(body["credential"]) @@ -55,6 +54,7 @@ async def issue_credential_route(request: web.BaseRequest): ) options = LDProofVCOptions.deserialize(options) try: + context: AdminRequestContext = request["context"] manager = context.inject(VcLdpManager) vc = await issue_credential( credential=credential.serialize(), @@ -79,11 +79,11 @@ async def store_credential_route(request: web.BaseRequest): request: aiohttp request object """ - context: AdminRequestContext = request["context"] body = await request.json() vc = VerifiableCredential.deserialize(body["verifiableCredential"]) try: + context: AdminRequestContext = request["context"] manager = context.inject(VcLdpManager) await manager.verify_credential(vc) await store_credential( @@ -109,10 +109,10 @@ async def verify_credential_route(request: web.BaseRequest): request: aiohttp request object """ - context: AdminRequestContext = request["context"] body = await request.json() vc = VerifiableCredential.deserialize(body.get("verifiableCredential")) try: + context: AdminRequestContext = request["context"] manager = context.inject(VcLdpManager) result = await verify_credential( credential=vc.serialize(), @@ -139,7 +139,6 @@ async def prove_presentation_route(request: web.BaseRequest): request: aiohttp request object """ - context: AdminRequestContext = request["context"] body = await request.json() presentation = VerifiablePresentation.deserialize(body["presentation"]) @@ -151,6 +150,7 @@ async def prove_presentation_route(request: web.BaseRequest): options = LDProofVCOptions.deserialize(options) try: + context: AdminRequestContext = request["context"] manager = context.inject(VcLdpManager) vp = await sign_presentation( presentation=presentation.serialize(), @@ -175,13 +175,13 @@ async def verify_presentation_route(request: web.BaseRequest): request: aiohttp request object """ - context: AdminRequestContext = request["context"] body = await request.json() vp = VerifiablePresentation.deserialize(body.get("verifiablePresentation")) options = {} if "options" not in body else body["options"] options = LDProofVCOptions.deserialize(options) try: + context: AdminRequestContext = request["context"] manager = context.inject(VcLdpManager) result = await verify_presentation( presentation=vp.serialize(), From 5e419567b0826d3069804c4b92df77ccb594bffc Mon Sep 17 00:00:00 2001 From: pstlouis Date: Mon, 22 Jan 2024 14:29:33 +0000 Subject: [PATCH 20/26] merge vc-api routes, add some examples and validations Signed-off-by: pstlouis --- aries_cloudagent/config/default_context.py | 1 - aries_cloudagent/messaging/valid.py | 49 + .../vc/ld_proofs/document_downloader.py | 1 - .../resources/traceability-v1-context.jsonld | 5371 ----------------- aries_cloudagent/vc/routes.py | 241 +- aries_cloudagent/vc/vc_ld/manager.py | 68 +- .../vc/vc_ld/models/credential.py | 6 +- .../vc/vc_ld/models/presentation.py | 8 +- .../vc/vc_ld/models/request_schemas.py | 72 + aries_cloudagent/vc/vc_ld/store.py | 42 - .../vc/vc_ld/tests/test_manager.py | 4 +- aries_cloudagent/vc_api/__init__.py | 0 aries_cloudagent/vc_api/examples.py | 189 - aries_cloudagent/vc_api/routes.py | 227 - 14 files changed, 360 insertions(+), 5919 deletions(-) delete mode 100644 aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld create mode 100644 aries_cloudagent/vc/vc_ld/models/request_schemas.py delete mode 100644 aries_cloudagent/vc/vc_ld/store.py delete mode 100644 aries_cloudagent/vc_api/__init__.py delete mode 100644 aries_cloudagent/vc_api/examples.py delete mode 100644 aries_cloudagent/vc_api/routes.py diff --git a/aries_cloudagent/config/default_context.py b/aries_cloudagent/config/default_context.py index 9645b18fbe..18e5c4a8ca 100644 --- a/aries_cloudagent/config/default_context.py +++ b/aries_cloudagent/config/default_context.py @@ -142,7 +142,6 @@ async def load_plugins(self, context: InjectionContext): plugin_registry.register_plugin("aries_cloudagent.resolver") plugin_registry.register_plugin("aries_cloudagent.settings") plugin_registry.register_plugin("aries_cloudagent.vc") - plugin_registry.register_plugin("aries_cloudagent.vc_api") plugin_registry.register_plugin("aries_cloudagent.wallet") if wallet_type == "askar-anoncreds": plugin_registry.register_plugin("aries_cloudagent.anoncreds") diff --git a/aries_cloudagent/messaging/valid.py b/aries_cloudagent/messaging/valid.py index 96522cadfc..c2266197ff 100644 --- a/aries_cloudagent/messaging/valid.py +++ b/aries_cloudagent/messaging/valid.py @@ -776,6 +776,27 @@ def __call__(self, value): return value +class PresentationType(Validator): + """Presentation Type.""" + + PRESENTATIONL_TYPE = "VerifiablePresentation" + EXAMPLE = [PRESENTATIONL_TYPE] + + def __init__(self) -> None: + """Initialize the instance.""" + super().__init__() + + def __call__(self, value): + """Validate input value.""" + length = len(value) + if length < 1 or PresentationType.PRESENTATIONL_TYPE not in value: + raise ValidationError( + f"type must include {PresentationType.PRESENTATIONL_TYPE}" + ) + + return value + + class CredentialContext(Validator): """Credential Context.""" @@ -827,6 +848,28 @@ def __call__(self, value): return value +class CredentialStatus(Validator): + """Credential status.""" + + EXAMPLE = { + "id": "https://example.com/credentials/status/3#94567", + "type": "BitstringStatusListEntry", + "statusPurpose": "revocation", + "statusListIndex": "94567", + "statusListCredential": "https://example.com/credentials/status/3", + } + + def __init__(self) -> None: + """Initialize the instance.""" + super().__init__() + + def __call__(self, value): + """Validate input value.""" + # TODO write some tests + + return value + + class IndyOrKeyDID(Regexp): """Indy or Key DID class.""" @@ -967,5 +1010,11 @@ def __init__( CREDENTIAL_SUBJECT_VALIDATE = CredentialSubject() CREDENTIAL_SUBJECT_EXAMPLE = CredentialSubject.EXAMPLE +CREDENTIAL_STATUS_VALIDATE = CredentialStatus() +CREDENTIAL_STATUS_EXAMPLE = CredentialStatus.EXAMPLE + +PRESENTATION_TYPE_VALIDATE = PresentationType() +PRESENTATION_TYPE_EXAMPLE = PresentationType.EXAMPLE + INDY_OR_KEY_DID_VALIDATE = IndyOrKeyDID() INDY_OR_KEY_DID_EXAMPLE = IndyOrKeyDID.EXAMPLE diff --git a/aries_cloudagent/vc/ld_proofs/document_downloader.py b/aries_cloudagent/vc/ld_proofs/document_downloader.py index be9da39eb6..19c64bbb97 100644 --- a/aries_cloudagent/vc/ld_proofs/document_downloader.py +++ b/aries_cloudagent/vc/ld_proofs/document_downloader.py @@ -42,7 +42,6 @@ class StaticCacheJsonLdDownloader: "https://w3id.org/security/v1": "security-v1-context.jsonld", "https://w3id.org/security/v2": "security-v2-context.jsonld", "https://w3id.org/security/suites/ed25519-2020/v1": "ed25519-2020-context.jsonld", - "https://w3id.org/traceability/v1": "traceability-v1-context.jsonld", } def __init__( diff --git a/aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld b/aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld deleted file mode 100644 index 8aeb1d5ea8..0000000000 --- a/aries_cloudagent/vc/ld_proofs/resources/traceability-v1-context.jsonld +++ /dev/null @@ -1,5371 +0,0 @@ -{ - "@context": { - "@version": 1.1, - "@vocab": "https://www.w3.org/ns/credentials/issuer-dependent#", - "id": "@id", - "type": "@type", - "name": "https://schema.org/name", - "description": "https://schema.org/description", - "identifier": "https://schema.org/identifier", - "image": { - "@id": "https://schema.org/image", - "@type": "@id" - }, - "relatedLink": { - "@id": "https://w3id.org/traceability#LinkRole" - }, - "manufacturer": "https://vocabulary.uncefact.org/manufacturerParty", - "manufacturingCountry": "https://vocabulary.uncefact.org/manufactureCountry", - "product": "https://w3id.org/traceability#SteelProduct", - "rawMaterial": "https://w3id.org/traceability#rawMaterial", - "items": "https://schema.org/ItemList", - "dateOfExport": { - "@id": "https://vocabulary.uncefact.org/exportExitDateTime", - "@type": "http://www.w3.org/2001/XMLSchema#dateTime" - }, - "TraceablePresentation": { - "@id": "https://w3id.org/traceability#traceable-presentation", - "@context": { - "replace": { - "@id": "https://w3id.org/traceability#workflow-replace", - "@type": "@id" - }, - "workflow": { - "@id": "https://w3id.org/traceability#workflow", - "@context": { - "definition": { - "@id": "https://w3id.org/traceability#workflow-definition", - "@type": "@id" - }, - "instance": { - "@id": "https://w3id.org/traceability#workflow-instance", - "@type": "@id" - } - } - } - } - }, - "AgricultureActivity": { - "@id": "https://w3id.org/traceability#AgricultureActivity", - "@context": { - "business": { - "@id": "https://w3id.org/traceability#dfn-entities" - }, - "actor": { - "@id": "https://w3id.org/traceability#Person" - }, - "location": { - "@id": "https://www.gs1.org/voc/Place" - }, - "activityDate": { - "@id": "https://schema.org/DateTime" - }, - "activityType": { - "@id": "https://schema.org/description" - }, - "agricultureProduct": { - "@id": "https://schema.org/ItemList" - }, - "observation": { - "@id": "https://w3id.org/traceability#observation" - } - } - }, - "AgricultureInspectionCommonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo", - "@context": { - "applicant": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "facility": { - "@id": "https://www.gs1.org/voc/location" - }, - "inspector": { - "@id": "https://w3id.org/traceability#Inspector" - }, - "delegateOf": { - "@id": "https://vocabulary.uncefact.org/specifiedLegalOrganization" - }, - "regulatoryAgency": { - "@id": "https://vocabulary.uncefact.org/specifiedLegalOrganization" - }, - "inspectionStarted": { - "@id": "https://schema.org/startDate" - }, - "inspectionEnded": { - "@id": "https://schema.org/endDate" - } - } - }, - "AgricultureInspectionGeneric": { - "@id": "https://w3id.org/traceability#AgricultureInspectionGeneric", - "@context": { - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "inspectionType": { - "@id": "https://www.gs1.org/voc/certificationType" - }, - "observation": { - "@id": "https://vocabulary.uncefact.org/relatedObservation" - }, - "name": { - "@id": "https://schema.org/name" - }, - "status": { - "@id": "https://vocabulary.uncefact.org/status" - }, - "productQuantity": { - "@id": "https://vocabulary.uncefact.org/Measurement" - }, - "packageSize": { - "@id": "https://vocabulary.uncefact.org/Measurement" - }, - "inspectorCounted": { - "@id": "https://vocabulary.uncefact.org/applicableSpecifiedAction" - } - } - }, - "AgriculturePackage": { - "@id": "https://w3id.org/traceability#AgriculturePackage", - "@context": { - "packageName": { - "@id": "https://schema.org/name" - }, - "grade": { - "@id": "https://w3id.org/traceability#grade" - }, - "responsibleParty": { - "@id": "https://w3id.org/traceability#responsibleParty" - }, - "voicePickCode": { - "@id": "https://w3id.org/traceability#voicePickCode" - }, - "date": { - "@id": "https://schema.org/DateTime" - }, - "labelImageUrl": { - "@id": "https://schema.org/url" - }, - "labelImageHash": { - "@id": "https://w3id.org/traceability#labelImageHash" - }, - "agricultureProduct": { - "@id": "https://schema.org/ItemList" - }, - "harvest": { - "@id": "https://w3id.org/traceability#AgricultureActivity" - } - } - }, - "AgricultureParcelDelivery": { - "@id": "https://w3id.org/traceability#AgricultureParcelDelivery", - "@context": { - "deliveryAddress": { - "@id": "https://schema.org/deliveryAddress" - }, - "originAddress": { - "@id": "https://schema.org/originAddress" - }, - "foreignPortExport": { - "@id": "https://schema.org/itinerary" - }, - "portOfEntry": { - "@id": "https://schema.org/itinerary" - }, - "deliveryMethod": { - "@id": "https://schema.org/hasDeliveryMethod" - }, - "trackingNumber": { - "@id": "https://schema.org/trackingNumber" - }, - "expectedArrival": { - "@id": "https://schema.org/expectedArrivalFrom" - }, - "specialInstructions": { - "@id": "https://schema.org/comment" - }, - "consignee": { - "@id": "https://schema.org/Organization" - }, - "agriculturePackage": { - "@id": "https://schema.org/itemShipped" - }, - "movementPoints": { - "@id": "https://schema.org/itinerary" - }, - "plannedRoute": { - "@id": "https://schema.org/itinerary" - }, - "shipper": { - "@id": "https://schema.org/seller" - }, - "purchaser": { - "@id": "https://schema.org/buyer" - }, - "carrier": { - "@id": "https://schema.org/carrier" - }, - "broker": { - "@id": "https://schema.org/broker" - } - } - }, - "AgricultureProduct": { - "@id": "https://w3id.org/traceability#AgricultureProduct", - "@context": { - "plu": { - "@id": "https://schema.org/identifier" - }, - "product": { - "@id": "https://www.gs1.org/voc/Product" - }, - "scientificName": { - "@id": "https://vocabulary.uncefact.org/scientificName" - }, - "plantParts": { - "@id": "https://schema.org/description" - }, - "labelImageUrl": { - "@id": "https://schema.org/url" - }, - "labelImageHash": { - "@id": "https://w3id.org/traceability#labelImageHash" - }, - "name": { - "@id": "https://schema.org/name" - }, - "variety": { - "@id": "https://www.gs1.org/voc/consumerProductVariant" - }, - "commodityDesignation": { - "@id": "https://www.gs1.org/voc/additionalProductDescription" - }, - "packType": { - "@id": "https://www.gs1.org/voc/packaging" - } - } - }, - "BankAccount": { - "@id": "https://w3id.org/traceability#BankAccount", - "@context": { - "accountId": { - "@id": "https://w3id.org/traceability#accountId" - }, - "BIC11": { - "@id": "https://w3id.org/traceability#BIC11" - }, - "iban": { - "@id": "https://w3id.org/traceability#iban" - }, - "routingInfo": { - "@id": "https://w3id.org/traceability#routingInfo" - }, - "familyName": { - "@id": "http://schema.org/familyName" - }, - "givenName": { - "@id": "http://schema.org/givenName" - }, - "address": { - "@id": "https://schema.org/PostalAddress" - } - } - }, - "BankAccountHolderAffirmation": { - "@id": "https://w3id.org/traceability#BankAccountHolderAffirmation", - "@context": { - "affirmingParty": { - "@id": "https://w3id.org/traceability#evidenceVerifier" - }, - "bankAccountHolderAffirmationApproach": { - "@id": "https://schema.org/name" - }, - "bank": { - "@id": "https://schema.org/Organization" - } - } - }, - "BillOfLading": { - "@id": "https://w3id.org/traceability#BillOfLading", - "@context": { - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "bookingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BN" - }, - "relatedDocuments": { - "@id": "https://schema.org/Purchase" - }, - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "consignor": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "notify": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "freightForwarder": { - "@id": "https://vocabulary.uncefact.org/freightForwarderParty" - }, - "freight": { - "@id": "https://schema.org/ParcelDelivery" - }, - "nmfcFreightClass": { - "@id": "https://w3id.org/traceability#nmfcFreightClass" - }, - "hazardCode": { - "@id": "https://w3id.org/traceability#hazardCode" - }, - "portOfLoading": { - "@id": "https://vocabulary.uncefact.org/LocationFunctionCodeList#9" - }, - "portOfDischarge": { - "@id": "https://vocabulary.uncefact.org/LocationFunctionCodeList#11" - }, - "particulars": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - } - } - }, - "BusinessRegistrationVerification": { - "@id": "https://w3id.org/traceability#BusinessRegistrationVerification", - "@context": { - "affirmingParty": { - "@id": "https://w3id.org/traceability#affirmingParty" - }, - "registrationUrl": { - "@id": "https://schema.org/url" - }, - "taxIdentificationNumber": { - "@id": "https://vocabulary.uncefact.org/uncl1153#AHP" - }, - "countryOfRegistration": { - "@id": "https://schema.org/country" - } - } - }, - "CBPEntry": { - "@id": "https://w3id.org/traceability#CBPEntry", - "@context": { - "portOfEntry": { - "@id": "https://schema.org/Place" - }, - "bondType": { - "@id": "https://w3id.org/traceability#bondType" - }, - "importer": { - "@id": "https://vocabulary.uncefact.org/importerParty" - }, - "importerOfRecord": { - "@id": "https://w3id.org/traceability#importerOfRecord" - }, - "entryNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" - }, - "bondValue": { - "@id": "https://schema.org/MonetaryAmount" - }, - "entryValue": { - "@id": "https://schema.org/MonetaryAmount" - }, - "centralizedExaminationSite": { - "@id": "https://w3id.org/traceability#centralizedExaminationSite" - }, - "entryType": { - "@id": "https://w3id.org/traceability#entryType" - }, - "originatingWarehouseEntryNumber": { - "@id": "https://w3id.org/traceability#originatingWarehouseEntryNumber" - }, - "suretyCode": { - "@id": "https://w3id.org/traceability#suretyCode" - }, - "portOfUnlading": { - "@id": "https://schema.org/Place" - }, - "transportMode": { - "@id": "https://w3id.org/traceability#transportMode" - }, - "locationOfGoods": { - "@id": "https://schema.org/Place" - }, - "generalOrderNumber": { - "@id": "https://w3id.org/traceability#generalOrderNumber" - }, - "conveyanceNameOrFreeTradeZoneID": { - "@id": "https://w3id.org/traceability#conveyanceNameOrFreeTradeZoneID" - }, - "referenceIDCode": { - "@id": "https://w3id.org/traceability#referenceIDCode" - }, - "referenceIDNumber": { - "@id": "https://w3id.org/traceability#referenceIDNumber" - }, - "lineItems": { - "@id": "https://w3id.org/traceability#lineItems" - }, - "nonAMS": { - "@id": "https://w3id.org/traceability#nonAMS" - }, - "splitBill": { - "@id": "https://w3id.org/traceability#splitBill" - }, - "bolType": { - "@id": "https://w3id.org/traceability#bolType" - }, - "scac": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" - }, - "inBondNumber": { - "@id": "https://w3id.org/traceability#inBondNumber" - }, - "bolNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "quantity": { - "@id": "https://w3id.org/traceability#quantity" - }, - "voyageFlightTrip": { - "@id": "https://w3id.org/traceability#voyageFlightTrip" - }, - "conveyanceName": { - "@id": "https://w3id.org/traceability#conveyanceName" - }, - "arrivalDate": { - "@id": "https://vocabulary.uncefact.org/actualArrivalRelatedDateTime" - } - } - }, - "CBPEntryEntity": { - "@id": "https://w3id.org/traceability#CBPEntryEntity", - "@context": { - "importerOfRecord": { - "@id": "https://w3id.org/traceability#importerOfRecord" - } - } - }, - "CBPEntryLineItem": { - "@id": "https://w3id.org/traceability#CBPEntryLineItem", - "@context": { - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "productDescription": { - "@id": "https://schema.org/description" - }, - "itemCount": { - "@id": "https://vocabulary.uncefact.org/despatchedQuantity" - }, - "itemParty": { - "@id": "https://w3id.org/traceability#itemParty" - }, - "freeTradeZoneFilingDate": { - "@id": "https://schema.org/Date" - }, - "freeTradeZoneStatus": { - "@id": "https://w3id.org/traceability#freeTradeZoneStatus" - }, - "countryOfOrigin": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "value": { - "@id": "https://schema.org/MonetaryAmount" - } - } - }, - "CBPEntrySummary": { - "@id": "https://w3id.org/traceability#CBPEntrySummary", - "@context": { - "entryNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" - }, - "entryType": { - "@id": "https://w3id.org/traceability#entryType" - }, - "summaryDate": { - "@id": "https://schema.org/Date" - }, - "suretyCode": { - "@id": "https://w3id.org/traceability#suretyCode" - }, - "bondType": { - "@id": "https://w3id.org/traceability#bondType" - }, - "portCode": { - "@id": "https://schema.org/Place" - }, - "entryDate": { - "@id": "https://schema.org/Date" - }, - "importingCarrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "transportMode": { - "@id": "https://w3id.org/traceability#transportMode" - }, - "countryOfOrigin": { - "@id": "https://w3id.org/traceability#countryOfOrigin" - }, - "importDate": { - "@id": "https://schema.org/Date" - }, - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "manufacturerId": { - "@id": "https://schema.org/identifier" - }, - "exportingCountry": { - "@id": "https://schema.org/addressCountry" - }, - "exportDate": { - "@id": "https://schema.org/Date" - }, - "immediateTransportationNumber": { - "@id": "https://schema.org/identifier" - }, - "immediateTransportationDate": { - "@id": "https://schema.org/Date" - }, - "missingDocuments": { - "@id": "https://w3id.org/traceability#missingDocuments" - }, - "portOfLoading": { - "@id": "https://schema.org/Place" - }, - "portOfUnlading": { - "@id": "https://schema.org/Place" - }, - "locationOfGoods": { - "@id": "https://schema.org/Place" - }, - "consigneeNumber": { - "@id": "https://schema.org/identifier" - }, - "importerNumber": { - "@id": "https://w3id.org/traceability#importerOfRecord" - }, - "referenceNumber": { - "@id": "https://w3id.org/traceability#referenceNumber" - }, - "ultimateConsignee": { - "@id": "https://vocabulary.uncefact.org/shipToParty" - }, - "importerOfRecord": { - "@id": "https://vocabulary.uncefact.org/importerParty" - }, - "descriptionOfMerchandise": { - "@id": "https://w3id.org/traceability#descriptionOfMerchandise" - }, - "otherFeeSummary": { - "@id": "https://w3id.org/traceability#otherFeeSummary" - }, - "totalEnteredValue": { - "@id": "https://schema.org/MonetaryAmount" - }, - "declarationOfImporter": { - "@id": "https://w3id.org/traceability#declarationOfImporter" - }, - "duty": { - "@id": "https://schema.org/MonetaryAmount" - }, - "tax": { - "@id": "https://schema.org/MonetaryAmount" - }, - "other": { - "@id": "https://schema.org/MonetaryAmount" - }, - "total": { - "@id": "https://schema.org/MonetaryAmount" - } - } - }, - "CBPEntrySummaryLineItem": { - "@id": "https://w3id.org/traceability#CBPEntrySummaryLineItem", - "@context": { - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "adCvdNumber": { - "@id": "https://w3id.org/traceability#adCvdNumber" - }, - "categoryNumber": { - "@id": "https://w3id.org/traceability#categoryNumber" - }, - "otherFees": { - "@id": "https://w3id.org/traceability#otherFees" - }, - "grossWeight": { - "@id": "https://schema.org/weight" - }, - "manifestQuantity": { - "@id": "https://w3id.org/traceability#manifestQuantity" - }, - "netQuantity": { - "@id": "https://schema.org/Quantity" - }, - "enteredValue": { - "@id": "https://schema.org/MonetaryAmount" - }, - "charges": { - "@id": "https://schema.org/MonetaryAmount" - }, - "relationship": { - "@id": "https://schema.org/MonetaryAmount" - }, - "htsRate": { - "@id": "https://w3id.org/traceability#htsRate" - }, - "adCvdRate": { - "@id": "https://w3id.org/traceability#adCvdRate" - }, - "ircRate": { - "@id": "https://w3id.org/traceability#ircRate" - }, - "visaNumber": { - "@id": "https://w3id.org/traceability#visaNumber" - }, - "agriculturalLicenseNumber": { - "@id": "https://w3id.org/traceability#agriculturalLicenseNumber" - }, - "dutyAndIRTax": { - "@id": "https://w3id.org/traceability#dutyAndIRTax" - } - } - }, - "CBPEntryType86": { - "@id": "https://w3id.org/traceability#CBPEntryType86", - "@context": { - "bolNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "entryNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" - }, - "portOfEntry": { - "@id": "https://schema.org/Place" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "countryOfOrigin": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "quantity": { - "@id": "https://w3id.org/traceability#quantity" - }, - "fairRetailValue": { - "@id": "https://schema.org/MonetaryAmount" - }, - "htsusNumber": { - "@id": "https://w3id.org/traceability#commodityCode" - }, - "importerOfRecord": { - "@id": "https://w3id.org/traceability#importerOfRecord" - } - } - }, - "CBPImporterOfRecord": { - "@id": "https://w3id.org/traceability#CBPImporterOfRecord", - "@context": { - "number": { - "@id": "https://w3id.org/traceability#CBPImporterOfRecordNumber" - }, - "identifierType": { - "@id": "https://w3id.org/traceability#CBPImporterOfRecordType" - } - } - }, - "CTPAT": { - "@id": "https://w3id.org/traceability#CTPAT", - "@context": { - "sviNumber": { - "@id": "https://w3id.org/traceability#sviNumber" - }, - "ctpatAccountNumber": { - "@id": "https://w3id.org/traceability#ctpatAccountNumber" - }, - "tradeSector": { - "@id": "https://schema.org/industry" - }, - "tier": { - "@id": "https://w3id.org/traceability#ctpatTier" - }, - "dateOfLastValidation": { - "@id": "https://schema.org/Date" - }, - "issuingCountry": { - "@id": "https://schema.org/addressCountry" - } - } - }, - "CTPATEIPApplication": { - "@id": "https://w3id.org/traceability#CTPAT", - "@context": { - "applicant": { - "@id": "https://w3id.org/traceability#applicant" - }, - "applicantType": { - "@id": "https://w3id.org/traceability#applicantType" - } - } - }, - "CTPATMember": { - "@id": "https://schema.org/Organization", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "scac": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" - }, - "iataCarrierCode": { - "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" - }, - "importerOfRecord": { - "@id": "https://w3id.org/traceability#importerOfRecord" - }, - "faxNumber": { - "@id": "https://schema.org/faxNumber" - }, - "url": { - "@id": "https://schema.org/url" - }, - "logo": { - "@id": "https://schema.org/logo" - } - } - }, - "CargoItem": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/cargoItem", - "@context": { - "cargoLineItems": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/cargoLineItem" - }, - "carrierBookingReference": { - "@id": "https://vocabulary.uncefact.org/carrierAssignedId" - }, - "weight": { - "@id": "https://schema.org/weight" - }, - "volume": { - "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" - }, - "weightUnit": { - "@id": "https://schema.org/unitCode" - }, - "volumeUnit": { - "@id": "https://schema.org/unitCode" - }, - "numberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "packageCode": { - "@id": "https://vocabulary.uncefact.org/packageTypeCode" - } - } - }, - "CargoLineItem": { - "@id": "https://w3id.org/traceability#CargoLineItem", - "@context": { - "cargoLineItemID": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/cargoLineItemID" - }, - "shippingMarks": { - "@id": "https://vocabulary.uncefact.org/physicalShippingMarks" - }, - "descriptionOfGoods": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/descriptionOfGoods" - }, - "HSCode": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/HSCode" - } - } - }, - "ChargeDeclaration": { - "@id": "https://w3id.org/traceability#ChargeDeclaration", - "@context": { - "weightCharge": { - "@id": "https://schema.org/price" - }, - "valuationCharge": { - "@id": "https://schema.org/price" - }, - "tax": { - "@id": "https://schema.org/price" - }, - "dueAgent": { - "@id": "https://schema.org/price" - }, - "dueCarrier": { - "@id": "https://schema.org/price" - }, - "total": { - "@id": "https://schema.org/totalPrice" - } - } - }, - "ChemicalProperty": { - "@id": "https://w3id.org/traceability#ChemicalProperty", - "@context": { - "identifier": { - "@id": "https://schema.org/identifier" - }, - "name": { - "@id": "https://schema.org/name" - }, - "description": { - "@id": "https://schema.org/description" - }, - "formula": { - "@id": "https://purl.obolibrary.org/obo/chebi/formula" - }, - "inchi": { - "@id": "https://purl.obolibrary.org/obo/chebi/inchi" - }, - "inchikey": { - "@id": "https://purl.obolibrary.org/obo/chebi/inchikey" - } - } - }, - "CommissionEvent": { - "@id": "https://w3id.org/traceability#CommissionEvent", - "@context": { - "place": { - "@id": "https://schema.org/Place" - }, - "organization": { - "@id": "https://w3id.org/traceability#Organization" - }, - "products": { - "@id": "https://schema.org/Product" - } - } - }, - "Commodity": { - "@id": "https://w3id.org/traceability#Commodity", - "@context": { - "commodityCode": { - "@id": "https://w3id.org/traceability#commodityCode" - }, - "commodityCodeType": { - "@id": "https://w3id.org/traceability#commodityCodeType" - }, - "description": { - "@id": "https://schema.org/description" - } - } - }, - "ConsignmentItem": { - "@id": "https://vocabulary.uncefact.org/ConsignmentItem", - "@context": { - "marksAndNumbers": { - "@id": "https://vocabulary.uncefact.org/ShippingMarks" - }, - "descriptionOfPackagesAndGoods": { - "@id": "https://vocabulary.uncefact.org/natureIdentificationCargo" - }, - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "packageQuantity": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "netWeight": { - "@id": "https://schema.org/weight" - }, - "grossWeight": { - "@id": "https://schema.org/weight" - }, - "grossVolume": { - "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" - }, - "countryOfOrigin": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "manufacturer": { - "@id": "https://vocabulary.uncefact.org/manufacturerParty" - }, - "transportPackages": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - } - } - }, - "ConsignmentRatingDetail": { - "@id": "https://w3id.org/traceability#ConsignmentRatingDetail", - "@context": { - "numberOfPieces": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "grossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "grossWeightUnit": { - "@id": "https://schema.org/unitCode" - }, - "rateClass": { - "@id": "https://vocabulary.uncefact.org/freightChargeTariffClassCode" - }, - "commodityItemNumber": { - "@id": "https://vocabulary.uncefact.org/discountIndicator" - }, - "chargeableWeight": { - "@id": "https://schema.org/weight" - }, - "rateCharge": { - "@id": "https://schema.org/price" - }, - "total": { - "@id": "https://schema.org/totalPrice" - }, - "natureAndVolumeOfGoods": { - "@id": "https://schema.org/description" - } - } - }, - "ContactPoint": { - "@id": "https://schema.org/ContactPoint", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "place": { - "@id": "https://w3id.org/traceability#place" - }, - "email": { - "@id": "https://schema.org/email" - }, - "phoneNumber": { - "@id": "https://schema.org/telephone" - } - } - }, - "Customer": { - "@id": "https://w3id.org/traceability#Customer", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "address": { - "@id": "https://schema.org/PostalAddress" - }, - "telephone": { - "@id": "https://schema.org/telephone" - }, - "email": { - "@id": "https://schema.org/email" - } - } - }, - "DCSAShippingInstruction": { - "@id": "https://vocabulary.uncefact.org/TransportInstructions", - "@context": { - "shippingInstructionID": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#TIN" - }, - "transportDocumentType": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/transportDocumentType" - }, - "preCarriageUnderShippersResponsibility": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/preCarriageUnderShippersResponsibility" - }, - "invoicePayableAt": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/invoicePayableAt" - }, - "carrierBookingReference": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BN" - }, - "cargoItems": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "utilizedTransportEquipments": { - "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" - }, - "shipmentLocations": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DOCUMENTATION_DOMAIN/1.0.0#/components/schemas/shipmentLocation" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "invoicePayerShipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "invoicePayerConsignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "firstNotify": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "secondNotify": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "otherNotify": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "shippersFreightForwarder": { - "@id": "https://vocabulary.uncefact.org/freightForwarderParty" - }, - "consigneesFreightForwarder": { - "@id": "https://vocabulary.uncefact.org/freightForwarderParty" - } - } - }, - "DCSATransportDocument": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/transportDocument", - "@context": { - "transportDocumentReference": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "placeOfIssue": { - "@id": "https://vocabulary.uncefact.org/issueLocation" - }, - "issueDate": { - "@id": "https://vocabulary.uncefact.org/issueDateTime" - }, - "shippedOnBoardDate": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/shippedOnBoardDate" - }, - "receivedForShipmentDate": { - "@id": "https://vocabulary.uncefact.org/availabilityDueDateTime" - }, - "termsAndConditions": { - "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" - }, - "issuerCode": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" - }, - "issuerCodeListProvider": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/issuerCodeListProvider" - }, - "declaredValueCurrency": { - "@id": "https://schema.org/currency" - }, - "cargoMovementTypeAtOrigin": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/cargoMovementTypeAtOrigin" - }, - "cargoMovementTypeAtDestination": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/cargoMovementTypeAtDestination" - }, - "receiptDeliveryTypeAtOrigin": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/receiptDeliveryTypeAtOrigin" - }, - "receiptDeliveryTypeAtDestination": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/receiptDeliveryTypeAtDestination" - }, - "serviceContractReference": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.2#/components/schemas/serviceContractReference" - }, - "shippingInstruction": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/shippingInstruction" - }, - "charges": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/charges" - }, - "clauses": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/clauses" - }, - "transports": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/transports" - } - } - }, - "DeMinimisShipment": { - "@id": "https://w3id.org/traceability#DeMinimisShipment", - "@context": { - "originatorCode": { - "@id": "https://w3id.org/traceability#originatorCode" - }, - "participantFilerType": { - "@id": "https://w3id.org/traceability#participantFilerType" - }, - "shipmentTrackingNumber": { - "@id": "https://vocabulary.uncefact.org/MarkingInstructionCodeList#37" - }, - "houseBillOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BH" - }, - "masterBillOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "modeOfTransportation": { - "@id": "https://vocabulary.uncefact.org/mode" - }, - "shipmentInitiator": { - "@id": "https://w3id.org/traceability#shipmentInitiator" - }, - "seller": { - "@id": "https://vocabulary.uncefact.org/sellerParty" - }, - "buyer": { - "@id": "https://vocabulary.uncefact.org/buyerParty" - }, - "finalDeliverTo": { - "@id": "https://vocabulary.uncefact.org/shipToParty" - }, - "enhancedProductDescription": { - "@id": "https://w3id.org/traceability#enhancedProductDescription" - }, - "shipmentSecurityScan": { - "@id": "https://w3id.org/traceability#shipmentSecurityScan" - }, - "knownCarrierCustomerFlag": { - "@id": "https://w3id.org/traceability#knownCarrierCustomerFlag" - }, - "knownMarketplaceSellerFlag": { - "@id": "https://w3id.org/traceability#knownMarketplaceSellerFlag" - }, - "marketplaceSellerAccountNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#ADE" - }, - "productPicture": { - "@id": "https://schema.org/image" - }, - "listedPriceOnMarketplace": { - "@id": "https://schema.org/price" - } - } - }, - "DeliverySchedule": { - "@id": "https://w3id.org/traceability#DeliverySchedule", - "@context": { - "transporter": { - "@id": "https://schema.org/agent" - }, - "batchNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BT" - }, - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "place": { - "@id": "https://schema.org/toLocation" - }, - "consignor": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "scheduledVolume": { - "@id": "https://w3id.org/traceability#QuantitativeValue" - }, - "scheduledDate": { - "@id": "https://schema.org/departureTime" - }, - "injectionVolume": { - "@id": "https://w3id.org/traceability#QuantitativeValue" - }, - "injectionDate": { - "@id": "https://schema.org/departureTime" - }, - "injectionEndDate": { - "@id": "https://schema.org/departureTime" - }, - "deliveryDate": { - "@id": "https://schema.org/arrivalTime" - }, - "deliveryEndDate": { - "@id": "https://schema.org/arrivalTime" - }, - "portOfEntry": { - "@id": "https://w3id.org/traceability#Place" - }, - "portOfDestination": { - "@id": "https://w3id.org/traceability#Place" - }, - "portOfArrival": { - "@id": "https://w3id.org/traceability#Place" - }, - "addressCountry": { - "@id": "https://schema.org/addressCountry" - } - } - }, - "DeliveryStatement": { - "@id": "https://w3id.org/traceability#DeliveryStatement", - "@context": { - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "deliveredDate": { - "@id": "https://schema.org/Date" - }, - "deliveredVolume": { - "@id": "https://schema.org/MeasuredValue" - }, - "observation": { - "@id": "https://w3id.org/traceability#observation" - } - } - }, - "EDDShape": { - "@id": "https://w3id.org/traceability#EDDShape", - "@context": { - "meta": { - "@id": "https://w3id.org/traceability#EDDShapeMeta" - }, - "reporter": { - "@id": "https://schema.org/name" - }, - "scientificName": { - "@id": "http://rs.tdwg.org/dwc/terms/scientificName" - }, - "commonName": { - "@id": "http://rs.tdwg.org/dwc/terms/vernacularName" - }, - "subjectNativity": { - "@id": "http://rs.tdwg.org/dwc/terms/establishmentMeans" - }, - "occurrenceStatus": { - "@id": "http://rs.tdwg.org/dwc/iri/measurementValue" - }, - "status": { - "@id": "https://schema.org/description" - }, - "observationDate": { - "@id": "http://rs.tdwg.org/dwc/terms/eventDate" - }, - "dateEntered": { - "@id": "http://rs.tdwg.org/dwc/terms/eventDate" - }, - "dateUpdated": { - "@id": "http://rs.tdwg.org/dwc/terms/eventDate" - }, - "location": { - "@id": "https://schema.org/location" - }, - "mapResources": { - "@id": "https://w3id.org/traceability#MapResource" - }, - "naDatum": { - "@id": "http://rs.tdwg.org/dwc/terms/geodeticDatum" - }, - "coordinateUncertainty": { - "@id": "http://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters" - }, - "centroidType": { - "@id": "https://schema.org/polygon" - }, - "abundance": { - "@id": "https://schema.org/description" - }, - "infestedAreaAcres": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "grossAreaAcres": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "percentCover": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "density": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementRemarks" - }, - "quantity": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "quantityUnits": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantityType" - }, - "approximateQuantity": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "incidence": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "severity": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "managementStatus": { - "@id": "https://schema.org/status" - }, - "habitat": { - "@id": "http://rs.tdwg.org/dwc/terms/habitat" - }, - "siteName": { - "@id": "http://rs.tdwg.org/dwc/terms/locationID" - }, - "recordBasis": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" - }, - "surveyor": { - "@id": "http://rs.tdwg.org/dwc/terms/recordedBy" - }, - "dateUncertaintyDays": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementAccuracy" - }, - "visitType": { - "@id": "https://schema.org/description" - }, - "persistentId": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceID" - }, - "uuid": { - "@id": "http://rs.tdwg.org/dwc/terms/dateIdentified" - }, - "reviewer": { - "@id": "http://rs.tdwg.org/dwc/terms/identifiedBy" - }, - "verificationMethod": { - "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" - }, - "verified": { - "@id": "http://rs.tdwg.org/dwc/terms/identificationVerificationStatus" - }, - "identificationCredibility": { - "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" - } - } - }, - "EDDShapeMeta": { - "@id": "https://w3id.org/traceability#EDDShapeMeta", - "@context": { - "recordOwner": { - "@id": "https://schema.org/name" - }, - "shapeType": { - "@id": "https://schema.org/description" - }, - "method": { - "@id": "http://rs.tdwg.org/dwc/terms/locationRemarks" - }, - "numberCollected": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementRemarks" - }, - "populationStatus": { - "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" - }, - "smallestOrganismSampled": { - "@id": "https://schema.org/size" - }, - "largestOrganismSampled": { - "@id": "https://schema.org/size" - }, - "hostScientificName": { - "@id": "http://rs.tdwg.org/dwc/terms/scientificName" - }, - "hostName": { - "@id": "http://rs.tdwg.org/dwc/terms/vernacularName" - }, - "hostPhenology": { - "@id": "http://rs.tdwg.org/dwc/terms/lifeStage" - }, - "hostDamage": { - "@id": "https://schema.org/description" - }, - "localOwnership": { - "@id": "http://rs.tdwg.org/dwc/terms/locality" - }, - "museum": { - "@id": "https://schema.org/name" - }, - "museumRecord": { - "@id": "http://rs.tdwg.org/dwc/terms/catalogNumber" - }, - "voucher": { - "@id": "http://rs.tdwg.org/dwc/terms/disposition" - }, - "observationId": { - "@id": "http://rs.tdwg.org/dwc/terms/identifiedBy" - }, - "collectionTimeMinutes": { - "@id": "https://schema.org/activityDuration" - }, - "originalRecordId": { - "@id": "http://rs.tdwg.org/dwc/terms/recordNumber" - }, - "originalReportedName": { - "@id": "http://rs.tdwg.org/dwc/terms/verbatimIdentification" - }, - "recordSourceType": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementRemarks" - }, - "dataCollectionMethod": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementMethod" - }, - "trapType": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" - }, - "numberTraps": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingEffort" - }, - "targetName": { - "@id": "http://rs.tdwg.org/dwc/terms/organismName" - }, - "targetCount": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "targetRange": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "phenology": { - "@id": "http://rs.tdwg.org/dwc/terms/organismRemarks" - }, - "lifeStatus": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - }, - "sex": { - "@id": "http://rs.tdwg.org/dwc/terms/sex" - }, - "waterBodyName": { - "@id": "http://rs.tdwg.org/dwc/terms/waterBody" - }, - "waterBodyType": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - }, - "substrate": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - }, - "treatmentArea": { - "@id": "http://rs.tdwg.org/dwc/iri/measurementValue" - }, - "plantsTreated": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "treatmentComments": { - "@id": "http://rs.tdwg.org/dwc/terms/eventRemarks" - }, - "reference": { - "@id": "http://rs.tdwg.org/dwc/terms/associatedReferences" - }, - "locality": { - "@id": "http://rs.tdwg.org/dwc/terms/locationRemarks" - }, - "comments": { - "@id": "http://rs.tdwg.org/dwc/terms/eventRemarks" - }, - "publicReviewerComments": { - "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" - } - } - }, - "Entity": { - "@id": "https://w3id.org/traceability#Entity", - "@context": { - "entityType": { - "@id": "https://schema.org/additionalType" - }, - "name": { - "@id": "https://schema.org/name" - }, - "legalName": { - "@id": "https://schema.org/legalName" - }, - "url": { - "@id": "https://schema.org/url" - }, - "taxId": { - "@id": "https://schema.org/taxID" - }, - "address": { - "@id": "https://schema.org/PostalAddress" - }, - "email": { - "@id": "https://schema.org/email" - }, - "phoneNumber": { - "@id": "https://schema.org/telephone" - }, - "faxNumber": { - "@id": "https://schema.org/faxNumber" - } - } - }, - "EntryNumber": { - "@id": "https://w3id.org/traceability#EntryNumber", - "@context": { - "entryNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" - } - } - }, - "Event": { - "@id": "https://w3id.org/traceability#EventCredential", - "@context": {} - }, - "ExternalResource": { - "@id": "https://w3id.org/traceability#ExternalResource", - "@context": { - "uri": { - "@id": "https://schema.org/contentUrl" - }, - "hash": { - "@id": "https://schema.org/sha256" - } - } - }, - "FSMAAbstractKDE": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE", - "@context": { - "name": { - "@id": "https://schema.org/propertyID" - }, - "value": { - "@id": "https://schema.org/value" - } - } - }, - "FSMACreatingCTE": { - "@id": "https://w3id.org/traceability#FSMACreatingCTE", - "@context": { - "food": { - "@id": "https://w3id.org/traceability#FSMAProduct" - }, - "location": { - "@id": "https://schema.org/location" - }, - "dateCompleted": { - "@id": "https://schema.org/endDate" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMAFirstReceiverData": { - "@id": "https://w3id.org/traceability#FSMAFirstReceiverData", - "@context": { - "traceabilityLot": { - "@id": "https://w3id.org/traceability#FSMATraceabilityLot" - }, - "originatorLocation": { - "@id": "https://schema.org/location" - }, - "harvestDate": { - "@id": "https://schema.org/endDate" - }, - "coolingLocation": { - "@id": "https://schema.org/location" - }, - "coolingDate": { - "@id": "https://schema.org/endDate" - }, - "packingLocation": { - "@id": "https://schema.org/location" - }, - "packingDate": { - "@id": "https://schema.org/endDate" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMAGrowingCTE": { - "@id": "https://w3id.org/traceability#FSMAGrowingCTE", - "@context": { - "traceabilityLot": { - "@id": "https://w3id.org/traceability#FSMATraceabilityLot" - }, - "growingAreaCoordinates": { - "@id": "https://w3id.org/traceability#GeoCoordinates" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMAProduct": { - "@id": "https://w3id.org/traceability#FSMAProduct", - "@context": { - "traceabilityLot": { - "@id": "https://w3id.org/traceability#FSMATraceabilityLot" - }, - "quantity": { - "@id": "https://vocabulary.uncefact.org/applicableQuantity" - }, - "unit": { - "@id": "https://vocabulary.uncefact.org/applicableQuantityUnitTypeCode" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMAReceivingCTE": { - "@id": "https://w3id.org/traceability#FSMAReceivingCTE", - "@context": { - "shipment": { - "@id": "https://w3id.org/traceability#FSMAShipment" - }, - "dateReceived": { - "@id": "https://schema.org/endDate" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMAShipment": { - "@id": "https://w3id.org/traceability#FSMAShipment", - "@context": { - "product": { - "@id": "https://w3id.org/traceability#FSMAProduct" - }, - "from": { - "@id": "https://schema.org/fromLocation" - }, - "to": { - "@id": "https://schema.org/toLocation" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMAShippingCTE": { - "@id": "https://w3id.org/traceability#FSMAShippingCTE", - "@context": { - "shipment": { - "@id": "https://w3id.org/traceability#FSMAShipment" - }, - "dateShipped": { - "@id": "https://schema.org/startDate" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMATraceabilityLot": { - "@id": "https://w3id.org/traceability#FSMATraceabilityLot", - "@context": { - "lotCode": { - "@id": "https://www.gs1.org/voc/hasBatchLotNumber" - }, - "lotCodeAssignmentMethod": { - "@id": "https://schema.org/description" - }, - "lotCodeGeneratorLocation": { - "@id": "https://schema.org/location" - }, - "lotCodeGeneratorPOC": { - "@id": "https://schema.org/contactPoint" - }, - "lotType": { - "@id": "https://schema.org/additionalType" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FSMATransformingCTE": { - "@id": "https://w3id.org/traceability#FSMATransformingCTE", - "@context": { - "foodUsed": { - "@id": "https://w3id.org/traceability#FSMAProduct" - }, - "foodProduced": { - "@id": "https://w3id.org/traceability#FSMAProduct" - }, - "locationTransformed": { - "@id": "https://schema.org/location" - }, - "dateCompleted": { - "@id": "https://schema.org/endDate" - }, - "additionalData": { - "@id": "https://w3id.org/traceability#FSMAAbstractKDE" - } - } - }, - "FoodDefenseDeficiency": { - "@id": "https://w3id.org/traceability#FoodDefenseDeficiency", - "@context": { - "number": { - "@id": "https://schema.org/identifier" - }, - "description": { - "@id": "https://schema.org/description" - }, - "proposedCorrectionDate": { - "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" - }, - "dateCorrected": { - "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" - } - } - }, - "FoodDefenseInspection": { - "@id": "https://w3id.org/traceability#FoodDefenseInspection", - "@context": { - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "questions": { - "@id": "https://w3id.org/traceability#FoodDefenseQuestion" - }, - "deficiencies": { - "@id": "https://w3id.org/traceability#FoodDefenseDeficiency" - } - } - }, - "FoodDefenseQuestion": { - "@id": "https://w3id.org/traceability#FoodDefenseQuestion", - "@context": { - "number": { - "@id": "https://schema.org/identifier" - }, - "facility": { - "@id": "https://schema.org/location" - }, - "response": { - "@id": "https://vocabulary.uncefact.org/assertion" - }, - "rating": { - "@id": "https://vocabulary.uncefact.org/assertion" - } - } - }, - "FoodGradeInspection": { - "@id": "https://w3id.org/traceability#FoodGradeInspection", - "@context": { - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "loadingStatus": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "carrierTypeName": { - "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" - }, - "refrigerationUnitOn": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "doorsOpen": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "lots": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionLot" - }, - "generalRemarks": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "estimatedCharges": { - "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" - } - } - }, - "FoodGradeInspectionDefect": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionDefect", - "@context": { - "offsizeDefect": { - "@id": "https://vocabulary.uncefact.org/damageRemarks" - }, - "averageDefects": { - "@id": "https://qudt.org/vocab/unit/PERCENT" - }, - "damage": { - "@id": "https://qudt.org/vocab/unit/PERCENT" - }, - "seriousDamage": { - "@id": "https://qudt.org/vocab/unit/PERCENT" - }, - "verySeriousDamage": { - "@id": "https://qudt.org/vocab/unit/PERCENT" - } - } - }, - "FoodGradeInspectionLot": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionLot", - "@context": { - "agricultureProduct": { - "@id": "https://w3id.org/traceability#AgricultureProduct" - }, - "lotIdentifier": { - "@id": "https://www.gs1.org/voc/hasBatchLotNumber" - }, - "numberContainers": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "countInspected": { - "@id": "https://vocabulary.uncefact.org/remark" - }, - "brandMarkings": { - "@id": "https://vocabulary.uncefact.org/brandName" - }, - "samples": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionSample" - }, - "defects": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionDefect" - }, - "grade": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionResult" - }, - "remarks": { - "@id": "https://vocabulary.uncefact.org/remark" - }, - "minTemperature": { - "@id": "https://schema.org/measuredValue" - }, - "maxTemperature": { - "@id": "https://schema.org/measuredValue" - } - } - }, - "FoodGradeInspectionResult": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionResult", - "@context": { - "gradeInspected": { - "@id": "https://vocabulary.uncefact.org/standard" - }, - "requirementsMet": { - "@id": "https://vocabulary.uncefact.org/assertion" - }, - "details": { - "@id": "https://vocabulary.uncefact.org/additionalInformationNote" - } - } - }, - "FoodGradeInspectionSample": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionSample", - "@context": { - "sampleSizeValue": { - "@id": "https://vocabulary.uncefact.org/applicableQuantity" - }, - "sampleSizeUnits": { - "@id": "https://vocabulary.uncefact.org/applicableQuantityUnitTypeCode" - }, - "sampleProperties": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionSampleProperty" - } - } - }, - "FoodGradeInspectionSampleProperty": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionSampleProperty", - "@context": { - "propertyName": { - "@id": "https://vocabulary.uncefact.org/parameterValue" - }, - "propertyValue": { - "@id": "https://vocabulary.uncefact.org/measuredValue" - } - } - }, - "ForeignChargeDeclaration": { - "@id": "https://w3id.org/traceability#ForeignChargeDeclaration", - "@context": { - "foreignCurrencyConvertionRate": { - "@id": "https://schema.org/currentExchangeRate" - }, - "foreignChargesCurrency": { - "@id": "https://schema.org/currency" - }, - "foreignCharges": { - "@id": "https://schema.org/price" - } - } - }, - "FreightManifest": { - "@id": "https://vocabulary.uncefact.org/manifestRelatedDocument", - "@context": { - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "carrierCode": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" - }, - "transportMeans": { - "@id": "https://vocabulary.uncefact.org/transportMeans" - }, - "transportMeansId": { - "@id": "https://schema.org/identifier" - }, - "voyage": { - "@id": "https://vocabulary.uncefact.org/TransportMovement" - }, - "billsOfLading": { - "@id": "https://vocabulary.uncefact.org/manifestRelatedDocument" - } - } - }, - "GAPCorrectiveActionReport": { - "@id": "https://w3id.org/traceability#GAPCorrectiveActionReport", - "@context": { - "nonconformityDescription": { - "@id": "https://schema.org/description" - }, - "notifiedCompanyStaff": { - "@id": "https://schema.org/actionStatus" - }, - "correctiveAction": { - "@id": "https://schema.org/potentialAction" - }, - "affirmingRepresentative": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - } - } - }, - "GAPInspection": { - "@id": "https://w3id.org/traceability#GAPInspection", - "@context": { - "GAPPlus": { - "@id": "https://vocabulary.uncefact.org/documentTypeCode" - }, - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "usesLogo": { - "@id": "https://vocabulary.uncefact.org/assertion" - }, - "subjectToRule": { - "@id": "https://vocabulary.uncefact.org/regulationConformityId" - }, - "operationDescription": { - "@id": "https://schema.org/description" - }, - "harvestCompany": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "otherContractors": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "commoditiesCovered": { - "@id": "https://schema.org/ItemList" - }, - "commoditiesProduced": { - "@id": "https://schema.org/ItemList" - }, - "totalArea": { - "@id": "https://www.gs1.org/voc/grossArea" - }, - "fieldOpsHarvestingScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "postHarvestOpsScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "logoUseScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "tomatoProdHarvestingScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "tomatoPackinghouseScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "tomatoGreenhouseScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "tomatoPackingDistributionScope": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "personsInterviewed": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "requestedBy": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "distributeTo": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "additionalComments": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "reviewingOfficial": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "dateReviewed": { - "@id": "https://www.gs1.org/voc/certificationAuditDate" - }, - "meetsCriteria": { - "@id": "https://www.gs1.org/voc/certificationStatus" - }, - "requirementResults": { - "@id": "https://w3id.org/traceability#GAPRequirementResult" - } - } - }, - "GAPLocationCertification": { - "@id": "https://w3id.org/traceability#GAPLocationCertification", - "@context": { - "location": { - "@id": "https://www.gs1.org/voc/certificationSubject" - }, - "gapInspection": { - "@id": "https://www.gs1.org/voc/certification" - }, - "isCertified": { - "@id": "https://www.gs1.org/voc/certificationStatus" - } - } - }, - "GAPRequirementResult": { - "@id": "https://w3id.org/traceability#GAPRequirementResult", - "@context": { - "requirementNumber": { - "@id": "https://vocabulary.uncefact.org/standard" - }, - "resultCode": { - "@id": "https://vocabulary.uncefact.org/assertionCode" - }, - "auditorComments": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "correctiveActionReport": { - "@id": "https://w3id.org/traceability#GAPCorrectiveActionReport" - } - } - }, - "GeoCoordinates": { - "@id": "https://schema.org/GeoCoordinates", - "@context": { - "latitude": { - "@id": "https://schema.org/latitude" - }, - "longitude": { - "@id": "https://schema.org/longitude" - } - } - }, - "HouseBillOfLading": { - "@id": "https://w3id.org/traceability#HouseBillOfLading", - "@context": { - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "bookingNumber": { - "@id": "https://vocabulary.uncefact.org/carrierAssignedId" - }, - "shippersReferences": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "notifyParty": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "preCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" - }, - "mainCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" - }, - "onCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" - }, - "placeOfReceipt": { - "@id": "https://schema.org/Place" - }, - "portOfLoading": { - "@id": "https://vocabulary.uncefact.org/transshipmentLocation" - }, - "placeOfDelivery": { - "@id": "https://schema.org/Place" - }, - "portOfDischarge": { - "@id": "https://vocabulary.uncefact.org/unloadingLocation" - }, - "totalNumberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "transportEquipmentQuantity": { - "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" - }, - "includedConsignmentItems": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "freightAndCharges": { - "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" - }, - "declaredValue": { - "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" - }, - "termsAndConditions": { - "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" - } - } - }, - "IATAAirWaybill": { - "@id": "https://w3id.org/traceability#IATAAirWaybill", - "@context": { - "airWaybillNumber": { - "@id": "https://schema.org/orderNumber" - }, - "waybillType": { - "@id": "https://schema.org/DigitalDocument" - }, - "airlineCodeNumber": { - "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" - }, - "serialNumber": { - "@id": "https://schema.org/serialNumber" - }, - "airportOfDeparture": { - "@id": "https://onerecord.iata.org/cargo/Location#code" - }, - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "conditionsOfContract": { - "@id": "https://schema.org/termsOfService" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "shippersAccountNumber": { - "@id": "https://schema.org/accountId" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "consigneesAccountNumber": { - "@id": "https://schema.org/accountId" - }, - "issuingCarrierAgent": { - "@id": "https://vocabulary.uncefact.org/carrierAgentParty" - }, - "agentIATACode": { - "@id": "https://onerecord.iata.org/cargo/Company#iataCargoAgentCode" - }, - "agentAccountNumber": { - "@id": "https://schema.org/accountId" - }, - "requestedRouting": { - "@id": "https://schema.org/Trip" - }, - "destinationAirport": { - "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" - }, - "requestedFlight": { - "@id": "https://schema.org/Flight" - }, - "requestedDate": { - "@id": "https://w3id.org/traceability#requestDate" - }, - "accountingInformation": { - "@id": "https://vocabulary.uncefact.org/typeCode" - }, - "currency": { - "@id": "https://schema.org/currency" - }, - "chargeCodes": { - "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" - }, - "weightValuationChargesType": { - "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" - }, - "otherChargesType": { - "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" - }, - "declaredValueForCarriage": { - "@id": "https://schema.org/value" - }, - "declaredValueForCustoms": { - "@id": "https://vocabulary.uncefact.org/customsValueSpecifiedAmount" - }, - "amountOfInsurance": { - "@id": "https://schema.org/value" - }, - "insuranceClauses": { - "@id": "https://vocabulary.uncefact.org/contractualClause" - }, - "handlingInformation": { - "@id": "https://vocabulary.uncefact.org/handlingInstructions" - }, - "specialCustomsInformation": { - "@id": "https://vocabulary.uncefact.org/SpecifiedDeclaration" - }, - "consignmentRatingDetails": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "totalNumberOfPieces": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "totalGrossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "totalCharge": { - "@id": "https://schema.org/totalPrice" - }, - "otherCharges": { - "@id": "https://schema.org/price" - }, - "prepaidChargeDeclaration": { - "@id": "https://w3id.org/traceability#PrepaidChargeDeclaration" - }, - "prepaidTotal": { - "@id": "https://schema.org/totalPrice" - }, - "collectChargeDeclaration": { - "@id": "https://w3id.org/traceability#CollectChargeDeclaration" - }, - "destinationCollectChargeDeclaration": { - "@id": "https://w3id.org/traceability#DestinationCollectChargeDeclaration" - }, - "collectTotal": { - "@id": "https://schema.org/totalPrice" - }, - "shippersCertificationBox": { - "@id": "https://vocabulary.uncefact.org/CertificateTypeCodeList#2" - }, - "executedOn": { - "@id": "https://w3id.org/traceability#executionTime" - }, - "executedAt": { - "@id": "https://schema.org/Place" - } - } - }, - "ImporterSecurityFiling": { - "@id": "https://w3id.org/traceability#ImporterSecurityFiling", - "@context": { - "seller": { - "@id": "https://vocabulary.uncefact.org/sellerParty" - }, - "buyer": { - "@id": "https://vocabulary.uncefact.org/buyerParty" - }, - "importer": { - "@id": "https://vocabulary.uncefact.org/importerParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "shipToParty": { - "@id": "https://vocabulary.uncefact.org/shipToParty" - }, - "filingItems": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "containerStuffingLocation": { - "@id": "https://w3id.org/traceability#containerStuffingLocation" - }, - "consolidator": { - "@id": "https://vocabulary.uncefact.org/consolidatorParty" - } - } - }, - "Inbond": { - "@id": "https://w3id.org/traceability#Inbond", - "@context": { - "product": { - "@id": "https://www.gs1.org/voc/Product" - }, - "shipment": { - "@id": "https://schema.org/ParcelDelivery" - }, - "inBondNumber": { - "@id": "https://schema.org/identifier" - }, - "entryId": { - "@id": "https://schema.org/identifier" - }, - "ftzNo": { - "@id": "https://schema.org/identifier" - }, - "inBondType": { - "@id": "https://schema.org/identifier" - }, - "portOfEntry": { - "@id": "https://www.gs1.org/voc/Place" - }, - "portOfDestination": { - "@id": "https://www.gs1.org/voc/Place" - }, - "portOfArrival": { - "@id": "https://www.gs1.org/voc/Place" - }, - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "irsNumber": { - "@id": "https://schema.org/identifier" - }, - "recipient": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "billOfLadingNumber": { - "@id": "https://schema.org/identifier" - }, - "expectedDeliveryDate": { - "@id": "https://schema.org/DateTime" - }, - "valuePerItem": { - "@id": "https://schema.org/PriceSpecification" - }, - "totalOrderValue": { - "@id": "https://schema.org/PriceSpecification" - } - } - }, - "InspectionReport": { - "@id": "https://w3id.org/traceability#InspectionReport", - "@context": { - "comment": { - "@id": "https://schema.org/comment" - }, - "inspectors": { - "@id": "https://schema.org/Person" - }, - "place": { - "@id": "https://schema.org/Place" - }, - "chemicalObservation": { - "@id": "https://schema.org/ItemList" - }, - "mechanicalObservation": { - "@id": "https://schema.org/ItemList" - } - } - }, - "Inspector": { - "@id": "https://w3id.org/traceability#Inspector", - "@context": { - "person": { - "@id": "https://schema.org/Person" - }, - "qualification": { - "@id": "https://w3id.org/traceability#qualification" - } - } - }, - "Instructions": { - "@id": "https://vocabulary.uncefact.org/TransportInstructions", - "@context": { - "description": { - "@id": "https://schema.org/description" - } - } - }, - "IntellectualPropertyRights": { - "@id": "https://w3id.org/traceability#IntellectualPropertyRights", - "@context": { - "intellectualPropertyRightsOwner": { - "@id": "https://w3id.org/traceability#intellectualPropertyRightsOwner" - }, - "intellectualPropertyRightsType": { - "@id": "https://w3id.org/traceability#intellectualPropertyRightsType" - }, - "intellectualPropertyRightsProduct": { - "@id": "https://w3id.org/traceability#intellectualPropertyRightsProduct" - } - } - }, - "IntellectualPropertyRightsAffirmation": { - "@id": "https://w3id.org/traceability#IntellectualPropertyRightsAffirmation", - "@context": { - "affirmingParty": { - "@id": "https://w3id.org/traceability#affirmingParty" - }, - "intellectualPropertyRightsType": { - "@id": "https://w3id.org/traceability#intellectualPropertyRightsType" - }, - "evidenceDocumentUrl": { - "@id": "https://schema.org/url" - } - } - }, - "IntellectualPropertyRightsLicense": { - "@id": "https://w3id.org/traceability#IntellectualPropertyRightsLicense", - "@context": {} - }, - "IntentToImport": { - "@id": "https://w3id.org/traceability#IntentToImport", - "@context": { - "exporter": { - "@id": "https://vocabulary.uncefact.org/exporterParty" - }, - "importer": { - "@id": "https://vocabulary.uncefact.org/importerParty" - }, - "product": { - "@id": "https://www.gs1.org/voc/Product" - }, - "declarationDate": { - "@id": "https://schema.org/startDate" - } - } - }, - "Invoice": { - "@id": "https://schema.org/Invoice", - "@context": { - "identifier": { - "@id": "https://schema.org/identifier" - }, - "invoiceNumber": { - "@id": "https://vocabulary.uncefact.org/invoiceIssuerReference" - }, - "customerReferenceNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#CR" - }, - "referencesOrder": { - "@id": "https://schema.org/referencesOrder" - }, - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "letterOfCreditNumber": { - "@id": "https://vocabulary.uncefact.org/letterOfCreditDocument" - }, - "portOfEntry": { - "@id": "https://schema.org/Place" - }, - "originCountry": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "destinationCountry": { - "@id": "https://vocabulary.uncefact.org/destinationCountry" - }, - "invoiceDate": { - "@id": "https://vocabulary.uncefact.org/invoiceDateTime" - }, - "purchaseDate": { - "@id": "https://schema.org/paymentDueDate" - }, - "seller": { - "@id": "https://vocabulary.uncefact.org/sellerParty" - }, - "buyer": { - "@id": "https://vocabulary.uncefact.org/buyerParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "itemsShipped": { - "@id": "https://schema.org/itemShipped" - }, - "comments": { - "@id": "https://schema.org/Comment" - }, - "packageQuantity": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "totalWeight": { - "@id": "https://schema.org/weight" - }, - "termsOfDelivery": { - "@id": "https://vocabulary.uncefact.org/specifiedDeliveryTerms" - }, - "termsOfPayment": { - "@id": "https://vocabulary.uncefact.org/specifiedPaymentTerms" - }, - "termsOfSettlement": { - "@id": "https://schema.org/currency" - }, - "totalPaymentDue": { - "@id": "https://schema.org/totalPaymentDue" - }, - "discounts": { - "@id": "https://schema.org/discount" - }, - "deductions": { - "@id": "https://vocabulary.uncefact.org/deductionAmount" - }, - "tax": { - "@id": "https://vocabulary.uncefact.org/taxTotalAmount" - }, - "freightCost": { - "@id": "https://schema.org/DeliveryChargeSpecification" - }, - "insuranceCost": { - "@id": "https://vocabulary.uncefact.org/insuranceChargeTotalAmount" - } - } - }, - "LEIaddress": { - "@id": "https://w3id.org/traceability#LEIaddress", - "@context": { - "language": { - "@id": "https://schema.org/Language" - }, - "addressNumberWithinBuilding": { - "@id": "https://schema.org/value" - }, - "mailRouting": { - "@id": "https://schema.org/Trip" - }, - "city": { - "@id": "https://schema.org/addressLocality" - }, - "region": { - "@id": "https://schema.org/addressRegion" - }, - "country": { - "@id": "https://schema.org/addressCountry" - }, - "postalCode": { - "@id": "https://schema.org/postalCode" - } - } - }, - "LEIauthority": { - "@id": "https://w3id.org/traceability#LEIauthority", - "@context": { - "validationAuthorityID": { - "@id": "https://schema.org/identifier" - }, - "otherValidationAuthorityID": { - "@id": "https://schema.org/taxID" - }, - "validationAuthorityEntityID": { - "@id": "https://schema.org/leiCode" - } - } - }, - "LEIentity": { - "@id": "https://w3id.org/traceability#LEIentity", - "@context": { - "legalName": { - "@id": "https://schema.org/legalName" - }, - "legalNameLanguage": { - "@id": "https://schema.org/Language" - }, - "legalAddress": { - "@id": "https://w3id.org/traceability#LEIaddress" - }, - "headquartersAddress": { - "@id": "https://schema.org/PostalAddress" - }, - "registrationAuthority": { - "@id": "https://w3id.org/traceability#LEIauthority" - }, - "legalJurisdiction": { - "@id": "https://schema.org/countryOfOrigin" - }, - "entityCategory": { - "@id": "https://schema.org/category" - }, - "legalForm": { - "@id": "https://schema.org/additionalType" - }, - "associatedEntity": { - "@id": "https://schema.org/Organization" - }, - "status": { - "@id": "https://schema.org/status" - }, - "expirationDate": { - "@id": "https://schema.org/expires" - }, - "expirationReason": { - "@id": "https://schema.org/Answer" - }, - "successorEntity": { - "@id": "https://schema.org/Corporation" - }, - "otherAddresses": { - "@id": "https://schema.org/Place" - } - } - }, - "LEIevidenceDocument": { - "@id": "https://w3id.org/traceability#LEIevidenceDocument", - "@context": { - "lei": { - "@id": "https://www.gleif.org/en/about-lei/iso-17442-the-lei-code-structure#" - }, - "entity": { - "@id": "https://w3id.org/traceability#LEIentity" - }, - "registration": { - "@id": "https://w3id.org/traceability#LEIregistration" - } - } - }, - "LEIregistration": { - "@id": "https://w3id.org/traceability#LEIregistration", - "@context": { - "initialRegistrationDate": { - "@id": "https://schema.org/dateIssued" - }, - "lastUpdateDate": { - "@id": "https://schema.org/dateModified" - }, - "status": { - "@id": "https://schema.org/status" - }, - "nextRenewalDate": { - "@id": "https://schema.org/validThrough" - }, - "managingLou": { - "@id": "https://www.gleif.org/en/about-lei/iso-17442-the-lei-code-structure#" - }, - "validationSources": { - "@id": "https://schema.org/eventStatus" - }, - "validationAuthority": { - "@id": "https://w3id.org/traceability#LEIauthority" - } - } - }, - "LaceyActProductDeclaration": { - "@id": "https://w3id.org/traceability#LaceyActProductDeclaration", - "@context": { - "htsNumber": { - "@id": "https://vocabulary.uncefact.org/applicableRegulatoryProcedure" - }, - "enteredValue": { - "@id": "https://vocabulary.uncefact.org/customsValueSpecifiedAmount" - }, - "articleOrComponent": { - "@id": "https://vocabulary.uncefact.org/procedureCode" - }, - "plantScientificNames": { - "@id": "https://w3id.org/traceability#Taxonomy" - }, - "countryOfHarvest": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "quantityOfPlantMaterial": { - "@id": "https://vocabulary.uncefact.org/totalPackageSpecifiedQuantity" - }, - "percentRecycled": { - "@id": "https://qudt.org/vocab/unit/PERCENT" - } - } - }, - "LinkRole": { - "@id": "https://schema.org/LinkRole", - "@context": { - "target": { - "@id": "https://schema.org/target" - }, - "linkRelationship": { - "@id": "https://schema.org/linkRelationship" - } - } - }, - "MapResource": { - "@id": "https://w3id.org/traceability#MapResource", - "@context": { - "resourceType": { - "@id": "https://schema.org/additionalType" - }, - "external": { - "@id": "https://w3id.org/traceability#ExternalResource" - }, - "geoJson": { - "@id": "https://schema.org/geo" - } - } - }, - "MasterBillOfLading": { - "@id": "https://w3id.org/traceability#MasterBillOfLading", - "@context": { - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "bookingNumber": { - "@id": "https://vocabulary.uncefact.org/carrierAssignedId" - }, - "shippersReferences": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" - }, - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "forwardingAgent": { - "@id": "https://vocabulary.uncefact.org/freightForwarderParty" - }, - "notifyParty": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "preCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" - }, - "mainCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" - }, - "onCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" - }, - "placeOfReceipt": { - "@id": "https://schema.org/Place" - }, - "portOfLoading": { - "@id": "https://vocabulary.uncefact.org/transshipmentLocation" - }, - "placeOfDelivery": { - "@id": "https://schema.org/Place" - }, - "portOfDischarge": { - "@id": "https://vocabulary.uncefact.org/unloadingLocation" - }, - "totalNumberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "transportEquipmentQuantity": { - "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" - }, - "includedConsignmentItems": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "utilizedTransportEquipment": { - "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" - }, - "freightAndCharges": { - "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" - }, - "declaredValue": { - "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" - }, - "shippedOnBoardDate": { - "@id": "https://schema.org/Date" - }, - "termsAndConditions": { - "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" - } - } - }, - "MeasuredProperty": { - "@id": "https://w3id.org/traceability#MeasuredProperty", - "@context": {} - }, - "MeasuredValue": { - "@id": "https://schema.org/QuantitativeValue", - "@context": { - "value": { - "@id": "https://schema.org/value" - }, - "unitCode": { - "@id": "https://schema.org/unitCode" - } - } - }, - "MechanicalProperty": { - "@id": "https://w3id.org/traceability#MechanicalProperty", - "@context": { - "identifier": { - "@id": "https://schema.org/identifier" - }, - "name": { - "@id": "https://schema.org/name" - }, - "description": { - "@id": "https://schema.org/description" - } - } - }, - "MonetaryAmount": { - "@id": "https://schema.org/MonetaryAmount", - "@context": { - "value": { - "@id": "https://schema.org/value" - }, - "currency": { - "@id": "https://schema.org/currency" - } - } - }, - "MonthlyAdvanceManifest": { - "@id": "https://w3id.org/traceability#MonthlyAdvanceManifest", - "@context": { - "date": { - "@id": "https://schema.org/Date" - } - } - }, - "MonthlyDeliveryStatement": { - "@id": "https://w3id.org/traceability#MonthlyDeliveryStatement", - "@context": { - "itemsDelivered": { - "@id": "https://w3id.org/traceability#DeliveryStatement" - } - } - }, - "MultiModalBillOfLading": { - "@id": "https://w3id.org/traceability#MultiModalBillOfLading", - "@context": { - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "bookingNumber": { - "@id": "https://vocabulary.uncefact.org/carrierAssignedId" - }, - "shippersReferences": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#SI" - }, - "freightForwardersReferences": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "forwardingAgent": { - "@id": "https://vocabulary.uncefact.org/freightForwarderParty" - }, - "notifyParty": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "carrier": { - "@id": "https://vocabulary.uncefact.org/carrierParty" - }, - "preCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" - }, - "mainCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" - }, - "onCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" - }, - "placeOfReceipt": { - "@id": "https://schema.org/Place" - }, - "portOfLoading": { - "@id": "https://vocabulary.uncefact.org/loadingLocation" - }, - "transshipmentLocation": { - "@id": "https://vocabulary.uncefact.org/transshipmentLocation" - }, - "placeOfDelivery": { - "@id": "https://schema.org/Place" - }, - "portOfDischarge": { - "@id": "https://vocabulary.uncefact.org/unloadingLocation" - }, - "totalNumberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "transportEquipmentQuantity": { - "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" - }, - "particulars": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "utilizedTransportEquipment": { - "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" - }, - "freightAndCharges": { - "@id": "https://vocabulary.uncefact.org/applicableServiceCharge" - }, - "declaredValue": { - "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" - }, - "shippedOnBoardDate": { - "@id": "https://schema.org/Date" - }, - "termsAndConditions": { - "@id": "https://vocabulary.uncefact.org/termsAndConditionsDescription" - } - } - }, - "NAISMADateTime": { - "@id": "https://w3id.org/traceability#NAISMADateTime", - "@context": { - "collectionDate": { - "@id": "http://rs.tdwg.org/dwc/terms/eventDate" - }, - "dateAccuracyDays": { - "@id": "http://rs.tdwg.org/dwc/iri/measurementMethod" - } - } - }, - "NAISMAInfestation": { - "@id": "https://w3id.org/traceability#NAISMAInfestation", - "@context": { - "infestedArea": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "areaSurveyed": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "incidence": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "severity": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementValue" - }, - "severityUnits": { - "@id": "https://schema.org/unitText" - }, - "organismQuantity": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "organismQuantityUnits": { - "@id": "https://schema.org/unitText" - } - } - }, - "NAISMAInformationSource": { - "@id": "https://w3id.org/traceability#NAISMAInformationSource", - "@context": { - "reference": { - "@id": "http://rs.tdwg.org/dwc/terms/associatedReferences" - }, - "examiner": { - "@id": "http://rs.tdwg.org/dwc/terms/recordedBy" - }, - "dataSource": { - "@id": "https://w3id.org/traceability#Entity" - } - } - }, - "NAISMALocation": { - "@id": "https://w3id.org/traceability#NAISMALocation", - "@context": { - "location": { - "@id": "https://w3id.org/traceability#Place" - }, - "description": { - "@id": "https://schema.org/description" - }, - "datum": { - "@id": "http://rs.tdwg.org/dwc/terms/geodeticDatum" - }, - "wellKnownText": { - "@id": "http://rs.tdwg.org/dwc/terms/footprintWKT" - }, - "centroidType": { - "@id": "https://schema.org/polygon" - }, - "dataType": { - "@id": "https://schema.org/additionalType" - }, - "coordinateUncertainty": { - "@id": "http://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters" - }, - "sourceOfLocation": { - "@id": "http://rs.tdwg.org/dwc/terms/georeferenceProtocol" - }, - "ecosystem": { - "@id": "http://rs.tdwg.org/dwc/terms/locationRemarks" - } - } - }, - "NAISMARecordLevelIdentifiers": { - "@id": "https://w3id.org/traceability#NAISMARecordLevelIdentifiers", - "@context": { - "uuid": { - "@id": "http://rs.tdwg.org/dwc/terms/resourceID" - }, - "pid": { - "@id": "https://schema.org/identifier" - }, - "catalogNumber": { - "@id": "http://rs.tdwg.org/dwc/terms/catalogNumber" - } - } - }, - "NAISMARecordStatus": { - "@id": "https://w3id.org/traceability#NAISMARecordStatus", - "@context": { - "occurrenceStatus": { - "@id": "https://schema.org/status" - }, - "populationStatus": { - "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" - }, - "managementStatus": { - "@id": "https://schema.org/status" - }, - "recordBasis": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" - }, - "recordType": { - "@id": "https://schema.org/description" - }, - "method": { - "@id": "http://rs.tdwg.org/dwc/terms/measurementMethod" - }, - "verificationMethod": { - "@id": "http://rs.tdwg.org/dwc/terms/identificationRemarks" - } - } - }, - "NAISMASubject": { - "@id": "https://w3id.org/traceability#NAISMASubject", - "@context": { - "lifeStage": { - "@id": "http://rs.tdwg.org/dwc/terms/lifeStage" - }, - "sex": { - "@id": "http://rs.tdwg.org/dwc/terms/sex" - }, - "hostSpecies": { - "@id": "https://w3id.org/traceability#Taxonomy" - }, - "comments": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - } - } - }, - "NAISMATaxonomy": { - "@id": "https://w3id.org/traceability#NAISMATaxonomy", - "@context": { - "speciesName": { - "@id": "https://w3id.org/traceability#Taxonomy" - }, - "commonName": { - "@id": "http://rs.tdwg.org/dwc/terms/vernacularName" - }, - "taxonomicSerialNumber": { - "@id": "http://rs.tdwg.org/dwc/terms/taxonID" - } - } - }, - "Observation": { - "@id": "https://schema.org/Observation", - "@context": { - "property": { - "@id": "https://schema.org/measuredProperty" - }, - "measurement": { - "@id": "https://w3id.org/traceability#MeasuredValue" - }, - "date": { - "@id": "https://schema.org/observationDate" - } - } - }, - "OilAndGasDeliveryTicket": { - "@id": "https://w3id.org/traceability#OilAndGasDeliveryTicket", - "@context": { - "createdDate": { - "@id": "https://schema.org/dateIssued" - }, - "openDate": { - "@id": "https://schema.org/startDate" - }, - "closeDate": { - "@id": "https://schema.org/endDate" - }, - "transporter": { - "@id": "https://schema.org/agent" - }, - "consignor": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "ticketControlNumber": { - "@id": "https://schema.org/ticketNumber" - }, - "batchNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BT" - }, - "place": { - "@id": "https://schema.org/toLocation" - }, - "product": { - "@id": "https://www.gs1.org/voc/Product" - }, - "observation": { - "@id": "https://w3id.org/traceability#observation" - } - } - }, - "OilAndGasProduct": { - "@id": "https://w3id.org/traceability#OilAndGasProduct", - "@context": { - "product": { - "@id": "https://www.gs1.org/voc/Product" - }, - "facility": { - "@id": "https://www.gs1.org/voc/Place" - }, - "UWI": { - "@id": "https://schema.org/identifier" - }, - "productionDate": { - "@id": "https://schema.org/DateTime" - }, - "observation": { - "@id": "https://w3id.org/traceability#observation" - } - } - }, - "Order": { - "@id": "https://schema.org/Order", - "@context": { - "orderNumber": { - "@id": "https://schema.org/orderNumber" - }, - "orderedItems": { - "@id": "https://schema.org/orderedItem" - } - } - }, - "OrderItem": { - "@id": "https://schema.org/OrderItem", - "@context": { - "marketplace": { - "@id": "https://vocabulary.uncefact.org/Marketplace" - }, - "fulfillmentCenter": { - "@id": "https://vocabulary.uncefact.org/logisticsServiceProviderParty" - }, - "orderedItem": { - "@id": "https://schema.org/orderedItem" - }, - "orderedQuantity": { - "@id": "https://schema.org/orderQuantity" - } - } - }, - "OrganicCertification": { - "@id": "https://w3id.org/traceability#OrganicCertification", - "@context": { - "countryOfIssuance": { - "@id": "https://www.gs1.org/voc/countryCode" - }, - "certifiedOperation": { - "@id": "https://www.gs1.org/voc/certificationSubject" - }, - "certifyingAgent": { - "@id": "https://www.gs1.org/voc/certificationAgency" - }, - "effectiveDate": { - "@id": "https://www.gs1.org/voc/certificationStartDate" - }, - "issueDate": { - "@id": "https://www.gs1.org/voc/initialCertificationDate" - }, - "anniversaryDate": { - "@id": "https://www.gs1.org/voc/certificationEndDate" - }, - "operationCategory": { - "@id": "https://www.gs1.org/voc/certificationStatement" - }, - "organicProducts": { - "@id": "https://www.gs1.org/voc/certificationStatement" - } - } - }, - "OrganicInspection": { - "@id": "https://w3id.org/traceability#OrganicInspection", - "@context": { - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "applicantCertificationNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "authorizedOperationContacts": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "peoplePresent": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "newApplicant": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "continuingCertification": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "newLocationActivity": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "reinstatement": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "announcedInspection": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "estimatedHarvestDate": { - "@id": "https://www.gs1.org/voc/harvestDate" - }, - "pesticideResidueSampling": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "samplingDetails": { - "@id": "https://vocabulary.uncefact.org/content" - }, - "introductionOperationDescription": { - "@id": "https://schema.org/description" - }, - "resolutionIssuesActionItems": { - "@id": "https://schema.org/description" - }, - "issuesRequests": { - "@id": "https://vocabulary.uncefact.org/additionalDescription" - }, - "attachments": { - "@id": "https://vocabulary.uncefact.org/additionalDocument" - }, - "OSPSectionReviews": { - "@id": "https://w3id.org/traceability#OrganicOSPSectionReview" - } - } - }, - "OrganicOSPSectionReview": { - "@id": "https://w3id.org/traceability#OrganicOSPSectionReview", - "@context": { - "OSPSectionCode": { - "@id": "https://vocabulary.uncefact.org/standard" - }, - "resultCode": { - "@id": "https://vocabulary.uncefact.org/assertionCode" - }, - "verificationExplanations": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "attachments": { - "@id": "https://vocabulary.uncefact.org/additionalDocument" - } - } - }, - "OrganicProductCertification": { - "@id": "https://w3id.org/traceability#OrganicProductCertification", - "@context": { - "agricultureProduct": { - "@id": "https://www.gs1.org/voc/certificationSubject" - }, - "organicCertification": { - "@id": "https://www.gs1.org/voc/certification" - }, - "isCertified": { - "@id": "https://www.gs1.org/voc/certificationStatus" - } - } - }, - "OrganicReview": { - "@id": "https://w3id.org/traceability#OrganicReview", - "@context": { - "inspectionReport": { - "@id": "https://w3id.org/traceability#OrganicInspection" - }, - "reviewer": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "decisionMaker": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "certificationDecision": { - "@id": "https://www.gs1.org/voc/certificationStatus" - }, - "additionalInformation": { - "@id": "https://vocabulary.uncefact.org/content" - } - } - }, - "Organization": { - "@id": "https://schema.org/Organization", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "legalName": { - "@id": "https://schema.org/legalName" - }, - "leiCode": { - "@id": "https://schema.org/leiCode" - }, - "url": { - "@id": "https://schema.org/url" - }, - "description": { - "@id": "https://schema.org/description" - }, - "globalLocationNumber": { - "@id": "https://schema.org/globalLocationNumber" - }, - "location": { - "@id": "https://schema.org/location" - }, - "email": { - "@id": "https://schema.org/email" - }, - "phoneNumber": { - "@id": "https://schema.org/telephone" - }, - "logo": { - "@id": "https://schema.org/logo" - }, - "faxNumber": { - "@id": "https://schema.org/faxNumber" - }, - "contactPoint": { - "@id": "https://schema.org/ContactPoint" - }, - "taxId": { - "@id": "https://schema.org/taxID" - }, - "iataCarrierCode": { - "@id": "https://onerecord.iata.org/cargo/Company#airlineCode" - }, - "scac": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AAZ" - } - } - }, - "PGAShipmentStatus": { - "@id": "https://w3id.org/traceability#PGAShipmentStatus", - "@context": { - "recordNo": { - "@id": "https://w3id.org/traceability#recordNo" - }, - "entryNo": { - "@id": "https://w3id.org/traceability#entryNo" - }, - "entryLineSequence": { - "@id": "https://w3id.org/traceability#entryLineSequence" - }, - "statusCode": { - "@id": "https://w3id.org/traceability#statusCode" - }, - "statusCodeDescription": { - "@id": "https://w3id.org/traceability#statusCodeDescription" - }, - "validCodeReason": { - "@id": "https://w3id.org/traceability#validCodeReason" - }, - "validCodeReasonDescription": { - "@id": "https://w3id.org/traceability#validCodeReasonDescription" - }, - "subReasonCode": { - "@id": "https://w3id.org/traceability#subReasonCode" - }, - "subReasonCodeDescription": { - "@id": "https://w3id.org/traceability#subReasonCodeDescription" - } - } - }, - "PGAShipmentStatusList": { - "@id": "https://w3id.org/traceability#PGAShipmentStatusList", - "@context": { - "pgaShipmentStatusItems": { - "@id": "https://schema.org/ItemList" - } - } - }, - "Package": { - "@id": "https://vocabulary.uncefact.org/Package", - "@context": { - "physicalShippingMarks": { - "@id": "https://vocabulary.uncefact.org/physicalShippingMarks" - }, - "packagingType": { - "@id": "https://www.gs1.org/voc/packagingMaterial" - }, - "perPackageUnitQuantity": { - "@id": "https://vocabulary.uncefact.org/perPackageUnitQuantity" - }, - "includedTradeLineItems": { - "@id": "https://vocabulary.uncefact.org/specifiedTradeLineItem" - }, - "netWeight": { - "@id": "https://vocabulary.uncefact.org/netWeightMeasure" - }, - "grossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "height": { - "@id": "https://schema.org/height" - }, - "width": { - "@id": "https://schema.org/width" - }, - "depth": { - "@id": "https://schema.org/depth" - }, - "grossVolume": { - "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" - } - } - }, - "PackingList": { - "@id": "https://w3id.org/traceability#PackingList", - "@context": { - "seller": { - "@id": "https://vocabulary.uncefact.org/sellerParty" - }, - "buyer": { - "@id": "https://vocabulary.uncefact.org/buyerParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "shipFromParty": { - "@id": "https://vocabulary.uncefact.org/shipFromParty" - }, - "shipToParty": { - "@id": "https://vocabulary.uncefact.org/shipToParty" - }, - "orderNumber": { - "@id": "https://schema.org/orderNumber" - }, - "invoiceId": { - "@id": "https://schema.org/identifier" - }, - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "trackingNumber": { - "@id": "https://schema.org/trackingNumber" - }, - "deliveryStatus": { - "@id": "https://schema.org/deliveryStatus" - }, - "estimatedTimeOfArrival": { - "@id": "https://schema.org/arrivalTime" - }, - "hasDeliveryMethod": { - "@id": "https://schema.org/hasDeliveryMethod" - }, - "handlingInstructions": { - "@id": "https://vocabulary.uncefact.org/handlingInstructions" - }, - "items": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "totalNetWeight": { - "@id": "https://vocabulary.uncefact.org/netWeightMeasure" - }, - "totalGrossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "totalGrossVolume": { - "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" - }, - "totalNumberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "totalItemQuantity": { - "@id": "https://vocabulary.uncefact.org/tradeLineItemQuantity" - } - } - }, - "ParcelDelivery": { - "@id": "https://schema.org/ParcelDelivery", - "@context": { - "deliveryAddress": { - "@id": "https://schema.org/deliveryAddress" - }, - "originAddress": { - "@id": "https://schema.org/originAddress" - }, - "deliveryMethod": { - "@id": "https://schema.org/DeliveryMethod" - }, - "trackingNumber": { - "@id": "https://schema.org/trackingNumber" - }, - "expectedArrival": { - "@id": "https://schema.org/expectedArrivalFrom" - }, - "specialInstructions": { - "@id": "https://schema.org/comment" - }, - "consignee": { - "@id": "https://schema.org/Organization" - }, - "item": { - "@id": "https://schema.org/itemShipped" - }, - "partOfOrder": { - "@id": "https://schema.org/partOfOrder" - } - } - }, - "PartOfOrder": { - "@id": "https://schema.org/OrderItem", - "@context": { - "manufacturer": { - "@id": "https://schema.org/Organization" - }, - "orderNumber": { - "@id": "https://schema.org/orderNumber" - }, - "transportPackages": { - "@id": "https://vocabulary.uncefact.org/Package" - }, - "netWeight": { - "@id": "https://vocabulary.uncefact.org/netWeightMeasure" - }, - "grossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "grossVolume": { - "@id": "https://vocabulary.uncefact.org/grossVolumeMeasure" - }, - "packageQuantity": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "itemQuantity": { - "@id": "https://vocabulary.uncefact.org/tradeLineItemQuantity" - } - } - }, - "Person": { - "@id": "https://schema.org/Person", - "@context": { - "firstName": { - "@id": "https://schema.org/givenName" - }, - "lastName": { - "@id": "https://schema.org/familyName" - }, - "email": { - "@id": "https://schema.org/email" - }, - "phoneNumber": { - "@id": "https://schema.org/telephone" - }, - "worksFor": { - "@id": "https://schema.org/worksFor" - }, - "jobTitle": { - "@id": "https://schema.org/jobTitle" - }, - "taxId": { - "@id": "https://schema.org/taxID" - } - } - }, - "PestDetermination": { - "@id": "https://w3id.org/traceability#PestDetermination", - "@context": { - "final": { - "@id": "https://dwc.tdwg.org/list/#dwc_identificationVerificationStatus" - }, - "determination": { - "@id": "https://w3id.org/traceability#Taxonomy" - }, - "notes": { - "@id": "https://dwc.tdwg.org/list/#dwc_identificationRemarks" - }, - "method": { - "@id": "https://dwc.tdwg.org/list/#dwc_measurementMethod" - }, - "reportable": { - "@id": "https://dwc.tdwg.org/list/#dwc_occurrenceStatus" - }, - "determinedBy": { - "@id": "https://dwc.tdwg.org/list/#dwc_identifiedBy" - }, - "date": { - "@id": "https://dwc.tdwg.org/list/#dwc_dateIdentified" - } - } - }, - "PestSample": { - "@id": "https://w3id.org/traceability#PestSample", - "@context": { - "hostName": { - "@id": "https://w3id.org/traceability#Taxonomy" - }, - "hostQuantity": { - "@id": "http://rs.tdwg.org/dwc/terms/organismQuantity" - }, - "affected": { - "@id": "https://dwc.tdwg.org/list/#dwc_measurementValue" - }, - "plantDistribution": { - "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" - }, - "plantPartsAffected": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - }, - "pestDistribution": { - "@id": "http://rs.tdwg.org/dwc/terms/degreeOfEstablishment" - }, - "pestProximity": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - }, - "pestType": { - "@id": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks" - }, - "aliveLarvae": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "alivePupae": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "aliveAdults": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "aliveEggs": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "aliveNymphs": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "aliveJuveniles": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "aliveCysts": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadLarvae": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadPupae": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadAdults": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadEggs": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadNymphs": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadJuveniles": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "deadCysts": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "castSkins": { - "@id": "http://rs.tdwg.org/dwc/terms/individualCount" - }, - "samplingMethod": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" - }, - "trapLureType": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" - }, - "trapNumber": { - "@id": "http://rs.tdwg.org/dwc/terms/samplingProtocol" - } - } - }, - "Phytosanitary": { - "@id": "https://w3id.org/traceability/Phytosanitary", - "@context": { - "certificateNumber": { - "@id": "https://schema.org/identifier" - }, - "plantOrg": { - "@id": "https://www.gs1.org/voc/Organization" - }, - "distinguishingMarks": { - "@id": "https://www.gs1.org/voc/variantDescription" - }, - "portOfEntry": { - "@id": "https://w3id.org/traceability#portOfEntry" - }, - "additionalDeclaration": { - "@id": "https://schema.org/Comment" - }, - "disinfectionDate": { - "@id": "https://schema.org/validFrom" - }, - "disinfectionTreatment": { - "@id": "https://w3id.org/traceability#disinfectionTreatment" - }, - "disinfectionChemical": { - "@id": "https://schema.org/activeIngredient" - }, - "disinfectionDuration": { - "@id": "https://schema.org/duration" - }, - "disinfectionTemperature": { - "@id": "https://schema.org/MeasuredValue" - }, - "disinfectionConcentration": { - "@id": "https://w3id.org/traceability#disinfectionConcentration" - }, - "signatureDate": { - "@id": "https://schema.org/DateTime" - }, - "facility": { - "@id": "https://www.gs1.org/voc/Place" - }, - "inspector": { - "@id": "https://w3id.org/traceability#Inspector" - }, - "shipment": { - "@id": "https://schema.org/AgricultureParcelDelivery" - }, - "agriculturePackage": { - "@id": "https://w3id.org/traceability#AgriculturePackage" - }, - "applicant": { - "@id": "https://w3c-ccg.github.io/traceability-vocab/#dfn-entities" - }, - "inspectionDate": { - "@id": "https://schema.org/DateTime" - }, - "inspectionType": { - "@id": "https://vocabulary.uncefact.org/inspectionStandard" - }, - "notes": { - "@id": "https://schema.org/Comment" - }, - "observation": { - "@id": "https://schema.org/ItemList" - } - } - }, - "Place": { - "@id": "https://schema.org/Place", - "@context": { - "globalLocationNumber": { - "@id": "https://schema.org/globalLocationNumber" - }, - "geo": { - "@id": "https://schema.org/GeoCoordinates" - }, - "address": { - "@id": "https://schema.org/PostalAddress" - }, - "unLocode": { - "@id": "https://vocabulary.uncefact.org/Location" - }, - "iataAirportCode": { - "@id": "https://onerecord.iata.org/cargo/Location#code" - }, - "locationName": { - "@id": "https://schema.org/name" - }, - "usPortCode": { - "@id": "https://w3id.org/traceability#usPortCode" - }, - "firmsCode": { - "@id": "https://w3id.org/traceability#firmsCode" - } - } - }, - "PlantSystemsInspection": { - "@id": "https://w3id.org/traceability#PlantSystemsInspection", - "@context": { - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "productsPacked": { - "@id": "https://vocabulary.uncefact.org/specifiedProduct" - }, - "summaryOfDeficiencies": { - "@id": "https://schema.org/description" - }, - "observationsImprovements": { - "@id": "https://schema.org/description" - }, - "questions": { - "@id": "https://w3id.org/traceability#PlantSystemsQuestion" - }, - "additionalViolations": { - "@id": "https://schema.org/description" - } - } - }, - "PlantSystemsQuestion": { - "@id": "https://w3id.org/traceability#PlantSystemsQuestion", - "@context": { - "code": { - "@id": "https://schema.org/identifier" - }, - "pointsWorth": { - "@id": "https://schema.org/ratingValue" - }, - "pointsDeducted": { - "@id": "https://schema.org/ratingValue" - } - } - }, - "PostalAddress": { - "@id": "https://schema.org/PostalAddress", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "streetAddress": { - "@id": "https://schema.org/streetAddress" - }, - "addressLocality": { - "@id": "https://schema.org/addressLocality" - }, - "addressRegion": { - "@id": "https://schema.org/addressRegion" - }, - "addressCountry": { - "@id": "https://schema.org/addressCountry" - }, - "crossStreet": { - "@id": "https://gs1.org/voc/crossStreet" - }, - "countyCode": { - "@id": "https://gs1.org/voc/countyCode" - }, - "postalCode": { - "@id": "https://schema.org/postalCode" - }, - "postOfficeBoxNumber": { - "@id": "https://schema.org/postOfficeBoxNumber" - }, - "plantOrSiteName": { - "@id": "https://vocabulary.uncefact.org/buildingName" - } - } - }, - "PostmanCollection": { - "@id": "https://w3id.org/traceability#PostmanCollection", - "@context": {} - }, - "PriceSpecification": { - "@id": "https://schema.org/PriceSpecification", - "@context": { - "price": { - "@id": "https://schema.org/price" - }, - "priceCurrency": { - "@id": "https://schema.org/priceCurrency" - } - } - }, - "Product": { - "@id": "https://schema.org/Product", - "@context": { - "gtin": { - "@id": "https://schema.org/gtin" - }, - "manufacturer": { - "@id": "https://schema.org/manufacturer" - }, - "countryOfOrigin": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "name": { - "@id": "https://schema.org/name" - }, - "description": { - "@id": "https://schema.org/description" - }, - "category": { - "@id": "https://schema.org/category" - }, - "sizeOrAmount": { - "@id": "https://schema.org/size" - }, - "weight": { - "@id": "https://schema.org/weight" - }, - "depth": { - "@id": "https://schema.org/depth" - }, - "width": { - "@id": "https://schema.org/width" - }, - "height": { - "@id": "https://schema.org/height" - }, - "productPrice": { - "@id": "https://schema.org/priceSpecification" - }, - "sku": { - "@id": "https://schema.org/sku" - }, - "batchNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BT" - }, - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "seller": { - "@id": "https://vocabulary.uncefact.org/sellerParty" - }, - "images": { - "@id": "https://schema.org/image" - }, - "imageUrl": { - "@id": "https://schema.org/url" - }, - "imageHash": { - "@id": "https://schema.org/sha256" - }, - "htsCode": { - "@id": "https://service.unece.org/trade/uncefact/vocabulary/uncefact/#applicableTax" - } - } - }, - "Purchase": { - "@id": "https://w3id.org/traceability#Purchase", - "@context": { - "customer": { - "@id": "https://w3id.org/traceability#Entity" - }, - "invoice": { - "@id": "https://w3id.org/traceability#Invoice" - }, - "invoiceNo": { - "@id": "https://schema.org/identifier" - }, - "internalCertificateNo": { - "@id": "https://schema.org/identifier" - }, - "purchaseOrderNo": { - "@id": "https://schema.org/identifier" - } - } - }, - "PurchaseOrder": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#105", - "@context": { - "purchaseOrderNo": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AUJ" - }, - "orderDate": { - "@id": "https://vocabulary.uncefact.org/buyerOrderDateTime" - }, - "buyer": { - "@id": "https://vocabulary.uncefact.org/buyerParty" - }, - "seller": { - "@id": "https://vocabulary.uncefact.org/sellerParty" - }, - "shipToParty": { - "@id": "https://vocabulary.uncefact.org/shipToParty" - }, - "itemsOrdered": { - "@id": "https://vocabulary.uncefact.org/SupplyChainTradeLineItem" - }, - "comments": { - "@id": "https://schema.org/Comment" - }, - "totalWeight": { - "@id": "https://schema.org/weight" - }, - "termsOfDelivery": { - "@id": "https://vocabulary.uncefact.org/specifiedDeliveryTerms" - }, - "termsOfPayment": { - "@id": "https://vocabulary.uncefact.org/specifiedPaymentTerms" - }, - "totalPaymentDue": { - "@id": "https://schema.org/totalPaymentDue" - }, - "discounts": { - "@id": "https://vocabulary.uncefact.org/deductionAmount" - }, - "tax": { - "@id": "https://vocabulary.uncefact.org/taxTotalAmount" - }, - "freightCost": { - "@id": "https://schema.org/DeliveryChargeSpecification" - }, - "insuranceCost": { - "@id": "https://vocabulary.uncefact.org/insuranceChargeTotalAmount" - }, - "totalOrderAmount": { - "@id": "https://vocabulary.uncefact.org/grandTotalAmount" - } - } - }, - "Qualification": { - "@id": "https://schema.org/qualifications", - "@context": { - "qualificationCategory": { - "@id": "https://schema.org/credentialCategory" - }, - "qualificationValue": { - "@id": "https://schema.org/hasCredential" - } - } - }, - "QuantitativeValue": { - "@id": "https://schema.org/QuantitativeValue", - "@context": { - "unitCode": { - "@id": "https://schema.org/unitCode" - }, - "value": { - "@id": "https://schema.org/value" - } - } - }, - "RawMaterial": { - "@id": "https://w3id.org/traceability#RawMaterial", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "inchiKey": { - "@id": "https://w3id.org/traceability#inchiKey" - } - } - }, - "RevocationList2020Status": { - "@id": "https://w3id.org/traceability#RevocationList2020Status", - "@context": { - "revocationListIndex": { - "@id": "https://schema.org/itemListElement" - }, - "revocationListCredential": { - "@id": "https://schema.org/LinkRole" - } - } - }, - "RoutingInfo": { - "@id": "https://w3id.org/traceability#RoutingInfo", - "@context": { - "code": { - "@id": "https://w3id.org/traceability#routingInfoCode" - }, - "value": { - "@id": "https://w3id.org/traceability#routingInfoValue" - } - } - }, - "SIMASteelImportLicense": { - "@id": "https://w3id.org/traceability#SIMASteelImportLicense", - "@context": { - "licenseNumber": { - "@id": "https://schema.org/identifier" - }, - "licensedCompany": { - "@id": "https://vocabulary.uncefact.org/grantedParty" - }, - "customsEntryNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AQM" - }, - "importer": { - "@id": "https://vocabulary.uncefact.org/importerParty" - }, - "exporter": { - "@id": "https://vocabulary.uncefact.org/exporterParty" - }, - "manufacturer": { - "@id": "https://vocabulary.uncefact.org/manufacturerParty" - }, - "countryOfOrigin": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "countryOfExportation": { - "@id": "https://vocabulary.uncefact.org/exportCountry" - }, - "expectedPortOfEntry": { - "@id": "https://vocabulary.uncefact.org/LocationFunctionCodeList#24" - }, - "expectedDateOfExport": { - "@id": "https://vocabulary.uncefact.org/DateTimePeriodFunctionCodeList#129" - }, - "expectedDateOfImport": { - "@id": "https://vocabulary.uncefact.org/DateTimePeriodFunctionCodeList#151" - }, - "productInformation": { - "@id": "https://w3id.org/traceability#productInformation" - } - } - }, - "SIMASteelImportProductSpecifier": { - "@id": "https://w3id.org/traceability#SIMASteelImportProductSpecifier", - "@context": { - "productCategory": { - "@id": "https://w3id.org/traceability#ProductCategory" - }, - "countryOfMeltAndPour": { - "@id": "https://w3id.org/traceability#countryOfMeltAndPour" - }, - "customsValue": { - "@id": "https://vocabulary.uncefact.org/declaredValueForCustomsAmount" - } - } - }, - "OssfScorecard": { - "@id": "https://w3id.org/traceability#OssfScorecard", - "@context": {} - }, - "SeaCargoManifest": { - "@id": "https://w3id.org/traceability#SeaCargoManifest", - "@context": { - "vesselName": { - "@id": "https://vocabulary.uncefact.org/transportMeans" - }, - "vesselNumber": { - "@id": "https://schema.org/identifier" - }, - "voyageNumber": { - "@id": "https://vocabulary.uncefact.org/TransportMovement" - }, - "registrationCountry": { - "@id": "https://vocabulary.uncefact.org/registrationCountry" - }, - "plannedDepartureDateTime": { - "@id": "https://schema.org/Date" - }, - "plannedArrivalDateTime": { - "@id": "https://schema.org/DateTime" - }, - "portOfDeparture": { - "@id": "https://schema.org/Place" - }, - "portOfArrival": { - "@id": "https://schema.org/Place" - }, - "netTonnage": { - "@id": "https://vocabulary.uncefact.org/netWeightMeasure" - }, - "grossTonnage": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "totalNumberOfTransportDocuments": { - "@id": "https://schema.org/Number" - }, - "transportEquipmentQuantity": { - "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" - }, - "totalNumberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "transportDocumentInformation": { - "@id": "https://vocabulary.uncefact.org/transportContractDocument" - } - } - }, - "Seal": { - "@id": "https://vocabulary.uncefact.org/Seal", - "@context": { - "sealNumber": { - "@id": "https://vocabulary.uncefact.org/identifier" - }, - "sealSource": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/sealSource" - }, - "sealType": { - "@id": "https://vocabulary.uncefact.org/logisticsSealTypeCode" - } - } - }, - "ServiceCharge": { - "@id": "https://vocabulary.uncefact.org/ServiceCharge", - "@context": { - "chargeCode": { - "@id": "https://vocabulary.uncefact.org/chargeCategoryCode" - }, - "paymentTerm": { - "@id": "https://vocabulary.uncefact.org/PaymentTerms" - }, - "chargeText": { - "@id": "https://schema.org/description" - }, - "rate": { - "@id": "https://vocabulary.uncefact.org/unitPrice" - }, - "calculationBasis": { - "@id": "https://vocabulary.uncefact.org/calculationBasis" - }, - "appliedAmount": { - "@id": "https://vocabulary.uncefact.org/appliedAmount" - } - } - }, - "ShippingDetails": { - "@id": "https://w3id.org/traceability#ShippingDetails", - "@context": { - "containerNumber": { - "@id": "https://w3id.org/traceability#containerNumber" - }, - "masterBillOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/uncl1153#MB" - }, - "manufacturerAddress": { - "@id": "https://w3id.org/traceability#manufacturerAddress" - }, - "customerAddress": { - "@id": "https://w3id.org/traceability#customerAddress" - } - } - }, - "ShippingInstructions": { - "@id": "https://w3id.org/traceability#ShippingInstructions", - "@context": { - "billOfLadingNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#BM" - }, - "bookingNumber": { - "@id": "https://vocabulary.uncefact.org/carrierAssignedId" - }, - "shippersReferences": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#FF" - }, - "shipper": { - "@id": "https://vocabulary.uncefact.org/consignorParty" - }, - "consignee": { - "@id": "https://vocabulary.uncefact.org/consigneeParty" - }, - "notifyParty": { - "@id": "https://vocabulary.uncefact.org/notifiedParty" - }, - "preCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/preCarriageTransportMovement" - }, - "mainCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/mainCarriageTransportMovement" - }, - "onCarriageTransportMovement": { - "@id": "https://vocabulary.uncefact.org/onCarriageTransportMovement" - }, - "placeOfReceipt": { - "@id": "https://schema.org/Place" - }, - "portOfLoading": { - "@id": "https://vocabulary.uncefact.org/transshipmentLocation" - }, - "placeOfDelivery": { - "@id": "https://schema.org/Place" - }, - "portOfDischarge": { - "@id": "https://vocabulary.uncefact.org/unloadingLocation" - }, - "totalNumberOfPackages": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "transportEquipmentQuantity": { - "@id": "https://vocabulary.uncefact.org/transportEquipmentQuantity" - }, - "includedConsignmentItems": { - "@id": "https://vocabulary.uncefact.org/includedConsignmentItem" - }, - "utilizedTransportEquipment": { - "@id": "https://vocabulary.uncefact.org/utilizedTransportEquipment" - }, - "declaredValue": { - "@id": "https://vocabulary.uncefact.org/declaredValueForCarriageAmount" - } - } - }, - "SoftwareBillOfMaterials": { - "@id": "https://w3id.org/traceability#SoftwareBillOfMaterials", - "@context": {} - }, - "SteelProduct": { - "@id": "https://w3id.org/traceability#SteelProduct", - "@context": { - "heatNumber": { - "@id": "https://schema.org/identifier" - }, - "specification": { - "@id": "https://schema.org/identifier" - }, - "grade": { - "@id": "https://schema.org/Rating" - }, - "weight": { - "@id": "https://schema.org/weight" - }, - "weightUnit": { - "@id": "http://qudt.org/schema/qudt/Unit" - }, - "originalCountryOfMeltAndPour": { - "@id": "https://schema.org/addressCountry" - }, - "commodity": { - "@id": "https://w3id.org/traceability#Commodity" - }, - "inspection": { - "@id": "https://w3id.org/traceability#Inspection" - } - } - }, - "Taxonomy": { - "@id": "https://w3id.org/traceability#Taxonomy", - "@context": { - "kingdom": { - "@id": "http://rs.tdwg.org/dwc/terms/kingdom" - }, - "phylum": { - "@id": "http://rs.tdwg.org/dwc/terms/phylum" - }, - "class": { - "@id": "http://rs.tdwg.org/dwc/terms/class" - }, - "order": { - "@id": "http://rs.tdwg.org/dwc/terms/order" - }, - "family": { - "@id": "http://rs.tdwg.org/dwc/terms/family" - }, - "genus": { - "@id": "http://rs.tdwg.org/dwc/terms/genus" - }, - "species": { - "@id": "http://rs.tdwg.org/dwc/terms/specificEpithet" - }, - "subspecies": { - "@id": "http://rs.tdwg.org/dwc/terms/infraspecificEpithet" - }, - "variety": { - "@id": "http://rs.tdwg.org/dwc/terms/cultivarEpithet" - } - } - }, - "TemperatureReading": { - "@id": "https://w3id.org/traceability#TemperatureReading", - "@context": { - "bulbNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "tests": { - "@id": "https://vocabulary.uncefact.org/actualMeasure" - } - } - }, - "Template": { - "@id": "https://w3id.org/traceability#Template", - "@context": { - "image": { - "@id": "https://schema.org/image" - } - } - }, - "Thing": { - "@id": "https://schema.org/Thing", - "@context": {} - }, - "TraceabilityAPI": { - "@id": "https://w3id.org/traceability#TraceabilityAPI", - "@context": {} - }, - "TradeLineItem": { - "@id": "https://vocabulary.uncefact.org/SupplyChainTradeLineItem", - "@context": { - "name": { - "@id": "https://schema.org/name" - }, - "purchaseOrderNumber": { - "@id": "https://schema.org/orderNumber" - }, - "itemCount": { - "@id": "https://vocabulary.uncefact.org/despatchedQuantity" - }, - "description": { - "@id": "https://schema.org/description" - }, - "packageQuantity": { - "@id": "https://vocabulary.uncefact.org/packageQuantity" - }, - "product": { - "@id": "https://schema.org/Product" - }, - "countryOfOrigin": { - "@id": "https://vocabulary.uncefact.org/originCountry" - }, - "shipToParty": { - "@id": "https://vocabulary.uncefact.org/shipToParty" - }, - "netWeight": { - "@id": "https://vocabulary.uncefact.org/netWeightMeasure" - }, - "grossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "priceSpecification": { - "@id": "https://schema.org/priceSpecification" - } - } - }, - "TransferEvent": { - "@id": "https://w3id.org/traceability#TransferEvent", - "@context": { - "place": { - "@id": "https://schema.org/Place" - }, - "price": { - "@id": "https://schema.org/price" - }, - "products": { - "@id": "https://schema.org/Product" - }, - "organization": { - "@id": "https://w3id.org/traceability#Organization" - }, - "identifier": { - "@id": "https://schema.org/identifier" - }, - "addressCountry": { - "@id": "https://schema.org/addressCountry" - } - } - }, - "TransformEvent": { - "@id": "https://w3id.org/traceability#TransformEvent", - "@context": { - "place": { - "@id": "https://schema.org/Place" - }, - "organization": { - "@id": "https://w3id.org/traceability#Organization" - }, - "newProducts": { - "@id": "https://w3c-ccg.github.io/hashlink/#hl-url-params" - }, - "consumedProducts": { - "@id": "https://w3c-ccg.github.io/hashlink/#hl-url-params" - } - } - }, - "Transport": { - "@id": "https://w3id.org/traceability#Transport", - "@context": { - "arrivalLocation": { - "@id": "https://schema.org/toLocation" - }, - "departureDate": { - "@id": "https://schema.org/departureTime" - }, - "arrivalDate": { - "@id": "https://schema.org/arrivalTime" - }, - "modeOfTransport": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/modeOfTransport" - }, - "carrier": { - "@id": "https://schema.org/carrier" - }, - "vesselNumber": { - "@id": "https://vocabulary.uncefact.org/identifier" - }, - "voyageNumber": { - "@id": "https://vocabulary.uncefact.org/identifier" - }, - "path": { - "@id": "https://schema.org/line" - } - } - }, - "TransportDocument": { - "@id": "https://w3id.org/traceability#TransportDocument", - "@context": {} - }, - "TransportEquipment": { - "@id": "https://vocabulary.uncefact.org/LogisticsTransportEquipment", - "@context": { - "equipmentReference": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "ISOEquipmentCode": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/ISOEquipmentCode" - }, - "tareWeight": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/tareWeight" - }, - "tareWeightUnit": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/weightUnit" - }, - "cargoGrossWeight": { - "@id": "https://vocabulary.uncefact.org/grossWeightMeasure" - }, - "cargoGrossWeightUnit": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/weightUnit" - }, - "isShipperOwned": { - "@id": "https://api.swaggerhub.com/domains/dcsaorg/DCSA_DOMAIN/1.0.1#/components/schemas/isShipperOwned" - }, - "seals": { - "@id": "https://vocabulary.uncefact.org/affixedSeal" - } - } - }, - "TransportEvent": { - "@id": "https://w3id.org/traceability#TransportEvent", - "@context": { - "place": { - "@id": "https://schema.org/Place" - }, - "organization": { - "@id": "https://w3id.org/traceability#Organization" - }, - "products": { - "@id": "https://schema.org/Product" - }, - "deliveryMethod": { - "@id": "https://schema.org/DeliveryMethod" - }, - "trackingNumber": { - "@id": "https://schema.org/trackingNumber" - } - } - }, - "USDAPPQ203ForeignSiteInspection": { - "@id": "https://w3id.org/traceability#USDAPPQ203ForeignSiteInspection", - "@context": { - "certificateNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "commonInfo": { - "@id": "https://w3id.org/traceability#AgricultureInspectionCommonInfo" - }, - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "signatureDate": { - "@id": "https://www.gs1.org/voc/certificationAuditDate" - }, - "inspectionType": { - "@id": "https://www.gs1.org/voc/certificationType" - }, - "observations": { - "@id": "https://vocabulary.uncefact.org/relatedObservation" - } - } - }, - "USDAPPQ309APestInterceptionRecord": { - "@id": "https://w3id.org/traceability#USDAPPQ309APestInterceptionRecord", - "@context": { - "interceptionNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "shippingStop": { - "@id": "https://vocabulary.uncefact.org/itineraryStopEvent" - }, - "forwardTo": { - "@id": "https://vocabulary.uncefact.org/recipientAssignedId" - }, - "priority": { - "@id": "https://vocabulary.uncefact.org/priorityCode" - }, - "interceptionDate": { - "@id": "https://vocabulary.uncefact.org/actualOccurrenceDateTime" - }, - "inspector": { - "@id": "https://vocabulary.uncefact.org/inspectionParty" - }, - "overtime": { - "@id": "https://vocabulary.uncefact.org/information" - }, - "pathway": { - "@id": "https://vocabulary.uncefact.org/mode" - }, - "modeOfTransportation": { - "@id": "https://vocabulary.uncefact.org/mode" - }, - "materialFor": { - "@id": "https://vocabulary.uncefact.org/intendedUse" - }, - "narp": { - "@id": "https://vocabulary.uncefact.org/statementNote" - }, - "importedAs": { - "@id": "https://schema.org/description" - }, - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "whereIntercepted": { - "@id": "https://vocabulary.uncefact.org/AttachedTransportEquipment" - }, - "PestSample": { - "@id": "http://rs.tdwg.org/dwc/terms/materialSampleID" - }, - "pestDeterminations": { - "@id": "https://dwc.tdwg.org/list/#dwc_identificationID" - }, - "quarantineStatus": { - "@id": "https://vocabulary.uncefact.org/conditionCode" - }, - "remarks": { - "@id": "https://vocabulary.uncefact.org/remark" - } - } - }, - "USDAPPQ368NoticeOfArrival": { - "@id": "https://w3id.org/traceability#USDAPPQ368NoticeOfArrival", - "@context": { - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "arrivalDate": { - "@id": "https://vocabulary.uncefact.org/actualArrivalRelatedDateTime" - }, - "permitNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "customsEntryNumber": { - "@id": "https://vocabulary.uncefact.org/customsId" - }, - "presentLocation": { - "@id": "https://vocabulary.uncefact.org/consignmentDestinationSpecifiedLocation" - }, - "locationGrown": { - "@id": "https://vocabulary.uncefact.org/originLocation" - }, - "ITNumber": { - "@id": "https://vocabulary.uncefact.org/customsId" - }, - "productDisposition": { - "@id": "https://vocabulary.uncefact.org/dispositionDocument" - }, - "ppqOfficial": { - "@id": "https://vocabulary.uncefact.org/inspectionParty" - }, - "signatureDate": { - "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" - } - } - }, - "USDAPPQ391SpecimensForDetermination": { - "@id": "https://w3id.org/traceability#USDAPPQ391SpecimensForDetermination", - "@context": { - "priority": { - "@id": "https://vocabulary.uncefact.org/priorityCode" - }, - "priorityExplanation": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "collectionNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "submissionDate": { - "@id": "https://vocabulary.uncefact.org/reportSubmissionDateTime" - }, - "collectionDate": { - "@id": "https://vocabulary.uncefact.org/actualOccurrenceDateTime" - }, - "submittingAgency": { - "@id": "https://vocabulary.uncefact.org/agencyId" - }, - "submitter": { - "@id": "https://vocabulary.uncefact.org/PartyRoleCodeList#TB" - }, - "collector": { - "@id": "https://vocabulary.uncefact.org/inspectionParty" - }, - "interceptionSite": { - "@id": "https://vocabulary.uncefact.org/occurrenceLocation" - }, - "identificationReason": { - "@id": "https://vocabulary.uncefact.org/reasonCode" - }, - "remarks": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "tentativeDetermination": { - "@id": "https://dwc.tdwg.org/list/#dwc_identificationID" - }, - "finalDetermination": { - "@id": "https://dwc.tdwg.org/list/#dwc_identificationID" - }, - "sampleDisposition": { - "@id": "https://dwc.tdwg.org/list/#dwc_disposition" - }, - "signatureDate": { - "@id": "https://vocabulary.uncefact.org/occurrenceDateTime" - }, - "lab": { - "@id": "https://vocabulary.uncefact.org/lodgementLocation" - }, - "labConformationNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "dateReceived": { - "@id": "https://vocabulary.uncefact.org/acceptanceDateTime" - } - } - }, - "USDAPPQ429FumigationRecord": { - "@id": "https://w3id.org/traceability#USDAPPQ429FumigationRecord", - "@context": { - "tarpaulin": { - "@id": "https://vocabulary.uncefact.org/value" - }, - "stationReporting": { - "@id": "https://vocabulary.uncefact.org/relevantLocation" - }, - "pest": { - "@id": "https://schema.org/description" - }, - "interceptionRecord": { - "@id": "https://w3id.org/traceability#USDAPPQ309APestInterceptionRecord.yml" - }, - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "fumigationContractor": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "dateFumigationOrdered": { - "@id": "https://vocabulary.uncefact.org/actualDateTime" - }, - "fumigationSite": { - "@id": "https://vocabulary.uncefact.org/occurrenceLocation" - }, - "dateFumigated": { - "@id": "https://vocabulary.uncefact.org/actualOccurrenceDateTime" - }, - "fumigantAndTreatmentSchedule": { - "@id": "https://vocabulary.uncefact.org/regulationName" - }, - "temperatureOfSpace": { - "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" - }, - "temperatureOfCommodity": { - "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" - }, - "gasAnalyzer": { - "@id": "https://schema.org/description" - }, - "enclosure": { - "@id": "https://schema.org/description" - }, - "weatherConditions": { - "@id": "https://schema.org/description" - }, - "cubicCapacity": { - "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" - }, - "section18Exemption": { - "@id": "https://vocabulary.uncefact.org/value" - }, - "numberOfFans": { - "@id": "https://vocabulary.uncefact.org/unitQuantity" - }, - "totalCFMOfFans": { - "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" - }, - "timeFansOperated": { - "@id": "https://vocabulary.uncefact.org/durationMeasure" - }, - "foodOrFeedCommodity": { - "@id": "https://vocabulary.uncefact.org/functionDescription" - }, - "gasIntroductionStart": { - "@id": "https://vocabulary.uncefact.org/startDateTime" - }, - "gasIntroductionFinish": { - "@id": "https://vocabulary.uncefact.org/endDateTime" - }, - "totalGasIntroduced": { - "@id": "https://vocabulary.uncefact.org/actualReportedMeasurement" - }, - "residueSampleTaken": { - "@id": "https://vocabulary.uncefact.org/value" - }, - "residueSampleNumber": { - "@id": "https://schema.org/description" - }, - "gasConcentrations": { - "@id": "https://vocabulary.uncefact.org/relatedObservation" - }, - "detectorTubeReadings": { - "@id": "https://vocabulary.uncefact.org/relatedObservation" - }, - "remarks": { - "@id": "https://vocabulary.uncefact.org/remark" - }, - "inspector": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "reviewer": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "fumigatorMaterials": { - "@id": "https://schema.org/description" - }, - "ppqMaterials": { - "@id": "https://schema.org/description" - }, - "preparationProcedures": { - "@id": "https://schema.org/description" - } - } - }, - "USDAPPQ449RTemperatureCalibration": { - "@id": "https://w3id.org/traceability#USDAPPQ449RTemperatureCalibration", - "@context": { - "vesselName": { - "@id": "https://vocabulary.uncefact.org/name" - }, - "ppqDutyStation": { - "@id": "https://vocabulary.uncefact.org/transitCustomsOfficeSpecifiedLocation" - }, - "inspectionDate": { - "@id": "https://vocabulary.uncefact.org/performanceDateTime" - }, - "inspectionPoint": { - "@id": "https://vocabulary.uncefact.org/transitLocation" - }, - "hullNumberDockyard": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "imoNumber": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "flagCode": { - "@id": "https://vocabulary.uncefact.org/identification" - }, - "shipsOfficer": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "ownerOperator": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "instrument1MakeModel": { - "@id": "https://vocabulary.uncefact.org/AttachedTransportEquipment" - }, - "instrument2MakeModel": { - "@id": "https://vocabulary.uncefact.org/AttachedTransportEquipment" - }, - "locationsDiagramMatchSatisfactory": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "sensorsBoxesLabelingSatisfactory": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "cableLengthSatisfactory": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "reactionTimeSatisfactory": { - "@id": "https://vocabulary.uncefact.org/DocumentCodeList#287" - }, - "temperatureReadings": { - "@id": "https://vocabulary.uncefact.org/transportTemperature" - }, - "participatingOfficials": { - "@id": "https://vocabulary.uncefact.org/specifiedContactPerson" - }, - "remarks": { - "@id": "https://vocabulary.uncefact.org/remarks" - }, - "company": { - "@id": "https://vocabulary.uncefact.org/specifiedOrganization" - }, - "signatureDate": { - "@id": "https://vocabulary.uncefact.org/performanceDateTime" - } - } - }, - "USDAPPQ505PlantDeclaration": { - "@id": "https://w3id.org/traceability#USDAPPQ505PlantDeclaration", - "@context": { - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "productDeclarations": { - "@id": "https://w3id.org/traceability#LaceyActProductDeclaration" - }, - "preparer": { - "@id": "https://vocabulary.uncefact.org/declarantParty" - }, - "date": { - "@id": "https://vocabulary.uncefact.org/issueDateTime" - } - } - }, - "USDAPPQ519ComplianceAgreement": { - "@id": "https://w3id.org/traceability#USDAPPQ519ComplianceAgreement", - "@context": { - "person": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "firm": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "regulatedArticles": { - "@id": "https://www.gs1.org/voc/regulatedProductName" - }, - "quarantinesRegulations": { - "@id": "https://vocabulary.uncefact.org/applicableRegulatoryProcedure" - }, - "agreement": { - "@id": "https://vocabulary.uncefact.org/guarantee" - }, - "signatureDate": { - "@id": "https://vocabulary.uncefact.org/issueDateTime" - }, - "ppqCbpOfficial": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "usAgencyOfficial": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "agreementNumber": { - "@id": "https://vocabulary.uncefact.org/ReferenceCodeList#AJS" - }, - "agreementDate": { - "@id": "https://vocabulary.uncefact.org/issueDateTime" - } - } - }, - "USDAPPQ587PlantImportApplication": { - "@id": "https://w3id.org/traceability#USDAPPQ587PlantImportApplication", - "@context": { - "applicant": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "plantProductsImported": { - "@id": "https://vocabulary.uncefact.org/specifiedProduct" - }, - "intendedUse": { - "@id": "https://vocabulary.uncefact.org/intendedUse" - }, - "meansOfTransportation": { - "@id": "https://vocabulary.uncefact.org/usedTransportMeans" - }, - "date": { - "@id": "https://vocabulary.uncefact.org/creationDateTime" - } - } - }, - "USDAPPQ587PlantImportPermit": { - "@id": "https://w3id.org/traceability#USDAPPQ587PlantImportPermit", - "@context": { - "applicant": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "shipment": { - "@id": "https://vocabulary.uncefact.org/transportPackage" - }, - "intendedUse": { - "@id": "https://vocabulary.uncefact.org/intendedUse" - }, - "signatureDate": { - "@id": "https://vocabulary.uncefact.org/issueDateTime" - } - } - }, - "USDASpecialtyCrops237AForm": { - "@id": "https://w3id.org/traceability#USDASpecialtyCrops237AForm", - "@context": { - "requestDate": { - "@id": "https://vocabulary.uncefact.org/reportSubmissionDateTime" - }, - "anticipatedAuditDate": { - "@id": "https://www.gs1.org/voc/certificationAuditDate" - }, - "auditee": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "applicant": { - "@id": "https://vocabulary.uncefact.org/associatedParty" - }, - "billingAccountNumber": { - "@id": "https://schema.org/accountId" - }, - "locations": { - "@id": "https://schema.org/location" - }, - "totalArea": { - "@id": "https://www.gs1.org/voc/grossArea" - }, - "commoditiesCovered": { - "@id": "https://www.gs1.org/voc/certificationSubject" - }, - "auditProgramsRequested": { - "@id": "https://www.gs1.org/voc/certificationType" - }, - "countByInspector": { - "@id": "https://vocabulary.uncefact.org/applicableSpecifiedAction" - }, - "additionalRemarks": { - "@id": "https://vocabulary.uncefact.org/remarks" - } - } - }, - "USMCACertifier": { - "@id": "https://w3id.org/traceability/USMCACertifier", - "@context": { - "role": { - "@id": "https://w3id.org/traceability#certifierRole" - }, - "certifierDetails": { - "@id": "https://w3id.org/traceability#certifierDetails" - } - } - }, - "USMCAClaims": { - "@id": "https://w3id.org/traceability/USMCAClaims", - "@context": { - "producerDetails": { - "@id": "https://schema.org/manufacturer" - }, - "producerConfidential": { - "@id": "https://w3id.org/traceability#producerConfidential" - }, - "importerDetails": { - "@id": "https://w3id.org/traceability#importerDetails" - }, - "importerUnknown": { - "@id": "https://w3id.org/traceability#importerUnknown" - }, - "exporterDetails": { - "@id": "https://w3id.org/traceability#exporterDetails" - }, - "goods": { - "@id": "https://schema.org/Product" - } - } - }, - "USMCAProduct": { - "@id": "https://w3id.org/traceability/USMCAProduct", - "@context": { - "commodityCode": { - "@id": "https://w3id.org/traceability#commodityCode" - }, - "commodityCodeType": { - "@id": "https://w3id.org/traceability#commodityCodeType" - }, - "originCriterion": { - "@id": "https://w3id.org/traceability#originCriterion" - }, - "countryOfOrigin": { - "@id": "https://w3id.org/traceability#countryOfOrigin" - } - } - }, - "UsdaSc6": { - "@id": "https://w3id.org/traceability#UsdaSc6", - "@context": { - "serialNumber": { - "@id": "https://w3id.org/traceability#serialNumber" - }, - "customsEntryNumber": { - "@id": "https://w3id.org/traceability#customsEntryNumber" - }, - "tariffCodeNumber": { - "@id": "https://w3id.org/traceability#tariffCodeNumber" - }, - "carrierId": { - "@id": "https://w3id.org/traceability#carrierId" - }, - "lotId": { - "@id": "https://w3id.org/traceability#lotId" - }, - "dateOfEntry": { - "@id": "https://w3id.org/traceability#dateOfEntry" - }, - "signatureDate": { - "@id": "https://w3id.org/traceability#signatureDate" - }, - "facility": { - "@id": "https://www.gs1.org/voc/Place" - }, - "inspector": { - "@id": "https://w3id.org/traceability#Inspector" - }, - "shipment": { - "@id": "https://w3id.org/traceability#AgricultureParcelDelivery" - }, - "applicant": { - "@id": "https://w3id.org/traceability#applicant" - }, - "importerSignatureDate": { - "@id": "https://w3id.org/traceability#importerSignatureDate" - }, - "inspectionDate": { - "@id": "https://schema.org/DateTime" - }, - "intendedUse": { - "@id": "https://w3id.org/traceability#intendedUse" - }, - "intendedUseCert": { - "@id": "https://w3id.org/traceability#intendedUseCert" - } - } - }, - "ActivityPubActorCard": { - "@id": "https://w3id.org/traceability#ActivityPubActorCard", - "@context": {} - }, - "AgricultureCanineCard": { - "@id": "https://w3id.org/traceability#AgricultureCanineCard", - "@context": {} - }, - "BankAccountCredential": { - "@id": "https://w3id.org/traceability#BankAccountCredential", - "@context": {} - }, - "BillOfLadingCredential": { - "@id": "https://w3id.org/traceability#BillOfLadingCredential", - "@context": {} - }, - "CBP3461EntryCredential": { - "@id": "https://w3id.org/traceability#CBP3461EntryCredential", - "@context": {} - }, - "CBP7501EntrySummaryCredential": { - "@id": "https://w3id.org/traceability#CBP7501EntrySummaryCredential", - "@context": {} - }, - "CBPEntryType86Credential": { - "@id": "https://w3id.org/traceability#CBPEntryType86Credential", - "@context": {} - }, - "CBPSection321DeMinimisDeMinimisCredential": { - "@id": "https://w3id.org/traceability#CBPSection321DeMinimisCredential", - "@context": {} - }, - "CTPATCertificate": { - "@id": "https://w3id.org/traceability#CTPATCertificate", - "@context": {} - }, - "CTPATEIPApplicationCredential": { - "@id": "https://w3id.org/traceability#CTPATEIPApplicationCredential", - "@context": {} - }, - "CTPATEIPFulfillmentCredential": { - "@id": "https://w3id.org/traceability#CTPATEIPFulfillmentCredential", - "@context": {} - }, - "CTPATEIPMarketplaceCredential": { - "@id": "https://w3id.org/traceability#CTPATEIPMarketplaceCredential", - "@context": {} - }, - "CTPATEIPSellerCredential": { - "@id": "https://w3id.org/traceability#CTPATEIPSellerCredential", - "@context": {} - }, - "CertificationOfOrigin": { - "@id": "https://w3id.org/traceability#CertificationOfOrigin", - "@context": {} - }, - "CommercialInvoiceCredential": { - "@id": "https://w3id.org/traceability#CommercialInvoiceCredential", - "@context": {} - }, - "DCSAShippingInstructionCredential": { - "@id": "https://w3id.org/traceability#DCSAShippingInstructionCredential", - "@context": {} - }, - "DCSATransportDocumentCredential": { - "@id": "https://w3id.org/traceability#DCSATransportDocumentCredential", - "@context": {} - }, - "DeliveryScheduleCredential": { - "@id": "https://w3id.org/traceability#DeliveryScheduleCredential", - "@context": {} - }, - "DeliveryStatementCredential": { - "@id": "https://w3id.org/traceability#DeliveryStatementCredential", - "@context": {} - }, - "DigitalProductPassportCredential": { - "@id": "https://w3id.org/traceability#DigitalProductPassportCredential", - "@context": {} - }, - "DigitalProductPassportDataCarrierCredential": { - "@id": "https://w3id.org/traceability#DigitalProductPassportDataCarrierCredential", - "@context": {} - }, - "EntryNumberCredential": { - "@id": "https://w3id.org/traceability#EntryNumberCredential", - "@context": {} - }, - "FSMACreatingCTECredential": { - "@id": "https://w3id.org/traceability#FSMACreatingCTECredential", - "@context": {} - }, - "FSMAFirstReceiverDataCredential": { - "@id": "https://w3id.org/traceability#FSMAFirstReceiverDataCredential", - "@context": {} - }, - "FSMAGrowingCTECredential": { - "@id": "https://w3id.org/traceability#FSMAGrowingCTECredential", - "@context": {} - }, - "FSMAReceivingCTECredential": { - "@id": "https://w3id.org/traceability#FSMAReceivingCTECredential", - "@context": {} - }, - "FSMAShippingCTECredential": { - "@id": "https://w3id.org/traceability#FSMAShippingCTECredential", - "@context": {} - }, - "FSMATransformingCTECredential": { - "@id": "https://w3id.org/traceability#FSMATransformingCTECredential", - "@context": {} - }, - "FoodDefenseInspectionCredential": { - "@id": "https://w3id.org/traceability#FoodDefenseInspectionCredential", - "@context": {} - }, - "FoodGradeInspectionCredential": { - "@id": "https://w3id.org/traceability#FoodGradeInspectionCredential", - "@context": {} - }, - "FreightManifestCredential": { - "@id": "https://w3id.org/traceability#FreightManifestCredential", - "@context": {} - }, - "FulfillmentRegistrationCredential": { - "@id": "https://w3id.org/traceability#FulfillmentRegistrationCredential", - "@context": {} - }, - "GAPInspectionCredential": { - "@id": "https://w3id.org/traceability#GAPInspectionCredential", - "@context": {} - }, - "GS18PrefixLicenseCredential": { - "@id": "https://w3id.org/traceability#GS18PrefixLicenseCredential", - "@context": {} - }, - "GS1CompanyPrefixLicenseCredential": { - "@id": "https://w3id.org/traceability#GS1CompanyPrefixLicenseCredential", - "@context": {} - }, - "GS1DataCredential": { - "@id": "https://w3id.org/traceability#GS1DataCredential", - "@context": {} - }, - "GS1DelegationCredential": { - "@id": "https://w3id.org/traceability#GS1DelegationCredential", - "@context": {} - }, - "GS1IdentificationKeyLicenseCredential": { - "@id": "https://w3id.org/traceability#GS1IdentificationKeyLicenseCredential", - "@context": {} - }, - "GS1KeyCredential": { - "@id": "https://w3id.org/traceability#GS1KeyCredential", - "@context": {} - }, - "GS1PrefixLicenseCredential": { - "@id": "https://w3id.org/traceability#GS1PrefixLicenseCredential", - "@context": {} - }, - "HouseBillOfLadingCredential": { - "@id": "https://w3id.org/traceability#HouseBillOfLadingCredential", - "@context": {} - }, - "IATAAirWaybillCredential": { - "@id": "https://w3id.org/traceability#IATAAirWaybillCredential", - "@context": {} - }, - "ImporterSecurityFilingCredential": { - "@id": "https://w3id.org/traceability#ImporterSecurityFilingCredential", - "@context": {} - }, - "IntellectualPropertyRightsCredential": { - "@id": "https://w3id.org/traceability#IntellectualPropertyRightsCredential", - "@context": {} - }, - "IntellectualPropertyRightsLicenseCredential": { - "@id": "https://w3id.org/traceability#IntellectualPropertyRightsLicenseCredential", - "@context": {} - }, - "IntentToImportCredential": { - "@id": "https://w3id.org/traceability#IntentToImportCredential", - "@context": {} - }, - "InventoryRegistrationCredential": { - "@id": "https://w3id.org/traceability#InventoryRegistrationCredential", - "@context": {} - }, - "MasterBillOfLadingCredential": { - "@id": "https://w3id.org/traceability#MasterBillOfLadingCredential", - "@context": {} - }, - "MexicoEInvoiceCredential": { - "@id": "https://w3id.org/traceability#MexicoEInvoiceCredential", - "@context": {} - }, - "MillTestReportCredential": { - "@id": "https://w3id.org/traceability#MillTestReportCredential", - "@context": {} - }, - "MonthlyAdvanceManifestCredential": { - "@id": "https://w3id.org/traceability#MonthlyAdvanceManifestCredential", - "@context": {} - }, - "MultiModalBillOfLadingCredential": { - "@id": "https://w3id.org/traceability#MultiModalBillOfLadingCredential", - "@context": {} - }, - "OilAndGasDeliveryTicketCredential": { - "@id": "https://w3id.org/traceability#OilAndGasDeliveryTicketCredential", - "@context": {} - }, - "OilAndGasProductCredential": { - "@id": "https://w3id.org/traceability#OilAndGasProductCredential", - "@context": {} - }, - "OrderConfirmationCredential": { - "@id": "https://w3id.org/traceability#OrderConfirmationCredential", - "@context": {} - }, - "OrganicCertificationCredential": { - "@id": "https://w3id.org/traceability#OrganicCertificationCredential", - "@context": {} - }, - "PGAShipmentStatusCredential": { - "@id": "https://w3id.org/traceability#PGAShipmentStatusCredential", - "@context": {} - }, - "PackingListCredential": { - "@id": "https://w3id.org/traceability#PackingListCredential", - "@context": {} - }, - "PlantSystemsInspectionCredential": { - "@id": "https://w3id.org/traceability#PlantSystemsInspectionCredential", - "@context": {} - }, - "PowerOfAttorneyCredential": { - "@id": "https://spec.edmcouncil.org/fibo/ontology/BE/LegalEntities/LegalPersons/PowerOfAttorney", - "@context": {} - }, - "ProductRegistrationCredential": { - "@id": "https://w3id.org/traceability#ProductRegistrationCredential", - "@context": {} - }, - "PurchaseOrderCredential": { - "@id": "https://w3id.org/traceability#PurchaseOrderCredential", - "@context": {} - }, - "SIMASteelImportLicenseApplicationCredential": { - "@id": "https://w3id.org/traceability#SIMASteelImportLicenseApplicationCredential", - "@context": {} - }, - "SIMASteelImportLicenseCredential": { - "@id": "https://w3id.org/traceability#SIMASteelImportLicenseCredential", - "@context": {} - }, - "SeaCargoManifestCredential": { - "@id": "https://w3id.org/traceability#SeaCargoManifestCredential", - "@context": {} - }, - "SellerRegistrationCredential": { - "@id": "https://w3id.org/traceability#SellerRegistrationCredential", - "@context": {} - }, - "ShippingInstructionsCredential": { - "@id": "https://w3id.org/traceability#ShippingInstructionsCredential", - "@context": {} - }, - "SoftwareBillofMaterialsCredential": { - "@id": "https://w3id.org/traceability#SoftwareBillOfMaterialsCredential", - "@context": {} - }, - "ThingCredential": { - "@id": "https://w3id.org/traceability#ThingCredential", - "@context": {} - }, - "USMCACertificationOfOrigin": { - "@id": "https://w3id.org/traceability#USMCACertificationOfOrigin", - "@context": {} - }, - "VerifiableBusinessCard": { - "@id": "https://w3id.org/traceability#VerifiableBusinessCard", - "@context": {} - }, - "VerifiablePostmanCollection": { - "@id": "https://w3id.org/traceability#VerifiablePostmanCollection", - "@context": {} - }, - "VerifiableScorecard": { - "@id": "https://w3id.org/traceability#VerifiableScorecard", - "@context": {} - } - } - } \ No newline at end of file diff --git a/aries_cloudagent/vc/routes.py b/aries_cloudagent/vc/routes.py index 74bdee581d..adacb397cf 100644 --- a/aries_cloudagent/vc/routes.py +++ b/aries_cloudagent/vc/routes.py @@ -1,46 +1,89 @@ -"""VC Routes.""" +"""VC-API Routes.""" from aiohttp import web from aiohttp_apispec import docs, request_schema, response_schema -from marshmallow import ValidationError, fields, validates_schema +from .vc_ld.models.credential import ( + VerifiableCredential, +) -from aries_cloudagent.vc.vc_ld.validation_result import ( - PresentationVerificationResultSchema, +from .vc_ld.models.presentation import ( + VerifiablePresentation, ) -from .vc_ld.models.credential import ( - CredentialSchema, - VerifiableCredential, - VerifiableCredentialSchema, +from .vc_ld.models.request_schemas import ( + ListCredentialResponseSchema, + IssueCredentialRequestSchema, + IssueCredentialResponseSchema, + VerifyCredentialRequestSchema, + VerifyCredentialResponseSchema, + ProvePresentationRequestSchema, + ProvePresentationResponseSchema, + VerifyPresentationRequestSchema, + VerifyPresentationResponseSchema, ) -from .vc_ld.models.options import LDProofVCOptions, LDProofVCOptionsSchema +from .vc_ld.models.options import LDProofVCOptions from .vc_ld.manager import VcLdpManager, VcLdpManagerError from ..admin.request_context import AdminRequestContext from ..config.base import InjectionError from ..resolver.base import ResolverError from ..wallet.error import WalletError -from ..messaging.models.openapi import OpenAPISchema +from ..storage.error import StorageError, StorageNotFoundError +from ..storage.vc_holder.base import VCHolder -class LdpIssueRequestSchema(OpenAPISchema): - """Request schema for signing an ldb_vc.""" +@docs(tags=["vc-api"], summary="List credentials") +@response_schema(ListCredentialResponseSchema(), 200, description="") +async def list_credentials_route(request: web.BaseRequest): + """Request handler for issuing a credential. - credential = fields.Nested(CredentialSchema) - options = fields.Nested(LDProofVCOptionsSchema) + Args: + request: aiohttp request object + """ + context: AdminRequestContext = request["context"] + async with context.profile.session() as session: + holder = session.inject(VCHolder) + try: + search = holder.search_credentials() + records = await search.fetch() + except StorageNotFoundError as err: + raise web.HTTPNotFound(reason=err.roll_up) from err + except StorageError as err: + raise web.HTTPBadRequest(reason=err.roll_up) from err + return web.json_response([record.serialize()["cred_value"] for record in records]) -class LdpIssueResponseSchema(OpenAPISchema): - """Request schema for signing an ldb_vc.""" - vc = fields.Nested(VerifiableCredentialSchema) +@docs(tags=["vc-api"], summary="Fetch credential by ID") +@response_schema(ListCredentialResponseSchema(), 200, description="") +async def fetch_credential_route(request: web.BaseRequest): + """Request handler for issuing a credential. + Args: + request: aiohttp request object -@docs(tags=["ldp_vc"], summary="Sign an LDP VC.") -@request_schema(LdpIssueRequestSchema()) -@response_schema(LdpIssueResponseSchema(), 200, description="") -async def ldp_issue(request: web.BaseRequest): - """Request handler for signing a jsonld doc. + """ + context: AdminRequestContext = request["context"] + credential_id = request.match_info["credential_id"] + async with context.profile.session() as session: + holder = session.inject(VCHolder) + try: + search = holder.search_credentials(given_id=credential_id.strip('"')) + records = await search.fetch() + record = [record.serialize() for record in records] + credential = record[0]["cred_value"] if len(record) == 1 else None + except StorageNotFoundError as err: + raise web.HTTPNotFound(reason=err.roll_up) from err + except StorageError as err: + raise web.HTTPBadRequest(reason=err.roll_up) from err + return web.json_response(credential) + + +@docs(tags=["vc-api"], summary="Issue a credential") +@request_schema(IssueCredentialRequestSchema()) +@response_schema(IssueCredentialResponseSchema(), 200, description="") +async def issue_credential_route(request: web.BaseRequest): + """Request handler for issuing a credential. Args: request: aiohttp request object @@ -49,6 +92,16 @@ async def ldp_issue(request: web.BaseRequest): context: AdminRequestContext = request["context"] body = await request.json() credential = VerifiableCredential.deserialize(body["credential"]) + options = {} if "options" not in body else body["options"] + # Default to Ed25519Signature2018 if no proof type was provided + if "type" in options: + options["proofType"] = options.pop("type") + else: + options["proofType"] = ( + "Ed25519Signature2018" + if "proofType" not in options + else options["proofType"] + ) options = LDProofVCOptions.deserialize(body["options"]) try: @@ -58,42 +111,100 @@ async def ldp_issue(request: web.BaseRequest): return web.json_response({"error": str(err)}, status=400) except (WalletError, InjectionError): raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"vc": vc.serialize()}) + return web.json_response({"verifiableCredential": vc.serialize()}) -class LdpVerifyRequestSchema(OpenAPISchema): - """Request schema for verifying an LDP VP.""" +@docs(tags=["vc-api"], summary="Verify a credential") +@request_schema(VerifyCredentialRequestSchema()) +@response_schema(VerifyCredentialResponseSchema(), 200, description="") +async def verify_credential_route(request: web.BaseRequest): + """Request handler for verifying a credential. - vp = fields.Nested(VerifiableCredentialSchema, required=False) - vc = fields.Nested(VerifiableCredentialSchema, required=False) - options = fields.Nested(LDProofVCOptionsSchema) + Args: + request: aiohttp request object - @validates_schema - def validate_fields(self, data, **kwargs): - """Validate schema fields. + """ + context: AdminRequestContext = request["context"] + body = await request.json() + vc = body.get("verifiableCredential") + try: + manager = context.inject(VcLdpManager) + vc = VerifiableCredential.deserialize(vc) + result = await manager.verify_credential(vc) + except (VcLdpManagerError, ResolverError, ValueError) as error: + raise web.HTTPBadRequest(reason=str(error)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return web.json_response(result.serialize()) - Args: - data: The data to validate - Raises: - ValidationError: if data has neither indy nor ld_proof +@docs(tags=["vc-api"], summary="Store a credential") +@request_schema(VerifyCredentialRequestSchema) +@response_schema(VerifyCredentialResponseSchema, 200) +async def store_credential_route(request: web.BaseRequest): + """Request handler for storing a credential. - """ - if not data.get("vp") and not data.get("vc"): - raise ValidationError("Field vp or vc must be present") - if data.get("vp") and data.get("vc"): - raise ValidationError("Field vp or vc must be present, not both") + Args: + request: aiohttp request object + + """ + body = await request.json() + vc = VerifiableCredential.deserialize(body["verifiableCredential"]) + options = {} if "options" not in body else body["options"] + options = LDProofVCOptions.deserialize(body["options"]) + + try: + context: AdminRequestContext = request["context"] + manager = context.inject(VcLdpManager) + await manager.verify_credential(vc) + await manager.store_credential(vc, options) + except VcLdpManagerError as err: + return web.json_response({"error": str(err)}, status=400) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="Bad credential") + return web.json_response({"message": "Credential stored"}, status=200) + + +@docs(tags=["vc-api"], summary="Prove a presentation") +@request_schema(ProvePresentationRequestSchema()) +@response_schema(ProvePresentationResponseSchema(), 200, description="") +async def prove_presentation_route(request: web.BaseRequest): + """Request handler for proving a presentation. + Args: + request: aiohttp request object + + """ + context: AdminRequestContext = request["context"] + body = await request.json() + presentation = VerifiablePresentation.deserialize(body["presentation"]) + options = {} if "options" not in body else body["options"] + # Default to Ed25519Signature2018 if no proof type was provided + if "type" in options: + options["proofType"] = options.pop("type") + else: + options["proofType"] = ( + "Ed25519Signature2018" + if "proofType" not in options + else options["proofType"] + ) + options = LDProofVCOptions.deserialize(body["options"]) -class LdpVerifyResponseSchema(PresentationVerificationResultSchema): - """Request schema for verifying an LDP VP.""" + try: + manager = context.inject(VcLdpManager) + vp = await manager.prove(presentation, options) + except VcLdpManagerError as err: + return web.json_response({"error": str(err)}, status=400) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return web.json_response({"verifiablePresentation": vp.serialize()}) -@docs(tags=["ldp_vc"], summary="Verify an LDP VC or VP.") -@request_schema(LdpVerifyRequestSchema()) -@response_schema(LdpVerifyResponseSchema(), 200, description="") -async def ldp_verify(request: web.BaseRequest): - """Request handler for signing a jsonld doc. +@docs(tags=["vc-api"], summary="Verify a Presentation") +@request_schema(VerifyPresentationRequestSchema()) +@response_schema(VerifyPresentationResponseSchema(), 200, description="") +async def verify_presentation_route(request: web.BaseRequest): + """Request handler for verifying a presentation. Args: request: aiohttp request object @@ -101,24 +212,17 @@ async def ldp_verify(request: web.BaseRequest): """ context: AdminRequestContext = request["context"] body = await request.json() - vp = body.get("vp") - vc = body.get("vc") + vp = body.get("verifiablePresentation") try: manager = context.inject(VcLdpManager) - if vp: - vp = VerifiableCredential.deserialize(vp) - options = LDProofVCOptions.deserialize(body["options"]) - result = await manager.verify_presentation(vp, options) - elif vc: - vc = VerifiableCredential.deserialize(vc) - result = await manager.verify_credential(vc) - else: - raise web.HTTPBadRequest(reason="vp or vc must be present") - return web.json_response(result.serialize()) + vp = VerifiablePresentation.deserialize(vp) + options = LDProofVCOptions.deserialize(body["options"]) + result = await manager.verify_presentation(vp, options) except (VcLdpManagerError, ResolverError, ValueError) as error: raise web.HTTPBadRequest(reason=str(error)) except (WalletError, InjectionError): raise web.HTTPForbidden(reason="No wallet available") + return web.json_response(result.serialize()) async def register(app: web.Application): @@ -126,8 +230,17 @@ async def register(app: web.Application): app.add_routes( [ - web.post("/vc/ldp/issue", ldp_issue), - web.post("/vc/ldp/verify", ldp_verify), + web.get("/vc/credentials", list_credentials_route, allow_head=False), + web.get( + "/vc/credentials/{credential_id}", + fetch_credential_route, + allow_head=False, + ), + web.post("/vc/credentials/issue", issue_credential_route), + web.post("/vc/credentials/store", store_credential_route), + web.post("/vc/credentials/verify", verify_credential_route), + web.post("/vc/presentations/prove", prove_presentation_route), + web.post("/vc/presentations/verify", verify_presentation_route), ] ) @@ -139,11 +252,11 @@ def post_process_routes(app: web.Application): app._state["swagger_dict"]["tags"] = [] app._state["swagger_dict"]["tags"].append( { - "name": "ldp-vc", - "description": "Issue and verify LDP VCs and VPs", + "name": "vc-api", + "description": "Endpoints for managing w3c credentials and presentations", "externalDocs": { "description": "Specification", - "url": "https://www.w3.org/TR/vc-data-model/", + "url": "https://w3c-ccg.github.io/vc-api/", }, } ) diff --git a/aries_cloudagent/vc/vc_ld/manager.py b/aries_cloudagent/vc/vc_ld/manager.py index b005a41397..0a50e1281a 100644 --- a/aries_cloudagent/vc/vc_ld/manager.py +++ b/aries_cloudagent/vc/vc_ld/manager.py @@ -2,6 +2,8 @@ from typing import Dict, List, Optional, Type, Union, cast +from pyld import jsonld +from pyld.jsonld import JsonLdProcessor from ...core.profile import Profile from ...wallet.base import BaseWallet @@ -9,6 +11,8 @@ from ...wallet.did_info import DIDInfo from ...wallet.error import WalletNotFoundError from ...wallet.key_type import BLS12381G2, ED25519, KeyType +from ...storage.vc_holder.base import VCHolder +from ...storage.vc_holder.vc_record import VCRecord from ..ld_proofs.constants import ( SECURITY_CONTEXT_BBS_URL, SECURITY_CONTEXT_ED25519_2020_URL, @@ -273,16 +277,14 @@ async def prepare_credential( return credential - async def _get_suite_for_credential( + async def _get_suite_for_document( self, document: Union[VerifiableCredential, VerifiablePresentation], options: LDProofVCOptions, ) -> LinkedDataProof: - document_type = document.type[0] - - if document_type == "VerifiableCredential": + if isinstance(document, VerifiableCredential): issuer_id = document.issuer_id - if document_type == "VerifiablePresentation": + elif isinstance(document, VerifiablePresentation): issuer_id = document.holder_id proof_type = options.proof_type @@ -352,7 +354,7 @@ async def issue( credential = await self.prepare_credential(credential, options) # Get signature suite, proof purpose and document loader - suite = await self._get_suite_for_credential(credential, options) + suite = await self._get_suite_for_document(credential, options) proof_purpose = self._get_proof_purpose( proof_purpose=options.proof_purpose, challenge=options.challenge, @@ -368,13 +370,55 @@ async def issue( ) return VerifiableCredential.deserialize(vc) + async def store_credential( + self, vc: VerifiableCredential, options: LDProofVCOptions, cred_id: str = None + ) -> VerifiableCredential: + """Store a verifiable credential.""" + + # Saving expanded type as a cred_tag + document_loader = self.profile.inject(DocumentLoader) + expanded = jsonld.expand( + vc.serialize(), options={"documentLoader": document_loader} + ) + types = JsonLdProcessor.get_values( + expanded[0], + "@type", + ) + vc_record = VCRecord( + contexts=vc.context_urls, + expanded_types=types, + issuer_id=vc.issuer_id, + subject_ids=vc.credential_subject_ids, + schema_ids=[], # Schemas not supported yet + proof_types=[vc.proof.type], + cred_value=vc.serialize(), + given_id=vc.id, + record_id=cred_id, + cred_tags=None, # Tags should be derived from credential values + ) + + async with self.profile.session() as session: + vc_holder = session.inject(VCHolder) + + await vc_holder.store_credential(vc_record) + + async def verify_credential( + self, vc: VerifiableCredential + ) -> DocumentVerificationResult: + """Verify a VC with a Linked Data Proof.""" + return await verify_credential( + credential=vc.serialize(), + suites=await self._get_all_proof_suites(), + document_loader=self.profile.inject(DocumentLoader), + ) + async def prove( self, presentation: VerifiablePresentation, options: LDProofVCOptions ) -> VerifiablePresentation: """Sign a VP with a Linked Data Proof.""" # Get signature suite, proof purpose and document loader - suite = await self._get_suite_for_credential(presentation, options) + suite = await self._get_suite_for_document(presentation, options) proof_purpose = self._get_proof_purpose( proof_purpose=options.proof_purpose, challenge=options.challenge, @@ -404,13 +448,3 @@ async def verify_presentation( document_loader=self.profile.inject(DocumentLoader), challenge=options.challenge, ) - - async def verify_credential( - self, vc: VerifiableCredential - ) -> DocumentVerificationResult: - """Verify a VC with a Linked Data Proof.""" - return await verify_credential( - credential=vc.serialize(), - suites=await self._get_all_proof_suites(), - document_loader=self.profile.inject(DocumentLoader), - ) diff --git a/aries_cloudagent/vc/vc_ld/models/credential.py b/aries_cloudagent/vc/vc_ld/models/credential.py index 698b34f97e..6a63df6b7d 100644 --- a/aries_cloudagent/vc/vc_ld/models/credential.py +++ b/aries_cloudagent/vc/vc_ld/models/credential.py @@ -13,6 +13,8 @@ CREDENTIAL_CONTEXT_VALIDATE, CREDENTIAL_SUBJECT_EXAMPLE, CREDENTIAL_SUBJECT_VALIDATE, + CREDENTIAL_STATUS_EXAMPLE, + CREDENTIAL_STATUS_VALIDATE, CREDENTIAL_TYPE_EXAMPLE, CREDENTIAL_TYPE_VALIDATE, RFC3339_DATETIME_EXAMPLE, @@ -352,8 +354,8 @@ class Meta: credential_status = DictOrDictListField( required=False, data_key="credentialStatus", - # validate=CREDENTIAL_STATUS_VALIDATE, - # metadata={"example": CREDENTIAL_STATUS_EXAMPLE}, + validate=CREDENTIAL_STATUS_VALIDATE, + metadata={"example": CREDENTIAL_STATUS_EXAMPLE}, ) proof = fields.Nested( diff --git a/aries_cloudagent/vc/vc_ld/models/presentation.py b/aries_cloudagent/vc/vc_ld/models/presentation.py index 2fee51c5de..4ceebd92a2 100644 --- a/aries_cloudagent/vc/vc_ld/models/presentation.py +++ b/aries_cloudagent/vc/vc_ld/models/presentation.py @@ -6,6 +6,8 @@ from ....messaging.models.base import BaseModel, BaseModelSchema from ....messaging.valid import ( CREDENTIAL_CONTEXT_VALIDATE, + PRESENTATION_TYPE_EXAMPLE, + PRESENTATION_TYPE_VALIDATE, DIDKey, StrOrDictField, Uri, @@ -217,10 +219,10 @@ class Meta: type = fields.List( fields.Str(required=True), required=True, - # validate=PRESENTATION_TYPE_VALIDATE, + validate=PRESENTATION_TYPE_VALIDATE, metadata={ "description": "The JSON-LD type of the presentation", - "example": [VERIFIABLE_PRESENTATION_TYPE], + "example": PRESENTATION_TYPE_EXAMPLE, }, ) @@ -235,11 +237,11 @@ class Meta: }, ) + # TODO how to validate VCs in list verifiable_credential = fields.List( fields.Dict(required=True), required=False, data_key="verifiableCredential", - # validate=VERIFIABLE_CREDENTIAL_VALIDATE, metadata={}, ) diff --git a/aries_cloudagent/vc/vc_ld/models/request_schemas.py b/aries_cloudagent/vc/vc_ld/models/request_schemas.py new file mode 100644 index 0000000000..f300697791 --- /dev/null +++ b/aries_cloudagent/vc/vc_ld/models/request_schemas.py @@ -0,0 +1,72 @@ +"""VC-API routes requests marshmallow schema classes.""" + +from marshmallow import fields +from ....messaging.models.openapi import OpenAPISchema + +from aries_cloudagent.vc.vc_ld.validation_result import ( + PresentationVerificationResultSchema, +) + +from .options import LDProofVCOptionsSchema +from .credential import ( + CredentialSchema, + VerifiableCredentialSchema, +) +from .presentation import ( + PresentationSchema, + VerifiablePresentationSchema, +) + + +class ListCredentialResponseSchema(OpenAPISchema): + """Response schema for listing credentials.""" + + credentials = [fields.Nested(VerifiableCredentialSchema)] + + +class IssueCredentialRequestSchema(OpenAPISchema): + """Request schema for issuing a credential.""" + + credential = fields.Nested(CredentialSchema) + options = fields.Nested(LDProofVCOptionsSchema) + + +class IssueCredentialResponseSchema(OpenAPISchema): + """Request schema for issuing a credential.""" + + verifiableCredential = fields.Nested(VerifiableCredentialSchema) + + +class VerifyCredentialRequestSchema(OpenAPISchema): + """Request schema for verifying a credential.""" + + verifiableCredential = fields.Nested(VerifiableCredentialSchema) + options = fields.Nested(LDProofVCOptionsSchema) + + +class VerifyCredentialResponseSchema(PresentationVerificationResultSchema): + """Request schema for verifying an LDP VP.""" + + +class ProvePresentationRequestSchema(OpenAPISchema): + """Request schema for proving a presentation.""" + + presentation = fields.Nested(PresentationSchema) + options = fields.Nested(LDProofVCOptionsSchema) + + +class ProvePresentationResponseSchema(OpenAPISchema): + """Request schema for proving a presentation.""" + + verifiablePresentation = fields.Nested(VerifiablePresentationSchema) + + +class VerifyPresentationRequestSchema(OpenAPISchema): + """Request schema for verifying a credential.""" + + verifiablePresentation = fields.Nested(VerifiablePresentationSchema) + options = fields.Nested(LDProofVCOptionsSchema) + + +class VerifyPresentationResponseSchema(PresentationVerificationResultSchema): + """Request schema for verifying an LDP VP.""" diff --git a/aries_cloudagent/vc/vc_ld/store.py b/aries_cloudagent/vc/vc_ld/store.py deleted file mode 100644 index 8974d3e198..0000000000 --- a/aries_cloudagent/vc/vc_ld/store.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Verifiable Credential storage methods.""" -from ...admin.request_context import AdminRequestContext -from ...storage.vc_holder.base import VCHolder -from ...storage.vc_holder.vc_record import VCRecord -from ...vc.vc_ld import VerifiableCredential -from ...vc.ld_proofs import DocumentLoader -from pyld import jsonld -from pyld.jsonld import JsonLdProcessor - - -async def store_credential( - credential: VerifiableCredential, - document_loader: DocumentLoader, - context: AdminRequestContext, - cred_id: str = None, -): - """Store a verifiable credential.""" - # Saving expanded type as a cred_tag - expanded = jsonld.expand( - credential.serialize(), options={"documentLoader": document_loader} - ) - types = JsonLdProcessor.get_values( - expanded[0], - "@type", - ) - vc_record = VCRecord( - contexts=credential.context_urls, - expanded_types=types, - issuer_id=credential.issuer_id, - subject_ids=credential.credential_subject_ids, - schema_ids=[], # Schemas not supported yet - proof_types=[credential.proof.type], - cred_value=credential.serialize(), - given_id=credential.id, - record_id=cred_id, - cred_tags=None, # Tags should be derived from credential values - ) - - async with context.profile.session() as session: - vc_holder = session.inject(VCHolder) - - await vc_holder.store_credential(vc_record) diff --git a/aries_cloudagent/vc/vc_ld/tests/test_manager.py b/aries_cloudagent/vc/vc_ld/tests/test_manager.py index 0f2b06888f..f1f67ce980 100644 --- a/aries_cloudagent/vc/vc_ld/tests/test_manager.py +++ b/aries_cloudagent/vc/vc_ld/tests/test_manager.py @@ -171,7 +171,7 @@ async def test_get_did_info_for_did_sov( @pytest.mark.asyncio -async def test_get_suite_for_credential(manager: VcLdpManager): +async def test_get_suite_for_document(manager: VcLdpManager): vc = VerifiableCredential.deserialize(VC["credential"]) options = LDProofVCOptions.deserialize(VC["options"]) @@ -184,7 +184,7 @@ async def test_get_suite_for_credential(manager: VcLdpManager): "_did_info_for_did", mock.CoroutineMock(), ) as mock_did_info: - suite = await manager._get_suite_for_credential(vc, options) + suite = await manager._get_suite_for_document(vc, options) assert suite.signature_type == options.proof_type assert isinstance(suite, Ed25519Signature2018) diff --git a/aries_cloudagent/vc_api/__init__.py b/aries_cloudagent/vc_api/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/aries_cloudagent/vc_api/examples.py b/aries_cloudagent/vc_api/examples.py deleted file mode 100644 index 7db1454847..0000000000 --- a/aries_cloudagent/vc_api/examples.py +++ /dev/null @@ -1,189 +0,0 @@ -"""VC-API requests and responses examples.""" - -from marshmallow import Schema, fields - -EXAMPLE_DID = "did:key:z6MkukGVb3mRvTu1msArDKY9UwxeZFGjmwnCKtdQttr4Fk6i" -EXAMPLE_VERIFICATION_METHOD = f"{EXAMPLE_DID}#{EXAMPLE_DID.split(':')[-1]}" -EXAMPLE_CRED_PROOF = "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ -SCPQDsbwaEo7aZ28hrpWOPa8vu3CHqM0do6UkVNVM8hM0__1rryDnzeU-V7_lvjxrhqs998rhnojE4UuOLZTDw" -EXAMPLE_PRES_PROOF = "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..\ -eqWrb_JcMPM1m1tBotnI01WPaV5_cQLUJslkT2oPD00MBb5xUZqIIzxCWdkYHhBo4IVDYCL3RkG5WDWdQ8AyBw" - - -class IssueCredentialRequest(Schema): - """Issue credential request. - - Based on https://w3c-ccg.github.io/vc-api/#issue-credential - - """ - - credential = fields.Dict( - metadata={ - "example": { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "credentialSubject": {"id": EXAMPLE_DID}, - "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": EXAMPLE_DID, - "type": ["VerifiableCredential"], - } - } - ) - options = fields.Dict(metadata={"example": {}}) - - -class IssueCredentialResponse(Schema): - """Issue credential response. - - Based on https://w3c-ccg.github.io/vc-api/#issue-credential - - """ - - verifiableCredential = fields.Dict( - metadata={ - "example": { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "type": ["VerifiableCredential"], - "issuer": EXAMPLE_DID, - "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": {"id": EXAMPLE_DID}, - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": EXAMPLE_VERIFICATION_METHOD, - "created": "2024-01-14T20:04:36+00:00", - "jws": EXAMPLE_CRED_PROOF, - }, - } - } - ) - - -VerifyCredentialRequest = IssueCredentialResponse() - - -class VerifyCredentialResponse(Schema): - """Verify credential response. - - Based on https://w3c-ccg.github.io/vc-api/#verify-credential - - """ - - verified = fields.Bool(metadata={"example": True}) - document = fields.Dict(metadata={"example": {}}) - # results = fields.List( - # metadata={ - # "example": [{ - # "verified": True, - # "proof": {}, - # "purpose_result": { - # "valid": True, - # "controller": {} - # } - # }] - # } - # ) - - -class ProvePresentationRequest(Schema): - """Prove presentation request. - - Based on https://w3c-ccg.github.io/vc-api/#prove-presentation - - """ - - presentation = fields.Dict( - metadata={ - "example": { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "type": ["VerifiablePresentation"], - "holder": EXAMPLE_DID, - "verifiableCredential": [ - { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "type": ["VerifiableCredential"], - "issuer": EXAMPLE_DID, - "issuanceDate": "2010-01-01T19:23:24Z", - "credentialSubject": {"id": EXAMPLE_DID}, - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": EXAMPLE_VERIFICATION_METHOD, - "created": "2024-01-14T20:04:36+00:00", - "jws": EXAMPLE_CRED_PROOF, - }, - } - ], - } - } - ) - options = fields.Dict(metadata={"example": {}}) - - -class ProvePresentationResponse(Schema): - """Prove presentation response. - - Based on https://w3c-ccg.github.io/vc-api/#prove-presentation - - """ - - verifiablePresentation = fields.Dict( - metadata={ - "example": { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "type": ["VerifiablePresentation"], - "holder": EXAMPLE_DID, - "verifiableCredential": [ - { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "credentialSubject": {"id": EXAMPLE_DID}, - "issuanceDate": "2010-01-01T19:23:24Z", - "issuer": EXAMPLE_DID, - "type": ["VerifiableCredential"], - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": EXAMPLE_VERIFICATION_METHOD, - "created": "2024-01-14T18:33:31+00:00", - "jws": EXAMPLE_CRED_PROOF, - }, - } - ], - "proof": { - "type": "Ed25519Signature2018", - "proofPurpose": "assertionMethod", - "verificationMethod": EXAMPLE_VERIFICATION_METHOD, - "created": "2024-01-14T22:03:36+00:00", - "jws": EXAMPLE_PRES_PROOF, - }, - } - } - ) - - -VerifyPresentationRequest = ProvePresentationResponse() - - -class VerifyPresentationResponse(Schema): - """Verify presentation response. - - Based on https://w3c-ccg.github.io/vc-api/#verify-presentation - - """ - - verified = fields.Bool(metadata={"example": True}) - presentation_result = fields.Dict( - metadata={ - "example": { - "verified": True, - "document": {}, - } - } - ) - # credential_results = fields.List( - # metadata={ - # "example": [{ - # "verified": True, - # "document": {}, - # }] - # } - # ) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py deleted file mode 100644 index 4f359297fd..0000000000 --- a/aries_cloudagent/vc_api/routes.py +++ /dev/null @@ -1,227 +0,0 @@ -"""VC-API Routes.""" - -from aiohttp import web -from aiohttp_apispec import docs, request_schema, response_schema - -from ..admin.request_context import AdminRequestContext -from ..config.base import InjectionError -from ..resolver.base import ResolverError -from ..wallet.error import WalletError - -from ..vc.ld_proofs.document_loader import DocumentLoader -from ..vc.ld_proofs.purposes.assertion_proof_purpose import AssertionProofPurpose - -from ..vc.vc_ld.verify import verify_credential, verify_presentation -from ..vc.vc_ld.issue import issue as issue_credential -from ..vc.vc_ld.prove import sign_presentation -from ..vc.vc_ld.store import store_credential -from ..vc.vc_ld.manager import VcLdpManager, VcLdpManagerError -from ..vc.vc_ld.models.credential import VerifiableCredential -from ..vc.vc_ld.models.presentation import VerifiablePresentation -from ..vc.vc_ld.models.options import LDProofVCOptions - -from .examples import ( - IssueCredentialRequest, - IssueCredentialResponse, - VerifyCredentialRequest, - VerifyCredentialResponse, - ProvePresentationRequest, - ProvePresentationResponse, - VerifyPresentationRequest, - VerifyPresentationResponse, -) - -"""CREDENTIALS""" - - -@docs(tags=["vc-api"], summary="Issue a credential") -@request_schema(IssueCredentialRequest) -@response_schema(IssueCredentialResponse, 201) -async def issue_credential_route(request: web.BaseRequest): - """Request handler for signing a jsonld doc. - - Args: - request: aiohttp request object - - """ - body = await request.json() - credential = VerifiableCredential.deserialize(body["credential"]) - - options = {} if "options" not in body else body["options"] - # Default to Ed25519Signature2018 if no proof type was provided - options["proofType"] = ( - "Ed25519Signature2018" if "proofType" not in options else options["proofType"] - ) - options = LDProofVCOptions.deserialize(options) - try: - context: AdminRequestContext = request["context"] - manager = context.inject(VcLdpManager) - vc = await issue_credential( - credential=credential.serialize(), - suite=await manager._get_suite_for_credential(credential, options), - document_loader=manager.profile.inject(DocumentLoader), - purpose=AssertionProofPurpose(), - ) - except VcLdpManagerError as err: - return web.json_response({"message": str(err)}, status=400) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"verifiableCredential": vc}, status=201) - - -@docs(tags=["vc-api"], summary="Store a credential") -@request_schema(VerifyCredentialRequest) -@response_schema(VerifyCredentialResponse, 200) -async def store_credential_route(request: web.BaseRequest): - """Request handler for storing a jsonld VC. - - Args: - request: aiohttp request object - - """ - body = await request.json() - vc = VerifiableCredential.deserialize(body["verifiableCredential"]) - - try: - context: AdminRequestContext = request["context"] - manager = context.inject(VcLdpManager) - await manager.verify_credential(vc) - await store_credential( - credential=vc, - document_loader=manager.profile.inject(DocumentLoader), - context=context, - cred_id=None, - ) - except VcLdpManagerError as err: - return web.json_response({"error": str(err)}, status=400) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="Bad credential") - return web.json_response({"message": "Credential stored"}, status=200) - - -@docs(tags=["vc-api"], summary="Verify a credential") -@request_schema(VerifyCredentialRequest) -@response_schema(VerifyCredentialResponse, 200) -async def verify_credential_route(request: web.BaseRequest): - """Request handler for verifying a jsonld doc. - - Args: - request: aiohttp request object - - """ - body = await request.json() - vc = VerifiableCredential.deserialize(body.get("verifiableCredential")) - try: - context: AdminRequestContext = request["context"] - manager = context.inject(VcLdpManager) - result = await verify_credential( - credential=vc.serialize(), - suites=await manager._get_all_suites(), - document_loader=manager.profile.inject(DocumentLoader), - ) - return web.json_response(result.serialize()) - except (VcLdpManagerError, ResolverError, ValueError) as error: - raise web.HTTPBadRequest(reason=str(error)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - - -"""PRESENTATIONS""" - - -@docs(tags=["vc-api"], summary="Prove a presentation") -@request_schema(ProvePresentationRequest) -@response_schema(ProvePresentationResponse, 201) -async def prove_presentation_route(request: web.BaseRequest): - """Request handler for signing a jsonld doc. - - Args: - request: aiohttp request object - - """ - body = await request.json() - presentation = VerifiablePresentation.deserialize(body["presentation"]) - - options = {} if "options" not in body else body["options"] - # Default to Ed25519Signature2018 if no proof type was provided - options["proofType"] = ( - "Ed25519Signature2018" if "proofType" not in options else options["proofType"] - ) - options = LDProofVCOptions.deserialize(options) - - try: - context: AdminRequestContext = request["context"] - manager = context.inject(VcLdpManager) - vp = await sign_presentation( - presentation=presentation.serialize(), - suite=await manager._get_suite_for_credential(presentation, options), - document_loader=manager.profile.inject(DocumentLoader), - purpose=AssertionProofPurpose(), - ) - except VcLdpManagerError as err: - return web.json_response({"error": str(err)}, status=400) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"verifiablePresentation": vp}, status=201) - - -@docs(tags=["vc-api"], summary="Verify a presentation") -@request_schema(VerifyPresentationRequest) -@response_schema(VerifyPresentationResponse, 201) -async def verify_presentation_route(request: web.BaseRequest): - """Request handler for verifying a jsonld doc. - - Args: - request: aiohttp request object - - """ - body = await request.json() - vp = VerifiablePresentation.deserialize(body.get("verifiablePresentation")) - - options = {} if "options" not in body else body["options"] - options = LDProofVCOptions.deserialize(options) - try: - context: AdminRequestContext = request["context"] - manager = context.inject(VcLdpManager) - result = await verify_presentation( - presentation=vp.serialize(), - suites=await manager._get_all_suites(), - document_loader=manager.profile.inject(DocumentLoader), - purpose=AssertionProofPurpose(), - ) - return web.json_response(result.serialize()) - except (VcLdpManagerError, ResolverError, ValueError) as error: - raise web.HTTPBadRequest(reason=str(error)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - - -async def register(app: web.Application): - """Register routes.""" - - app.add_routes( - [ - web.post("/credentials/issue", issue_credential_route), - web.post("/credentials/store", store_credential_route), - web.post("/credentials/verify", verify_credential_route), - web.post("/presentations/prove", prove_presentation_route), - web.post("/presentations/verify", verify_presentation_route), - ] - ) - - -def post_process_routes(app: web.Application): - """Amend swagger API.""" - # Add top-level tags description - if "tags" not in app._state["swagger_dict"]: - app._state["swagger_dict"]["tags"] = [] - app._state["swagger_dict"]["tags"].append( - { - "name": "vc-api", - "description": "Manage W3C credentials and presentations", - "externalDocs": { - "description": "Specification", - "url": "https://w3c-ccg.github.io/vc-api", - }, - } - ) From e021fe4c2f1f7613e2ce9493e8d2962fa9b63cb7 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Tue, 23 Jan 2024 18:08:04 +0000 Subject: [PATCH 21/26] Added custom vc-api request schemas Signed-off-by: pstlouis --- aries_cloudagent/config/default_context.py | 1 + aries_cloudagent/vc/routes.py | 262 ------------------ aries_cloudagent/vc_api/__init__.py | 0 aries_cloudagent/vc_api/models/__init__.py | 0 aries_cloudagent/vc_api/models/credentials.py | 96 +++++++ aries_cloudagent/vc_api/models/options.py | 45 +++ .../vc_api/models/presentations.py | 67 +++++ aries_cloudagent/vc_api/models/proofs.py | 72 +++++ .../vc_api/models/request_schemas.py | 75 +++++ aries_cloudagent/vc_api/routes.py | 168 +++++++++++ aries_cloudagent/vc_api/service.py | 226 +++++++++++++++ 11 files changed, 750 insertions(+), 262 deletions(-) delete mode 100644 aries_cloudagent/vc/routes.py create mode 100644 aries_cloudagent/vc_api/__init__.py create mode 100644 aries_cloudagent/vc_api/models/__init__.py create mode 100644 aries_cloudagent/vc_api/models/credentials.py create mode 100644 aries_cloudagent/vc_api/models/options.py create mode 100644 aries_cloudagent/vc_api/models/presentations.py create mode 100644 aries_cloudagent/vc_api/models/proofs.py create mode 100644 aries_cloudagent/vc_api/models/request_schemas.py create mode 100644 aries_cloudagent/vc_api/routes.py create mode 100644 aries_cloudagent/vc_api/service.py diff --git a/aries_cloudagent/config/default_context.py b/aries_cloudagent/config/default_context.py index 18e5c4a8ca..9645b18fbe 100644 --- a/aries_cloudagent/config/default_context.py +++ b/aries_cloudagent/config/default_context.py @@ -142,6 +142,7 @@ async def load_plugins(self, context: InjectionContext): plugin_registry.register_plugin("aries_cloudagent.resolver") plugin_registry.register_plugin("aries_cloudagent.settings") plugin_registry.register_plugin("aries_cloudagent.vc") + plugin_registry.register_plugin("aries_cloudagent.vc_api") plugin_registry.register_plugin("aries_cloudagent.wallet") if wallet_type == "askar-anoncreds": plugin_registry.register_plugin("aries_cloudagent.anoncreds") diff --git a/aries_cloudagent/vc/routes.py b/aries_cloudagent/vc/routes.py deleted file mode 100644 index adacb397cf..0000000000 --- a/aries_cloudagent/vc/routes.py +++ /dev/null @@ -1,262 +0,0 @@ -"""VC-API Routes.""" - -from aiohttp import web -from aiohttp_apispec import docs, request_schema, response_schema - -from .vc_ld.models.credential import ( - VerifiableCredential, -) - -from .vc_ld.models.presentation import ( - VerifiablePresentation, -) - -from .vc_ld.models.request_schemas import ( - ListCredentialResponseSchema, - IssueCredentialRequestSchema, - IssueCredentialResponseSchema, - VerifyCredentialRequestSchema, - VerifyCredentialResponseSchema, - ProvePresentationRequestSchema, - ProvePresentationResponseSchema, - VerifyPresentationRequestSchema, - VerifyPresentationResponseSchema, -) -from .vc_ld.models.options import LDProofVCOptions -from .vc_ld.manager import VcLdpManager, VcLdpManagerError -from ..admin.request_context import AdminRequestContext -from ..config.base import InjectionError -from ..resolver.base import ResolverError -from ..wallet.error import WalletError -from ..storage.error import StorageError, StorageNotFoundError -from ..storage.vc_holder.base import VCHolder - - -@docs(tags=["vc-api"], summary="List credentials") -@response_schema(ListCredentialResponseSchema(), 200, description="") -async def list_credentials_route(request: web.BaseRequest): - """Request handler for issuing a credential. - - Args: - request: aiohttp request object - - """ - context: AdminRequestContext = request["context"] - async with context.profile.session() as session: - holder = session.inject(VCHolder) - try: - search = holder.search_credentials() - records = await search.fetch() - except StorageNotFoundError as err: - raise web.HTTPNotFound(reason=err.roll_up) from err - except StorageError as err: - raise web.HTTPBadRequest(reason=err.roll_up) from err - return web.json_response([record.serialize()["cred_value"] for record in records]) - - -@docs(tags=["vc-api"], summary="Fetch credential by ID") -@response_schema(ListCredentialResponseSchema(), 200, description="") -async def fetch_credential_route(request: web.BaseRequest): - """Request handler for issuing a credential. - - Args: - request: aiohttp request object - - """ - context: AdminRequestContext = request["context"] - credential_id = request.match_info["credential_id"] - async with context.profile.session() as session: - holder = session.inject(VCHolder) - try: - search = holder.search_credentials(given_id=credential_id.strip('"')) - records = await search.fetch() - record = [record.serialize() for record in records] - credential = record[0]["cred_value"] if len(record) == 1 else None - except StorageNotFoundError as err: - raise web.HTTPNotFound(reason=err.roll_up) from err - except StorageError as err: - raise web.HTTPBadRequest(reason=err.roll_up) from err - return web.json_response(credential) - - -@docs(tags=["vc-api"], summary="Issue a credential") -@request_schema(IssueCredentialRequestSchema()) -@response_schema(IssueCredentialResponseSchema(), 200, description="") -async def issue_credential_route(request: web.BaseRequest): - """Request handler for issuing a credential. - - Args: - request: aiohttp request object - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - credential = VerifiableCredential.deserialize(body["credential"]) - options = {} if "options" not in body else body["options"] - # Default to Ed25519Signature2018 if no proof type was provided - if "type" in options: - options["proofType"] = options.pop("type") - else: - options["proofType"] = ( - "Ed25519Signature2018" - if "proofType" not in options - else options["proofType"] - ) - options = LDProofVCOptions.deserialize(body["options"]) - - try: - manager = context.inject(VcLdpManager) - vc = await manager.issue(credential, options) - except VcLdpManagerError as err: - return web.json_response({"error": str(err)}, status=400) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"verifiableCredential": vc.serialize()}) - - -@docs(tags=["vc-api"], summary="Verify a credential") -@request_schema(VerifyCredentialRequestSchema()) -@response_schema(VerifyCredentialResponseSchema(), 200, description="") -async def verify_credential_route(request: web.BaseRequest): - """Request handler for verifying a credential. - - Args: - request: aiohttp request object - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - vc = body.get("verifiableCredential") - try: - manager = context.inject(VcLdpManager) - vc = VerifiableCredential.deserialize(vc) - result = await manager.verify_credential(vc) - except (VcLdpManagerError, ResolverError, ValueError) as error: - raise web.HTTPBadRequest(reason=str(error)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return web.json_response(result.serialize()) - - -@docs(tags=["vc-api"], summary="Store a credential") -@request_schema(VerifyCredentialRequestSchema) -@response_schema(VerifyCredentialResponseSchema, 200) -async def store_credential_route(request: web.BaseRequest): - """Request handler for storing a credential. - - Args: - request: aiohttp request object - - """ - body = await request.json() - vc = VerifiableCredential.deserialize(body["verifiableCredential"]) - options = {} if "options" not in body else body["options"] - options = LDProofVCOptions.deserialize(body["options"]) - - try: - context: AdminRequestContext = request["context"] - manager = context.inject(VcLdpManager) - await manager.verify_credential(vc) - await manager.store_credential(vc, options) - except VcLdpManagerError as err: - return web.json_response({"error": str(err)}, status=400) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="Bad credential") - return web.json_response({"message": "Credential stored"}, status=200) - - -@docs(tags=["vc-api"], summary="Prove a presentation") -@request_schema(ProvePresentationRequestSchema()) -@response_schema(ProvePresentationResponseSchema(), 200, description="") -async def prove_presentation_route(request: web.BaseRequest): - """Request handler for proving a presentation. - - Args: - request: aiohttp request object - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - presentation = VerifiablePresentation.deserialize(body["presentation"]) - options = {} if "options" not in body else body["options"] - # Default to Ed25519Signature2018 if no proof type was provided - if "type" in options: - options["proofType"] = options.pop("type") - else: - options["proofType"] = ( - "Ed25519Signature2018" - if "proofType" not in options - else options["proofType"] - ) - options = LDProofVCOptions.deserialize(body["options"]) - - try: - manager = context.inject(VcLdpManager) - vp = await manager.prove(presentation, options) - except VcLdpManagerError as err: - return web.json_response({"error": str(err)}, status=400) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return web.json_response({"verifiablePresentation": vp.serialize()}) - - -@docs(tags=["vc-api"], summary="Verify a Presentation") -@request_schema(VerifyPresentationRequestSchema()) -@response_schema(VerifyPresentationResponseSchema(), 200, description="") -async def verify_presentation_route(request: web.BaseRequest): - """Request handler for verifying a presentation. - - Args: - request: aiohttp request object - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - vp = body.get("verifiablePresentation") - try: - manager = context.inject(VcLdpManager) - vp = VerifiablePresentation.deserialize(vp) - options = LDProofVCOptions.deserialize(body["options"]) - result = await manager.verify_presentation(vp, options) - except (VcLdpManagerError, ResolverError, ValueError) as error: - raise web.HTTPBadRequest(reason=str(error)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return web.json_response(result.serialize()) - - -async def register(app: web.Application): - """Register routes.""" - - app.add_routes( - [ - web.get("/vc/credentials", list_credentials_route, allow_head=False), - web.get( - "/vc/credentials/{credential_id}", - fetch_credential_route, - allow_head=False, - ), - web.post("/vc/credentials/issue", issue_credential_route), - web.post("/vc/credentials/store", store_credential_route), - web.post("/vc/credentials/verify", verify_credential_route), - web.post("/vc/presentations/prove", prove_presentation_route), - web.post("/vc/presentations/verify", verify_presentation_route), - ] - ) - - -def post_process_routes(app: web.Application): - """Amend swagger API.""" - # Add top-level tags description - if "tags" not in app._state["swagger_dict"]: - app._state["swagger_dict"]["tags"] = [] - app._state["swagger_dict"]["tags"].append( - { - "name": "vc-api", - "description": "Endpoints for managing w3c credentials and presentations", - "externalDocs": { - "description": "Specification", - "url": "https://w3c-ccg.github.io/vc-api/", - }, - } - ) diff --git a/aries_cloudagent/vc_api/__init__.py b/aries_cloudagent/vc_api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aries_cloudagent/vc_api/models/__init__.py b/aries_cloudagent/vc_api/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aries_cloudagent/vc_api/models/credentials.py b/aries_cloudagent/vc_api/models/credentials.py new file mode 100644 index 0000000000..37c917a13a --- /dev/null +++ b/aries_cloudagent/vc_api/models/credentials.py @@ -0,0 +1,96 @@ +"""Verifiable Credential marshmallow schema classes.""" + +from marshmallow import fields, Schema + +from ...messaging.valid import ( + CREDENTIAL_SUBJECT_EXAMPLE, + CREDENTIAL_STATUS_EXAMPLE, + RFC3339_DATETIME_EXAMPLE, + UUID4_EXAMPLE, + DictOrDictListField, + DIDKey, + StrOrDictField, + UriOrDictField, +) +from ...vc.ld_proofs.constants import ( + CREDENTIALS_CONTEXT_V1_URL, + VERIFIABLE_CREDENTIAL_TYPE, +) +from .proofs import ProofSchema + + +class CredentialSchema(Schema): + """Linked data credential schema. + + Based on https://www.w3.org/TR/vc-data-model + + """ + + context = fields.List( + UriOrDictField(required=True), + data_key="@context", + required=True, + metadata={ + "example": [CREDENTIALS_CONTEXT_V1_URL], + }, + ) + id = fields.Str( + data_key="id", + required=False, + metadata={ + "example": UUID4_EXAMPLE, + }, + ) + type = fields.List( + fields.Str(required=True), + data_key="type", + required=True, + metadata={ + "example": [VERIFIABLE_CREDENTIAL_TYPE], + }, + ) + issuer = StrOrDictField( + data_key="issuer", + required=True, + metadata={ + "example": DIDKey.EXAMPLE, + }, + ) + issuanceDate = fields.Str( + data_key="issuanceDate", + required=True, + metadata={ + "example": RFC3339_DATETIME_EXAMPLE, + }, + ) + expirationDate = fields.Str( + data_key="expirationDate", + required=False, + metadata={ + "example": RFC3339_DATETIME_EXAMPLE, + }, + ) + credentialSubject = DictOrDictListField( + data_key="credentialSubject", + required=True, + metadata={ + "example": CREDENTIAL_SUBJECT_EXAMPLE, + }, + ) + credentialStatus = DictOrDictListField( + data_key="credentialStatus", + required=False, + metadata={ + "example": CREDENTIAL_STATUS_EXAMPLE, + }, + ) + + +class VerifiableCredentialSchema(CredentialSchema): + """Linked data verifiable credential schema. + + Based on https://www.w3.org/TR/vc-data-model + + """ + + proof = fields.Nested(ProofSchema) diff --git a/aries_cloudagent/vc_api/models/options.py b/aries_cloudagent/vc_api/models/options.py new file mode 100644 index 0000000000..e2769a0b3c --- /dev/null +++ b/aries_cloudagent/vc_api/models/options.py @@ -0,0 +1,45 @@ +"""Options for specifying how the linked data proof is created.""" + +from marshmallow import Schema, fields + +from ...messaging.valid import ( + RFC3339_DATETIME_EXAMPLE, +) + + +class OptionsSchema(Schema): + """Linked data proof verifiable credential options schema.""" + + created = fields.Str( + data_key="created", + required=False, + metadata={ + "example": RFC3339_DATETIME_EXAMPLE, + }, + ) + type = fields.Str( + data_key="type", + required=False, + metadata={ + "example": "Ed25519Signature2020", + }, + ) + domain = fields.Str( + data_key="domain", + required=False, + metadata={ + "example": "website.example", + }, + ) + challenge = fields.Str( + data_key="challenge", + required=False, + metadata={ + "example": "6e62f66e-67de-11eb-b490-ef3eeefa55f2", + }, + ) + # TODO enable credentialStatusList publication + # credentialStatus = fields.Dict(data_key="credentialStatus", required=False, + # metadata={ + # "example": {"type": "BitstringStatusList"}, + # }) diff --git a/aries_cloudagent/vc_api/models/presentations.py b/aries_cloudagent/vc_api/models/presentations.py new file mode 100644 index 0000000000..a903d2b95b --- /dev/null +++ b/aries_cloudagent/vc_api/models/presentations.py @@ -0,0 +1,67 @@ +"""Verifiable Presentation model.""" + +from marshmallow import fields, Schema +from ...messaging.valid import ( + DIDKey, + StrOrDictField, + UriOrDictField, + UUID4_EXAMPLE, +) +from ...vc.ld_proofs.constants import ( + CREDENTIALS_CONTEXT_V1_URL, + VERIFIABLE_PRESENTATION_TYPE, +) +from .proofs import ProofSchema + + +class PresentationSchema(Schema): + """Linked data presentation schema. + + Based on https://www.w3.org/TR/vc-data-model + + """ + + context = fields.List( + UriOrDictField(required=True), + data_key="@context", + required=True, + metadata={ + "example": [CREDENTIALS_CONTEXT_V1_URL], + }, + ) + id = fields.Str( + data_key="id", + required=False, + metadata={ + "example": UUID4_EXAMPLE, + }, + ) + type = fields.List( + fields.Str(required=True), + data_key="type", + required=True, + metadata={ + "example": [VERIFIABLE_PRESENTATION_TYPE], + }, + ) + holder = StrOrDictField( + data_key="holder", + required=False, + metadata={ + "example": DIDKey.EXAMPLE, + }, + ) + verifiableCredential = fields.List( + fields.Dict(required=True), + data_key="verifiableCredential", + required=False, + metadata={ + "example": [{}], + }, + ) + + +class VerifiablePresentationSchema(PresentationSchema): + """Single Verifiable Presentation Schema.""" + + proof = fields.Nested(ProofSchema, data_key="proof", required=False) diff --git a/aries_cloudagent/vc_api/models/proofs.py b/aries_cloudagent/vc_api/models/proofs.py new file mode 100644 index 0000000000..b5fce60512 --- /dev/null +++ b/aries_cloudagent/vc_api/models/proofs.py @@ -0,0 +1,72 @@ +"""LinkedDataProof.""" + +from marshmallow import fields, Schema + +from ...messaging.valid import ( + RFC3339_DATETIME_EXAMPLE, +) + + +class ProofSchema(Schema): + """Linked data proof schema. + + Based on https://w3c-ccg.github.io/ld-proofs + + """ + + created = fields.Str( + data_key="created", + required=True, + metadata={ + "example": RFC3339_DATETIME_EXAMPLE, + }, + ) + type = fields.Str( + data_key="type", + required=True, + metadata={ + "example": "Ed25519Signature2020", + }, + ) + domain = fields.Str( + data_key="domain", + required=False, + metadata={ + "example": "website.example", + }, + ) + challenge = fields.Str( + data_key="challenge", + required=False, + metadata={ + "example": "6e62f66e-67de-11eb-b490-ef3eeefa55f2", + }, + ) + proofPurpose = fields.Str( + data_key="proofPurpose", + required=True, + metadata={ + "example": "assertionMethod", + }, + ) + verificationMethod = fields.Str( + data_key="verificationMethod", + required=True, + metadata={ + "example": "did:example:123#key-01", + }, + ) + jws = fields.Str( + data_key="jws", + required=False, + metadata={ + "example": "eyJhbGciOiAiRWRE...BKY5qBQ", + }, + ) + proofValue = fields.Str( + data_key="proofValue", + required=False, + metadata={ + "example": "eyJhbGciOiAiRWRE...BKY5qBQ", + }, + ) diff --git a/aries_cloudagent/vc_api/models/request_schemas.py b/aries_cloudagent/vc_api/models/request_schemas.py new file mode 100644 index 0000000000..507aa072f6 --- /dev/null +++ b/aries_cloudagent/vc_api/models/request_schemas.py @@ -0,0 +1,75 @@ +"""VC-API routes requests marshmallow schema classes.""" + +from marshmallow import fields +from ...messaging.models.openapi import OpenAPISchema + +from ...vc.vc_ld.validation_result import ( + PresentationVerificationResultSchema, +) +from .options import OptionsSchema +from .credentials import ( + CredentialSchema, + VerifiableCredentialSchema, +) +from .presentations import ( + PresentationSchema, + VerifiablePresentationSchema, +) + + +class ListCredentialResponseSchema(OpenAPISchema): + """Response schema for listing credentials.""" + + credentials = [fields.Nested(VerifiableCredentialSchema)] + + +class IssueCredentialRequestSchema(OpenAPISchema): + """Request schema for issuing a credential.""" + + credential = fields.Nested(CredentialSchema) + options = fields.Nested(OptionsSchema) + + +class IssueCredentialResponseSchema(OpenAPISchema): + """Request schema for issuing a credential.""" + + verifiableCredential = fields.Nested(VerifiableCredentialSchema) + + +class VerifyCredentialRequestSchema(OpenAPISchema): + """Request schema for verifying a credential.""" + + verifiableCredential = fields.Nested(VerifiableCredentialSchema) + options = fields.Nested(OptionsSchema) + + +class VerifyCredentialResponseSchema(OpenAPISchema): + """Request schema for verifying an LDP VP.""" + + results = fields.Nested(PresentationVerificationResultSchema) + + +class ProvePresentationRequestSchema(OpenAPISchema): + """Request schema for proving a presentation.""" + + presentation = fields.Nested(PresentationSchema) + options = fields.Nested(OptionsSchema) + + +class ProvePresentationResponseSchema(OpenAPISchema): + """Request schema for proving a presentation.""" + + verifiablePresentation = fields.Nested(VerifiablePresentationSchema) + + +class VerifyPresentationRequestSchema(OpenAPISchema): + """Request schema for verifying a credential.""" + + verifiablePresentation = fields.Nested(VerifiablePresentationSchema) + options = fields.Nested(OptionsSchema) + + +class VerifyPresentationResponseSchema(OpenAPISchema): + """Request schema for verifying an LDP VP.""" + + results = fields.Nested(PresentationVerificationResultSchema) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py new file mode 100644 index 0000000000..fd89d04da6 --- /dev/null +++ b/aries_cloudagent/vc_api/routes.py @@ -0,0 +1,168 @@ +"""VC-API Routes.""" + +from aiohttp import web +from aiohttp_apispec import docs, request_schema, response_schema + +from .service import ( + list_stored_credentials, + fetch_stored_credential, + issue_credential, + store_issued_credential, + verify_credential, + prove_presentation, + verify_presentation, +) +from .models.request_schemas import ( + ListCredentialResponseSchema, + IssueCredentialRequestSchema, + IssueCredentialResponseSchema, + VerifyCredentialRequestSchema, + VerifyCredentialResponseSchema, + ProvePresentationRequestSchema, + ProvePresentationResponseSchema, + VerifyPresentationRequestSchema, + VerifyPresentationResponseSchema, +) + + +@docs(tags=["vc-api"], summary="List credentials") +@response_schema(ListCredentialResponseSchema(), 200, description="") +async def list_credentials_route(request: web.BaseRequest): + """Request handler for issuing a credential. + + Args: + request: aiohttp request object + + """ + records = list_stored_credentials(request) + response = [record.serialize()["cred_value"] for record in records] + return web.json_response(response) + + +@docs(tags=["vc-api"], summary="Fetch credential by ID") +# @response_schema(ListCredentialResponseSchema(), 200, description="") +async def fetch_credential_route(request: web.BaseRequest): + """Request handler for issuing a credential. + + Args: + request: aiohttp request object + + """ + credential = await fetch_stored_credential(request) + return web.json_response(credential) + + +@docs(tags=["vc-api"], summary="Issue a credential") +@request_schema(IssueCredentialRequestSchema()) +@response_schema(IssueCredentialResponseSchema(), 200, description="") +async def issue_credential_route(request: web.BaseRequest): + """Request handler for issuing a credential. + + Args: + request: aiohttp request object + + """ + vc = await issue_credential(request) + response = {"verifiableCredential": vc.serialize()} + return web.json_response(response, status=201) + + +@docs(tags=["vc-api"], summary="Verify a credential") +@request_schema(VerifyCredentialRequestSchema()) +@response_schema(VerifyCredentialResponseSchema(), 200, description="") +async def verify_credential_route(request: web.BaseRequest): + """Request handler for verifying a credential. + + Args: + request: aiohttp request object + + """ + verified = await verify_credential(request) + response = verified.serialize() + return web.json_response(response) + + +@docs(tags=["vc-api"], summary="Store a credential") +@request_schema(VerifyCredentialRequestSchema) +@response_schema(VerifyCredentialResponseSchema, 200) +async def store_credential_route(request: web.BaseRequest): + """Request handler for storing a credential. + + Args: + request: aiohttp request object + + """ + credential_stored = await store_issued_credential(request) + if not credential_stored: + response = {"message": "Credential not stored"} + return web.json_response(response, status=400) + + response = {"message": "Credential stored"} + return web.json_response(response, status=200) + + +@docs(tags=["vc-api"], summary="Prove a presentation") +@request_schema(ProvePresentationRequestSchema()) +@response_schema(ProvePresentationResponseSchema(), 200, description="") +async def prove_presentation_route(request: web.BaseRequest): + """Request handler for proving a presentation. + + Args: + request: aiohttp request object + + """ + vp = await prove_presentation(request) + response = {"verifiablePresentation": vp.serialize()} + return web.json_response(response) + + +@docs(tags=["vc-api"], summary="Verify a Presentation") +@request_schema(VerifyPresentationRequestSchema()) +@response_schema(VerifyPresentationResponseSchema(), 200, description="") +async def verify_presentation_route(request: web.BaseRequest): + """Request handler for verifying a presentation. + + Args: + request: aiohttp request object + + """ + verified = await verify_presentation(request) + response = verified.serialize() + return web.json_response(response) + + +async def register(app: web.Application): + """Register routes.""" + + app.add_routes( + [ + web.get("/vc/credentials", list_credentials_route, allow_head=False), + web.get( + "/vc/credentials/{credential_id}", + fetch_credential_route, + allow_head=False, + ), + web.post("/vc/credentials/issue", issue_credential_route), + web.post("/vc/credentials/store", store_credential_route), + web.post("/vc/credentials/verify", verify_credential_route), + web.post("/vc/presentations/prove", prove_presentation_route), + web.post("/vc/presentations/verify", verify_presentation_route), + ] + ) + + +def post_process_routes(app: web.Application): + """Amend swagger API.""" + # Add top-level tags description + if "tags" not in app._state["swagger_dict"]: + app._state["swagger_dict"]["tags"] = [] + app._state["swagger_dict"]["tags"].append( + { + "name": "vc-api", + "description": "Endpoints for managing w3c credentials and presentations", + "externalDocs": { + "description": "Specification", + "url": "https://w3c-ccg.github.io/vc-api/", + }, + } + ) diff --git a/aries_cloudagent/vc_api/service.py b/aries_cloudagent/vc_api/service.py new file mode 100644 index 0000000000..1c55c7bcd8 --- /dev/null +++ b/aries_cloudagent/vc_api/service.py @@ -0,0 +1,226 @@ +"""VC-API Service for interacting with the VcLdpManager.""" + +from aiohttp import web + +from ..vc.vc_ld.manager import VcLdpManager as VcManager +from ..vc.vc_ld.manager import VcLdpManagerError as VcManagerError +from ..admin.request_context import AdminRequestContext +from ..config.base import InjectionError +from ..resolver.base import ResolverError +from ..wallet.error import WalletError +from ..storage.error import StorageError, StorageNotFoundError +from ..storage.vc_holder.base import VCHolder + +from ..vc.vc_ld.models.credential import ( + VerifiableCredential, +) + +from ..vc.vc_ld.models.presentation import ( + VerifiablePresentation, +) + +from ..vc.vc_ld.models.options import LDProofVCOptions + + +async def list_stored_credentials(request): + """List stored credentials. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + list: Stored verifiable credentials + + """ + context: AdminRequestContext = request["context"] + async with context.profile.session() as session: + holder = session.inject(VCHolder) + try: + search = holder.search_credentials() + records = await search.fetch() + except StorageNotFoundError as err: + raise web.HTTPNotFound(reason=err.roll_up) from err + except StorageError as err: + raise web.HTTPBadRequest(reason=err.roll_up) from err + return records + + +async def fetch_stored_credential(request): + """Fetch stored credential by id. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + VerifiableCredential: A stored verifiable credential + + """ + context: AdminRequestContext = request["context"] + credential_id = request.match_info["credential_id"] + async with context.profile.session() as session: + holder = session.inject(VCHolder) + try: + search = holder.search_credentials(given_id=credential_id.strip('"')) + records = await search.fetch() + record = [record.serialize() for record in records] + credential = record[0]["cred_value"] if len(record) == 1 else None + except StorageNotFoundError as err: + raise web.HTTPNotFound(reason=err.roll_up) from err + except StorageError as err: + raise web.HTTPBadRequest(reason=err.roll_up) from err + return credential + + +async def issue_credential(request): + """Issue credential. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + VerifiableCredential: A verifiable credential + + """ + context: AdminRequestContext = request["context"] + body = await request.json() + credential = body["credential"] + options = {} if "options" not in body else body["options"] + # Default to Ed25519Signature2020 if no proof type is provided + options["proofType"] = ( + options.pop("type") if "type" in options else "Ed25519Signature2018" + ) + try: + credential = VerifiableCredential.deserialize(credential) + options = LDProofVCOptions.deserialize(options) + manager = context.inject(VcManager) + vc = await manager.issue(credential, options) + except VcManagerError as err: + raise web.HTTPBadRequest(reason=str(err)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return vc + + +async def store_issued_credential(request): + """Store issued credential. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + Bool: If the credential has been stored. + + """ + body = await request.json() + vc = body["verifiableCredential"] + options = {} if "options" not in body else body["options"] + + try: + vc = VerifiableCredential.deserialize(vc) + options = LDProofVCOptions.deserialize(options) + context: AdminRequestContext = request["context"] + manager = context.inject(VcManager) + await manager.verify_credential(vc) + await manager.store_credential(vc, options) + except VcManagerError as err: + raise web.HTTPBadRequest(reason=str(err)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="Bad credential") + return True + + +async def verify_credential(request): + """Verify credential. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + PresentationVerificationResultSchema: Results of the verification. + + """ + context: AdminRequestContext = request["context"] + body = await request.json() + vc = body.get("verifiableCredential") + options = {} if "options" not in body else body["options"] + try: + vc = VerifiableCredential.deserialize(vc) + options = LDProofVCOptions.deserialize(options) + manager = context.inject(VcManager) + result = await manager.verify_credential(vc) + except (VcManagerError, ResolverError, ValueError) as error: + raise web.HTTPBadRequest(reason=str(error)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return result + + +async def prove_presentation(request): + """Prove presentation. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + VerifiablePresentation: verifiable presentation. + + """ + context: AdminRequestContext = request["context"] + body = await request.json() + presentation = body["presentation"] + options = {} if "options" not in body else body["options"] + # Default to Ed25519Signature2020 if no proof type is provided + options["proofType"] = ( + options.pop("type") if "type" in options else "Ed25519Signature2018" + ) + + try: + presentation = VerifiablePresentation.deserialize(presentation) + options = LDProofVCOptions.deserialize(options) + manager = context.inject(VcManager) + vp = await manager.prove(presentation, options) + except VcManagerError as err: + raise web.HTTPBadRequest(reason=str(err)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return vp + + +async def verify_presentation(request): + """Verify presentation. + + Process the web request and pass it to the VcLdpManage. + + Args: + request (web.BaseRequest): aiohttp web request object. + + Returns: + PresentationVerificationResultSchema: Results of the verification. + + """ + context: AdminRequestContext = request["context"] + body = await request.json() + vp = body.get("verifiablePresentation") + options = {} if "options" not in body else body["options"] + try: + vp = VerifiablePresentation.deserialize(vp) + options = LDProofVCOptions.deserialize(options) + manager = context.inject(VcManager) + result = await manager.verify_presentation(vp, options) + except (VcManagerError, ResolverError, ValueError) as err: + raise web.HTTPBadRequest(reason=str(err)) + except (WalletError, InjectionError): + raise web.HTTPForbidden(reason="No wallet available") + return result From c4e945c2f9343dd476b0f18c2d586eefe586cbb8 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Tue, 23 Jan 2024 18:21:04 +0000 Subject: [PATCH 22/26] remove requests schemas from the vc_ld models Signed-off-by: pstlouis --- .../vc/vc_ld/models/request_schemas.py | 72 ------------------- aries_cloudagent/vc_api/service.py | 4 +- 2 files changed, 2 insertions(+), 74 deletions(-) delete mode 100644 aries_cloudagent/vc/vc_ld/models/request_schemas.py diff --git a/aries_cloudagent/vc/vc_ld/models/request_schemas.py b/aries_cloudagent/vc/vc_ld/models/request_schemas.py deleted file mode 100644 index f300697791..0000000000 --- a/aries_cloudagent/vc/vc_ld/models/request_schemas.py +++ /dev/null @@ -1,72 +0,0 @@ -"""VC-API routes requests marshmallow schema classes.""" - -from marshmallow import fields -from ....messaging.models.openapi import OpenAPISchema - -from aries_cloudagent.vc.vc_ld.validation_result import ( - PresentationVerificationResultSchema, -) - -from .options import LDProofVCOptionsSchema -from .credential import ( - CredentialSchema, - VerifiableCredentialSchema, -) -from .presentation import ( - PresentationSchema, - VerifiablePresentationSchema, -) - - -class ListCredentialResponseSchema(OpenAPISchema): - """Response schema for listing credentials.""" - - credentials = [fields.Nested(VerifiableCredentialSchema)] - - -class IssueCredentialRequestSchema(OpenAPISchema): - """Request schema for issuing a credential.""" - - credential = fields.Nested(CredentialSchema) - options = fields.Nested(LDProofVCOptionsSchema) - - -class IssueCredentialResponseSchema(OpenAPISchema): - """Request schema for issuing a credential.""" - - verifiableCredential = fields.Nested(VerifiableCredentialSchema) - - -class VerifyCredentialRequestSchema(OpenAPISchema): - """Request schema for verifying a credential.""" - - verifiableCredential = fields.Nested(VerifiableCredentialSchema) - options = fields.Nested(LDProofVCOptionsSchema) - - -class VerifyCredentialResponseSchema(PresentationVerificationResultSchema): - """Request schema for verifying an LDP VP.""" - - -class ProvePresentationRequestSchema(OpenAPISchema): - """Request schema for proving a presentation.""" - - presentation = fields.Nested(PresentationSchema) - options = fields.Nested(LDProofVCOptionsSchema) - - -class ProvePresentationResponseSchema(OpenAPISchema): - """Request schema for proving a presentation.""" - - verifiablePresentation = fields.Nested(VerifiablePresentationSchema) - - -class VerifyPresentationRequestSchema(OpenAPISchema): - """Request schema for verifying a credential.""" - - verifiablePresentation = fields.Nested(VerifiablePresentationSchema) - options = fields.Nested(LDProofVCOptionsSchema) - - -class VerifyPresentationResponseSchema(PresentationVerificationResultSchema): - """Request schema for verifying an LDP VP.""" diff --git a/aries_cloudagent/vc_api/service.py b/aries_cloudagent/vc_api/service.py index 1c55c7bcd8..76974967e6 100644 --- a/aries_cloudagent/vc_api/service.py +++ b/aries_cloudagent/vc_api/service.py @@ -93,7 +93,7 @@ async def issue_credential(request): options = {} if "options" not in body else body["options"] # Default to Ed25519Signature2020 if no proof type is provided options["proofType"] = ( - options.pop("type") if "type" in options else "Ed25519Signature2018" + options.pop("type") if "type" in options else "Ed25519Signature2020" ) try: credential = VerifiableCredential.deserialize(credential) @@ -183,7 +183,7 @@ async def prove_presentation(request): options = {} if "options" not in body else body["options"] # Default to Ed25519Signature2020 if no proof type is provided options["proofType"] = ( - options.pop("type") if "type" in options else "Ed25519Signature2018" + options.pop("type") if "type" in options else "Ed25519Signature2020" ) try: From f733563fdcb66b2c7b5351fb6d74f303f4c95eb2 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Wed, 24 Jan 2024 14:13:29 +0000 Subject: [PATCH 23/26] ready to merge Signed-off-by: pstlouis --- aries_cloudagent/config/default_context.py | 1 - aries_cloudagent/vc/routes.py | 244 ++++++++++++++++++ .../vc/vc_ld/models/web_schemas.py | 99 +++++++ aries_cloudagent/vc_api/__init__.py | 0 aries_cloudagent/vc_api/models/__init__.py | 0 aries_cloudagent/vc_api/models/credentials.py | 96 ------- aries_cloudagent/vc_api/models/options.py | 45 ---- .../vc_api/models/presentations.py | 67 ----- aries_cloudagent/vc_api/models/proofs.py | 72 ------ .../vc_api/models/request_schemas.py | 75 ------ aries_cloudagent/vc_api/routes.py | 168 ------------ aries_cloudagent/vc_api/service.py | 226 ---------------- 12 files changed, 343 insertions(+), 750 deletions(-) create mode 100644 aries_cloudagent/vc/routes.py create mode 100644 aries_cloudagent/vc/vc_ld/models/web_schemas.py delete mode 100644 aries_cloudagent/vc_api/__init__.py delete mode 100644 aries_cloudagent/vc_api/models/__init__.py delete mode 100644 aries_cloudagent/vc_api/models/credentials.py delete mode 100644 aries_cloudagent/vc_api/models/options.py delete mode 100644 aries_cloudagent/vc_api/models/presentations.py delete mode 100644 aries_cloudagent/vc_api/models/proofs.py delete mode 100644 aries_cloudagent/vc_api/models/request_schemas.py delete mode 100644 aries_cloudagent/vc_api/routes.py delete mode 100644 aries_cloudagent/vc_api/service.py diff --git a/aries_cloudagent/config/default_context.py b/aries_cloudagent/config/default_context.py index 9645b18fbe..18e5c4a8ca 100644 --- a/aries_cloudagent/config/default_context.py +++ b/aries_cloudagent/config/default_context.py @@ -142,7 +142,6 @@ async def load_plugins(self, context: InjectionContext): plugin_registry.register_plugin("aries_cloudagent.resolver") plugin_registry.register_plugin("aries_cloudagent.settings") plugin_registry.register_plugin("aries_cloudagent.vc") - plugin_registry.register_plugin("aries_cloudagent.vc_api") plugin_registry.register_plugin("aries_cloudagent.wallet") if wallet_type == "askar-anoncreds": plugin_registry.register_plugin("aries_cloudagent.anoncreds") diff --git a/aries_cloudagent/vc/routes.py b/aries_cloudagent/vc/routes.py new file mode 100644 index 0000000000..b0b227787f --- /dev/null +++ b/aries_cloudagent/vc/routes.py @@ -0,0 +1,244 @@ +"""VC-API Routes.""" + +from aiohttp import web +from aiohttp_apispec import docs, request_schema, response_schema +from marshmallow.exceptions import ValidationError +from ..admin.request_context import AdminRequestContext +from ..storage.error import StorageError, StorageNotFoundError +from ..wallet.error import WalletError +from ..config.base import InjectionError +from ..resolver.base import ResolverError +from ..storage.vc_holder.base import VCHolder +from .vc_ld.models import web_schemas +from .vc_ld.manager import VcLdpManager +from .vc_ld.manager import VcLdpManagerError +from .vc_ld.models.credential import ( + VerifiableCredential, +) + +from .vc_ld.models.presentation import ( + VerifiablePresentation, +) + +from .vc_ld.models.options import LDProofVCOptions + + +@docs(tags=["vc-api"], summary="List credentials") +@response_schema(web_schemas.ListCredentialsResponse(), 200, description="") +async def list_credentials_route(request: web.BaseRequest): + """Request handler for issuing a credential. + + Args: + request: aiohttp request object + + """ + context: AdminRequestContext = request["context"] + holder = context.inject(VCHolder) + try: + search = holder.search_credentials() + records = [record.serialize()["cred_value"] for record in await search.fetch()] + return web.json_response(records, status=200) + except (StorageError, StorageNotFoundError) as err: + return web.json_response({"message": err.roll_up}, status=400) + + +@docs(tags=["vc-api"], summary="Fetch credential by ID") +@response_schema(web_schemas.FetchCredentialResponse(), 200, description="") +async def fetch_credential_route(request: web.BaseRequest): + """Request handler for issuing a credential. + + Args: + request: aiohttp request object + + """ + context: AdminRequestContext = request["context"] + holder = context.inject(VCHolder) + try: + credential_id = request.match_info["credential_id"].strip('"') + search = holder.search_credentials(given_id=credential_id) + record = [record.serialize()["cred_value"] for record in await search.fetch()] + if len(record) < 1: + return web.json_response({"message": "No credential found"}, status=404) + if len(record) > 1: + return web.json_response(record, status=200) + return web.json_response(record[0], status=200) + except (StorageError, StorageNotFoundError) as err: + return web.json_response({"message": err.roll_up}, status=400) + + +@docs(tags=["vc-api"], summary="Issue a credential") +@request_schema(web_schemas.IssueCredentialRequest()) +@response_schema(web_schemas.IssueCredentialResponse(), 200, description="") +async def issue_credential_route(request: web.BaseRequest): + """Request handler for issuing a credential. + + Args: + request: aiohttp request object + + """ + body = await request.json() + context: AdminRequestContext = request["context"] + manager = context.inject(VcLdpManager) + try: + credential = VerifiableCredential.deserialize(body["credential"]) + options = {} if "options" not in body else body["options"] + # Our request uses the "type" key to represent the proof type (suite) to use + # We must pass this value as "proofType" to the LDProofVCOptions instance + # Default to Ed25519Signature2020 if no proof type is provided + options["proofType"] = ( + options.pop("type") if "type" in options else "Ed25519Signature2020" + ) + options = LDProofVCOptions.deserialize(options) + vc = await manager.issue(credential, options) + response = {"verifiableCredential": vc.serialize()} + return web.json_response(response, status=201) + except (ValidationError, VcLdpManagerError, WalletError, InjectionError) as err: + return web.json_response({"message": str(err)}, status=400) + + +@docs(tags=["vc-api"], summary="Verify a credential") +@request_schema(web_schemas.VerifyCredentialRequest()) +@response_schema(web_schemas.VerifyCredentialResponse(), 200, description="") +async def verify_credential_route(request: web.BaseRequest): + """Request handler for verifying a credential. + + Args: + request: aiohttp request object + + """ + body = await request.json() + context: AdminRequestContext = request["context"] + manager = context.inject(VcLdpManager) + try: + vc = VerifiableCredential.deserialize(body["verifiableCredential"]) + result = await manager.verify_credential(vc) + result = result.serialize() + return web.json_response(result) + except ( + ValidationError, + VcLdpManagerError, + ResolverError, + ValueError, + WalletError, + InjectionError, + ) as err: + return web.json_response({"message": str(err)}, status=400) + + +@docs(tags=["vc-api"], summary="Store a credential") +async def store_credential_route(request: web.BaseRequest): + """Request handler for storing a credential. + + Args: + request: aiohttp request object + + """ + body = await request.json() + context: AdminRequestContext = request["context"] + manager = context.inject(VcLdpManager) + + try: + vc = VerifiableCredential.deserialize(body["verifiableCredential"]) + options = {} if "options" not in body else body["options"] + options = LDProofVCOptions.deserialize(options) + await manager.verify_credential(vc) + await manager.store_credential(vc, options) + return web.json_response({"message": "Credential stored"}, status=200) + except (ValidationError, VcLdpManagerError, WalletError, InjectionError) as err: + return web.json_response({"message": str(err)}, status=400) + + +@docs(tags=["vc-api"], summary="Prove a presentation") +@request_schema(web_schemas.ProvePresentationRequest()) +@response_schema(web_schemas.ProvePresentationResponse(), 200, description="") +async def prove_presentation_route(request: web.BaseRequest): + """Request handler for proving a presentation. + + Args: + request: aiohttp request object + + """ + context: AdminRequestContext = request["context"] + manager = context.inject(VcLdpManager) + body = await request.json() + try: + presentation = VerifiablePresentation.deserialize(body["presentation"]) + options = {} if "options" not in body else body["options"] + # Our request uses the "type" key to represent the proof type (suite) to use + # We must pass this value as "proofType" to the LDProofVCOptions instance + # Default to Ed25519Signature2020 if no proof type is provided + options["proofType"] = ( + options.pop("type") if "type" in options else "Ed25519Signature2020" + ) + options = LDProofVCOptions.deserialize(options) + vp = await manager.prove(presentation, options) + return web.json_response({"verifiablePresentation": vp.serialize()}, status=201) + except (ValidationError, VcLdpManagerError, WalletError, InjectionError) as err: + return web.json_response({"message": str(err)}, status=400) + + +@docs(tags=["vc-api"], summary="Verify a Presentation") +@request_schema(web_schemas.VerifyPresentationRequest()) +@response_schema(web_schemas.VerifyPresentationResponse(), 200, description="") +async def verify_presentation_route(request: web.BaseRequest): + """Request handler for verifying a presentation. + + Args: + request: aiohttp request object + + """ + context: AdminRequestContext = request["context"] + manager = context.inject(VcLdpManager) + body = await request.json() + try: + vp = VerifiablePresentation.deserialize(body["verifiablePresentation"]) + options = {} if "options" not in body else body["options"] + options = LDProofVCOptions.deserialize(options) + verified = await manager.verify_presentation(vp, options) + return web.json_response(verified.serialize(), status=200) + except ( + ValidationError, + WalletError, + InjectionError, + VcLdpManagerError, + ResolverError, + ValueError, + ) as err: + return web.json_response({"message": str(err)}, status=400) + + +async def register(app: web.Application): + """Register routes.""" + + app.add_routes( + [ + web.get("/vc/credentials", list_credentials_route, allow_head=False), + web.get( + "/vc/credentials/{credential_id}", + fetch_credential_route, + allow_head=False, + ), + web.post("/vc/credentials/issue", issue_credential_route), + web.post("/vc/credentials/store", store_credential_route), + web.post("/vc/credentials/verify", verify_credential_route), + web.post("/vc/presentations/prove", prove_presentation_route), + web.post("/vc/presentations/verify", verify_presentation_route), + ] + ) + + +def post_process_routes(app: web.Application): + """Amend swagger API.""" + # Add top-level tags description + if "tags" not in app._state["swagger_dict"]: + app._state["swagger_dict"]["tags"] = [] + app._state["swagger_dict"]["tags"].append( + { + "name": "vc-api", + "description": "Endpoints for managing w3c credentials and presentations", + "externalDocs": { + "description": "Specification", + "url": "https://w3c-ccg.github.io/vc-api/", + }, + } + ) diff --git a/aries_cloudagent/vc/vc_ld/models/web_schemas.py b/aries_cloudagent/vc/vc_ld/models/web_schemas.py new file mode 100644 index 0000000000..38ed843717 --- /dev/null +++ b/aries_cloudagent/vc/vc_ld/models/web_schemas.py @@ -0,0 +1,99 @@ +"""VC-API routes web requests schemas.""" + +from marshmallow import fields, Schema +from ....messaging.models.openapi import OpenAPISchema + +from ....messaging.valid import ( + RFC3339_DATETIME_EXAMPLE, + UUID4_EXAMPLE, +) +from ..validation_result import ( + PresentationVerificationResultSchema, +) +from .options import LDProofVCOptionsSchema +from .credential import ( + CredentialSchema, + VerifiableCredentialSchema, +) +from .presentation import ( + PresentationSchema, + VerifiablePresentationSchema, +) + + +class IssuanceOptionsSchema(Schema): + """Linked data proof verifiable credential options schema.""" + + type = fields.Str(required=False, metadata={"example": "Ed25519Signature2020"}) + created = fields.Str(required=False, metadata={"example": RFC3339_DATETIME_EXAMPLE}) + domain = fields.Str(required=False, metadata={"example": "website.example"}) + challenge = fields.Str(required=False, metadata={"example": UUID4_EXAMPLE}) + credential_status = fields.Dict( + data_key="credentialStatus", + required=False, + metadata={"example": {"type": "StatusList2021"}}, + ) + + +class ListCredentialsResponse(OpenAPISchema): + """Response schema for listing credentials.""" + + results = [fields.Nested(VerifiableCredentialSchema)] + + +class FetchCredentialResponse(OpenAPISchema): + """Response schema for fetching a credential.""" + + results = fields.Nested(VerifiableCredentialSchema) + + +class IssueCredentialRequest(OpenAPISchema): + """Request schema for issuing a credential.""" + + credential = fields.Nested(CredentialSchema) + options = fields.Nested(IssuanceOptionsSchema) + + +class IssueCredentialResponse(OpenAPISchema): + """Request schema for issuing a credential.""" + + verifiableCredential = fields.Nested(VerifiableCredentialSchema) + + +class VerifyCredentialRequest(OpenAPISchema): + """Request schema for verifying a credential.""" + + verifiableCredential = fields.Nested(VerifiableCredentialSchema) + options = fields.Nested(LDProofVCOptionsSchema) + + +class VerifyCredentialResponse(OpenAPISchema): + """Request schema for verifying an LDP VP.""" + + results = fields.Nested(PresentationVerificationResultSchema) + + +class ProvePresentationRequest(OpenAPISchema): + """Request schema for proving a presentation.""" + + presentation = fields.Nested(PresentationSchema) + options = fields.Nested(IssuanceOptionsSchema) + + +class ProvePresentationResponse(OpenAPISchema): + """Request schema for proving a presentation.""" + + verifiablePresentation = fields.Nested(VerifiablePresentationSchema) + + +class VerifyPresentationRequest(OpenAPISchema): + """Request schema for verifying a credential.""" + + verifiablePresentation = fields.Nested(VerifiablePresentationSchema) + options = fields.Nested(LDProofVCOptionsSchema) + + +class VerifyPresentationResponse(OpenAPISchema): + """Request schema for verifying an LDP VP.""" + + results = fields.Nested(PresentationVerificationResultSchema) diff --git a/aries_cloudagent/vc_api/__init__.py b/aries_cloudagent/vc_api/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/aries_cloudagent/vc_api/models/__init__.py b/aries_cloudagent/vc_api/models/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/aries_cloudagent/vc_api/models/credentials.py b/aries_cloudagent/vc_api/models/credentials.py deleted file mode 100644 index 37c917a13a..0000000000 --- a/aries_cloudagent/vc_api/models/credentials.py +++ /dev/null @@ -1,96 +0,0 @@ -"""Verifiable Credential marshmallow schema classes.""" - -from marshmallow import fields, Schema - -from ...messaging.valid import ( - CREDENTIAL_SUBJECT_EXAMPLE, - CREDENTIAL_STATUS_EXAMPLE, - RFC3339_DATETIME_EXAMPLE, - UUID4_EXAMPLE, - DictOrDictListField, - DIDKey, - StrOrDictField, - UriOrDictField, -) -from ...vc.ld_proofs.constants import ( - CREDENTIALS_CONTEXT_V1_URL, - VERIFIABLE_CREDENTIAL_TYPE, -) -from .proofs import ProofSchema - - -class CredentialSchema(Schema): - """Linked data credential schema. - - Based on https://www.w3.org/TR/vc-data-model - - """ - - context = fields.List( - UriOrDictField(required=True), - data_key="@context", - required=True, - metadata={ - "example": [CREDENTIALS_CONTEXT_V1_URL], - }, - ) - id = fields.Str( - data_key="id", - required=False, - metadata={ - "example": UUID4_EXAMPLE, - }, - ) - type = fields.List( - fields.Str(required=True), - data_key="type", - required=True, - metadata={ - "example": [VERIFIABLE_CREDENTIAL_TYPE], - }, - ) - issuer = StrOrDictField( - data_key="issuer", - required=True, - metadata={ - "example": DIDKey.EXAMPLE, - }, - ) - issuanceDate = fields.Str( - data_key="issuanceDate", - required=True, - metadata={ - "example": RFC3339_DATETIME_EXAMPLE, - }, - ) - expirationDate = fields.Str( - data_key="expirationDate", - required=False, - metadata={ - "example": RFC3339_DATETIME_EXAMPLE, - }, - ) - credentialSubject = DictOrDictListField( - data_key="credentialSubject", - required=True, - metadata={ - "example": CREDENTIAL_SUBJECT_EXAMPLE, - }, - ) - credentialStatus = DictOrDictListField( - data_key="credentialStatus", - required=False, - metadata={ - "example": CREDENTIAL_STATUS_EXAMPLE, - }, - ) - - -class VerifiableCredentialSchema(CredentialSchema): - """Linked data verifiable credential schema. - - Based on https://www.w3.org/TR/vc-data-model - - """ - - proof = fields.Nested(ProofSchema) diff --git a/aries_cloudagent/vc_api/models/options.py b/aries_cloudagent/vc_api/models/options.py deleted file mode 100644 index e2769a0b3c..0000000000 --- a/aries_cloudagent/vc_api/models/options.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Options for specifying how the linked data proof is created.""" - -from marshmallow import Schema, fields - -from ...messaging.valid import ( - RFC3339_DATETIME_EXAMPLE, -) - - -class OptionsSchema(Schema): - """Linked data proof verifiable credential options schema.""" - - created = fields.Str( - data_key="created", - required=False, - metadata={ - "example": RFC3339_DATETIME_EXAMPLE, - }, - ) - type = fields.Str( - data_key="type", - required=False, - metadata={ - "example": "Ed25519Signature2020", - }, - ) - domain = fields.Str( - data_key="domain", - required=False, - metadata={ - "example": "website.example", - }, - ) - challenge = fields.Str( - data_key="challenge", - required=False, - metadata={ - "example": "6e62f66e-67de-11eb-b490-ef3eeefa55f2", - }, - ) - # TODO enable credentialStatusList publication - # credentialStatus = fields.Dict(data_key="credentialStatus", required=False, - # metadata={ - # "example": {"type": "BitstringStatusList"}, - # }) diff --git a/aries_cloudagent/vc_api/models/presentations.py b/aries_cloudagent/vc_api/models/presentations.py deleted file mode 100644 index a903d2b95b..0000000000 --- a/aries_cloudagent/vc_api/models/presentations.py +++ /dev/null @@ -1,67 +0,0 @@ -"""Verifiable Presentation model.""" - -from marshmallow import fields, Schema -from ...messaging.valid import ( - DIDKey, - StrOrDictField, - UriOrDictField, - UUID4_EXAMPLE, -) -from ...vc.ld_proofs.constants import ( - CREDENTIALS_CONTEXT_V1_URL, - VERIFIABLE_PRESENTATION_TYPE, -) -from .proofs import ProofSchema - - -class PresentationSchema(Schema): - """Linked data presentation schema. - - Based on https://www.w3.org/TR/vc-data-model - - """ - - context = fields.List( - UriOrDictField(required=True), - data_key="@context", - required=True, - metadata={ - "example": [CREDENTIALS_CONTEXT_V1_URL], - }, - ) - id = fields.Str( - data_key="id", - required=False, - metadata={ - "example": UUID4_EXAMPLE, - }, - ) - type = fields.List( - fields.Str(required=True), - data_key="type", - required=True, - metadata={ - "example": [VERIFIABLE_PRESENTATION_TYPE], - }, - ) - holder = StrOrDictField( - data_key="holder", - required=False, - metadata={ - "example": DIDKey.EXAMPLE, - }, - ) - verifiableCredential = fields.List( - fields.Dict(required=True), - data_key="verifiableCredential", - required=False, - metadata={ - "example": [{}], - }, - ) - - -class VerifiablePresentationSchema(PresentationSchema): - """Single Verifiable Presentation Schema.""" - - proof = fields.Nested(ProofSchema, data_key="proof", required=False) diff --git a/aries_cloudagent/vc_api/models/proofs.py b/aries_cloudagent/vc_api/models/proofs.py deleted file mode 100644 index b5fce60512..0000000000 --- a/aries_cloudagent/vc_api/models/proofs.py +++ /dev/null @@ -1,72 +0,0 @@ -"""LinkedDataProof.""" - -from marshmallow import fields, Schema - -from ...messaging.valid import ( - RFC3339_DATETIME_EXAMPLE, -) - - -class ProofSchema(Schema): - """Linked data proof schema. - - Based on https://w3c-ccg.github.io/ld-proofs - - """ - - created = fields.Str( - data_key="created", - required=True, - metadata={ - "example": RFC3339_DATETIME_EXAMPLE, - }, - ) - type = fields.Str( - data_key="type", - required=True, - metadata={ - "example": "Ed25519Signature2020", - }, - ) - domain = fields.Str( - data_key="domain", - required=False, - metadata={ - "example": "website.example", - }, - ) - challenge = fields.Str( - data_key="challenge", - required=False, - metadata={ - "example": "6e62f66e-67de-11eb-b490-ef3eeefa55f2", - }, - ) - proofPurpose = fields.Str( - data_key="proofPurpose", - required=True, - metadata={ - "example": "assertionMethod", - }, - ) - verificationMethod = fields.Str( - data_key="verificationMethod", - required=True, - metadata={ - "example": "did:example:123#key-01", - }, - ) - jws = fields.Str( - data_key="jws", - required=False, - metadata={ - "example": "eyJhbGciOiAiRWRE...BKY5qBQ", - }, - ) - proofValue = fields.Str( - data_key="proofValue", - required=False, - metadata={ - "example": "eyJhbGciOiAiRWRE...BKY5qBQ", - }, - ) diff --git a/aries_cloudagent/vc_api/models/request_schemas.py b/aries_cloudagent/vc_api/models/request_schemas.py deleted file mode 100644 index 507aa072f6..0000000000 --- a/aries_cloudagent/vc_api/models/request_schemas.py +++ /dev/null @@ -1,75 +0,0 @@ -"""VC-API routes requests marshmallow schema classes.""" - -from marshmallow import fields -from ...messaging.models.openapi import OpenAPISchema - -from ...vc.vc_ld.validation_result import ( - PresentationVerificationResultSchema, -) -from .options import OptionsSchema -from .credentials import ( - CredentialSchema, - VerifiableCredentialSchema, -) -from .presentations import ( - PresentationSchema, - VerifiablePresentationSchema, -) - - -class ListCredentialResponseSchema(OpenAPISchema): - """Response schema for listing credentials.""" - - credentials = [fields.Nested(VerifiableCredentialSchema)] - - -class IssueCredentialRequestSchema(OpenAPISchema): - """Request schema for issuing a credential.""" - - credential = fields.Nested(CredentialSchema) - options = fields.Nested(OptionsSchema) - - -class IssueCredentialResponseSchema(OpenAPISchema): - """Request schema for issuing a credential.""" - - verifiableCredential = fields.Nested(VerifiableCredentialSchema) - - -class VerifyCredentialRequestSchema(OpenAPISchema): - """Request schema for verifying a credential.""" - - verifiableCredential = fields.Nested(VerifiableCredentialSchema) - options = fields.Nested(OptionsSchema) - - -class VerifyCredentialResponseSchema(OpenAPISchema): - """Request schema for verifying an LDP VP.""" - - results = fields.Nested(PresentationVerificationResultSchema) - - -class ProvePresentationRequestSchema(OpenAPISchema): - """Request schema for proving a presentation.""" - - presentation = fields.Nested(PresentationSchema) - options = fields.Nested(OptionsSchema) - - -class ProvePresentationResponseSchema(OpenAPISchema): - """Request schema for proving a presentation.""" - - verifiablePresentation = fields.Nested(VerifiablePresentationSchema) - - -class VerifyPresentationRequestSchema(OpenAPISchema): - """Request schema for verifying a credential.""" - - verifiablePresentation = fields.Nested(VerifiablePresentationSchema) - options = fields.Nested(OptionsSchema) - - -class VerifyPresentationResponseSchema(OpenAPISchema): - """Request schema for verifying an LDP VP.""" - - results = fields.Nested(PresentationVerificationResultSchema) diff --git a/aries_cloudagent/vc_api/routes.py b/aries_cloudagent/vc_api/routes.py deleted file mode 100644 index fd89d04da6..0000000000 --- a/aries_cloudagent/vc_api/routes.py +++ /dev/null @@ -1,168 +0,0 @@ -"""VC-API Routes.""" - -from aiohttp import web -from aiohttp_apispec import docs, request_schema, response_schema - -from .service import ( - list_stored_credentials, - fetch_stored_credential, - issue_credential, - store_issued_credential, - verify_credential, - prove_presentation, - verify_presentation, -) -from .models.request_schemas import ( - ListCredentialResponseSchema, - IssueCredentialRequestSchema, - IssueCredentialResponseSchema, - VerifyCredentialRequestSchema, - VerifyCredentialResponseSchema, - ProvePresentationRequestSchema, - ProvePresentationResponseSchema, - VerifyPresentationRequestSchema, - VerifyPresentationResponseSchema, -) - - -@docs(tags=["vc-api"], summary="List credentials") -@response_schema(ListCredentialResponseSchema(), 200, description="") -async def list_credentials_route(request: web.BaseRequest): - """Request handler for issuing a credential. - - Args: - request: aiohttp request object - - """ - records = list_stored_credentials(request) - response = [record.serialize()["cred_value"] for record in records] - return web.json_response(response) - - -@docs(tags=["vc-api"], summary="Fetch credential by ID") -# @response_schema(ListCredentialResponseSchema(), 200, description="") -async def fetch_credential_route(request: web.BaseRequest): - """Request handler for issuing a credential. - - Args: - request: aiohttp request object - - """ - credential = await fetch_stored_credential(request) - return web.json_response(credential) - - -@docs(tags=["vc-api"], summary="Issue a credential") -@request_schema(IssueCredentialRequestSchema()) -@response_schema(IssueCredentialResponseSchema(), 200, description="") -async def issue_credential_route(request: web.BaseRequest): - """Request handler for issuing a credential. - - Args: - request: aiohttp request object - - """ - vc = await issue_credential(request) - response = {"verifiableCredential": vc.serialize()} - return web.json_response(response, status=201) - - -@docs(tags=["vc-api"], summary="Verify a credential") -@request_schema(VerifyCredentialRequestSchema()) -@response_schema(VerifyCredentialResponseSchema(), 200, description="") -async def verify_credential_route(request: web.BaseRequest): - """Request handler for verifying a credential. - - Args: - request: aiohttp request object - - """ - verified = await verify_credential(request) - response = verified.serialize() - return web.json_response(response) - - -@docs(tags=["vc-api"], summary="Store a credential") -@request_schema(VerifyCredentialRequestSchema) -@response_schema(VerifyCredentialResponseSchema, 200) -async def store_credential_route(request: web.BaseRequest): - """Request handler for storing a credential. - - Args: - request: aiohttp request object - - """ - credential_stored = await store_issued_credential(request) - if not credential_stored: - response = {"message": "Credential not stored"} - return web.json_response(response, status=400) - - response = {"message": "Credential stored"} - return web.json_response(response, status=200) - - -@docs(tags=["vc-api"], summary="Prove a presentation") -@request_schema(ProvePresentationRequestSchema()) -@response_schema(ProvePresentationResponseSchema(), 200, description="") -async def prove_presentation_route(request: web.BaseRequest): - """Request handler for proving a presentation. - - Args: - request: aiohttp request object - - """ - vp = await prove_presentation(request) - response = {"verifiablePresentation": vp.serialize()} - return web.json_response(response) - - -@docs(tags=["vc-api"], summary="Verify a Presentation") -@request_schema(VerifyPresentationRequestSchema()) -@response_schema(VerifyPresentationResponseSchema(), 200, description="") -async def verify_presentation_route(request: web.BaseRequest): - """Request handler for verifying a presentation. - - Args: - request: aiohttp request object - - """ - verified = await verify_presentation(request) - response = verified.serialize() - return web.json_response(response) - - -async def register(app: web.Application): - """Register routes.""" - - app.add_routes( - [ - web.get("/vc/credentials", list_credentials_route, allow_head=False), - web.get( - "/vc/credentials/{credential_id}", - fetch_credential_route, - allow_head=False, - ), - web.post("/vc/credentials/issue", issue_credential_route), - web.post("/vc/credentials/store", store_credential_route), - web.post("/vc/credentials/verify", verify_credential_route), - web.post("/vc/presentations/prove", prove_presentation_route), - web.post("/vc/presentations/verify", verify_presentation_route), - ] - ) - - -def post_process_routes(app: web.Application): - """Amend swagger API.""" - # Add top-level tags description - if "tags" not in app._state["swagger_dict"]: - app._state["swagger_dict"]["tags"] = [] - app._state["swagger_dict"]["tags"].append( - { - "name": "vc-api", - "description": "Endpoints for managing w3c credentials and presentations", - "externalDocs": { - "description": "Specification", - "url": "https://w3c-ccg.github.io/vc-api/", - }, - } - ) diff --git a/aries_cloudagent/vc_api/service.py b/aries_cloudagent/vc_api/service.py deleted file mode 100644 index 76974967e6..0000000000 --- a/aries_cloudagent/vc_api/service.py +++ /dev/null @@ -1,226 +0,0 @@ -"""VC-API Service for interacting with the VcLdpManager.""" - -from aiohttp import web - -from ..vc.vc_ld.manager import VcLdpManager as VcManager -from ..vc.vc_ld.manager import VcLdpManagerError as VcManagerError -from ..admin.request_context import AdminRequestContext -from ..config.base import InjectionError -from ..resolver.base import ResolverError -from ..wallet.error import WalletError -from ..storage.error import StorageError, StorageNotFoundError -from ..storage.vc_holder.base import VCHolder - -from ..vc.vc_ld.models.credential import ( - VerifiableCredential, -) - -from ..vc.vc_ld.models.presentation import ( - VerifiablePresentation, -) - -from ..vc.vc_ld.models.options import LDProofVCOptions - - -async def list_stored_credentials(request): - """List stored credentials. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - list: Stored verifiable credentials - - """ - context: AdminRequestContext = request["context"] - async with context.profile.session() as session: - holder = session.inject(VCHolder) - try: - search = holder.search_credentials() - records = await search.fetch() - except StorageNotFoundError as err: - raise web.HTTPNotFound(reason=err.roll_up) from err - except StorageError as err: - raise web.HTTPBadRequest(reason=err.roll_up) from err - return records - - -async def fetch_stored_credential(request): - """Fetch stored credential by id. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - VerifiableCredential: A stored verifiable credential - - """ - context: AdminRequestContext = request["context"] - credential_id = request.match_info["credential_id"] - async with context.profile.session() as session: - holder = session.inject(VCHolder) - try: - search = holder.search_credentials(given_id=credential_id.strip('"')) - records = await search.fetch() - record = [record.serialize() for record in records] - credential = record[0]["cred_value"] if len(record) == 1 else None - except StorageNotFoundError as err: - raise web.HTTPNotFound(reason=err.roll_up) from err - except StorageError as err: - raise web.HTTPBadRequest(reason=err.roll_up) from err - return credential - - -async def issue_credential(request): - """Issue credential. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - VerifiableCredential: A verifiable credential - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - credential = body["credential"] - options = {} if "options" not in body else body["options"] - # Default to Ed25519Signature2020 if no proof type is provided - options["proofType"] = ( - options.pop("type") if "type" in options else "Ed25519Signature2020" - ) - try: - credential = VerifiableCredential.deserialize(credential) - options = LDProofVCOptions.deserialize(options) - manager = context.inject(VcManager) - vc = await manager.issue(credential, options) - except VcManagerError as err: - raise web.HTTPBadRequest(reason=str(err)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return vc - - -async def store_issued_credential(request): - """Store issued credential. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - Bool: If the credential has been stored. - - """ - body = await request.json() - vc = body["verifiableCredential"] - options = {} if "options" not in body else body["options"] - - try: - vc = VerifiableCredential.deserialize(vc) - options = LDProofVCOptions.deserialize(options) - context: AdminRequestContext = request["context"] - manager = context.inject(VcManager) - await manager.verify_credential(vc) - await manager.store_credential(vc, options) - except VcManagerError as err: - raise web.HTTPBadRequest(reason=str(err)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="Bad credential") - return True - - -async def verify_credential(request): - """Verify credential. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - PresentationVerificationResultSchema: Results of the verification. - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - vc = body.get("verifiableCredential") - options = {} if "options" not in body else body["options"] - try: - vc = VerifiableCredential.deserialize(vc) - options = LDProofVCOptions.deserialize(options) - manager = context.inject(VcManager) - result = await manager.verify_credential(vc) - except (VcManagerError, ResolverError, ValueError) as error: - raise web.HTTPBadRequest(reason=str(error)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return result - - -async def prove_presentation(request): - """Prove presentation. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - VerifiablePresentation: verifiable presentation. - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - presentation = body["presentation"] - options = {} if "options" not in body else body["options"] - # Default to Ed25519Signature2020 if no proof type is provided - options["proofType"] = ( - options.pop("type") if "type" in options else "Ed25519Signature2020" - ) - - try: - presentation = VerifiablePresentation.deserialize(presentation) - options = LDProofVCOptions.deserialize(options) - manager = context.inject(VcManager) - vp = await manager.prove(presentation, options) - except VcManagerError as err: - raise web.HTTPBadRequest(reason=str(err)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return vp - - -async def verify_presentation(request): - """Verify presentation. - - Process the web request and pass it to the VcLdpManage. - - Args: - request (web.BaseRequest): aiohttp web request object. - - Returns: - PresentationVerificationResultSchema: Results of the verification. - - """ - context: AdminRequestContext = request["context"] - body = await request.json() - vp = body.get("verifiablePresentation") - options = {} if "options" not in body else body["options"] - try: - vp = VerifiablePresentation.deserialize(vp) - options = LDProofVCOptions.deserialize(options) - manager = context.inject(VcManager) - result = await manager.verify_presentation(vp, options) - except (VcManagerError, ResolverError, ValueError) as err: - raise web.HTTPBadRequest(reason=str(err)) - except (WalletError, InjectionError): - raise web.HTTPForbidden(reason="No wallet available") - return result From 6357cd0657475656acc3f0d573685ec8be76dd31 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Wed, 24 Jan 2024 15:23:46 -0500 Subject: [PATCH 24/26] added vc-api routes abstract in readme, section in JsonLdCredentials.md and a postman collection in the demo folder Signed-off-by: pstlouis --- JsonLdCredentials.md | 17 ++ README.md | 4 + demo/AriesPostmanDemo.md | 81 ++++++ demo/postman/collections/vc-api.json | 402 +++++++++++++++++++++++++++ demo/postman/environment.json | 15 + 5 files changed, 519 insertions(+) create mode 100644 demo/AriesPostmanDemo.md create mode 100644 demo/postman/collections/vc-api.json create mode 100644 demo/postman/environment.json diff --git a/JsonLdCredentials.md b/JsonLdCredentials.md index 314dabdcde..3e1bf7d368 100644 --- a/JsonLdCredentials.md +++ b/JsonLdCredentials.md @@ -16,6 +16,7 @@ By design Hyperledger Aries is credential format agnostic. This means you can us - [Issuing Credentials](#issuing-credentials) - [Retrieving Issued Credentials](#retrieving-issued-credentials) - [Present Proof](#present-proof) +- [VC-API Endpoints](#vc-api) ## General Concept @@ -210,3 +211,19 @@ Call the `/credentials/w3c` endpoint to retrieve all JSON-LD credentials in your ## Present Proof > ⚠️ TODO: https://github.com/hyperledger/aries-cloudagent-python/pull/1125 + + +## VC-API + +In order to support these functionalities outside of the respective DIDComm protocols, a set of endpoints conforming to the [vc-api](https://w3c-ccg.github.io/vc-api) specification are available. These endpoints should be used by a controller when building an identity platform. + +These endpoints include: +- `GET /vc/credentials` -> returns a list of all stored json-ld credentials +- `GET /vc/credentials/{id}` -> returns a json-ld credential based on it's ID +- `POST /vc/credentials/issue` -> signs a credential +- `POST /vc/credentials/verify` -> verifies a credential +- `POST /vc/credentials/store` -> stores an issued credential +- `POST /vc/presentations/prove` -> proves a presentation +- `POST /vc/presentations/verify` -> verifies a presentation + +To learn more about using these endpoints, please refer to the available [postman collection](./demo/AriesPostmanDemo.md#experimenting-with-the-vc-api-endpoints). \ No newline at end of file diff --git a/README.md b/README.md index aab7293411..74f29fd3fd 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,10 @@ ACA-Py supports a Transaction Endorsement protocol, for agents that don't have w ACA-Py supports deployments in scaled environments such as in Kubernetes environments where ACA-Py and its storage components can be horizontally scaled as needed to handle the load. +### VC-API Endpoints + +A set of endpoints conforming to the vc-api specification are included to manage w3c credentials and presentations. They are documented [here](JsonLdCredentials.md#vc-api) and a postman demo is available [here](./demo/AriesPostmanDemo.md#vc-api). + ## Example Uses The business logic you use with ACA-Py is limited only by your imagination. Possible applications include: diff --git a/demo/AriesPostmanDemo.md b/demo/AriesPostmanDemo.md new file mode 100644 index 0000000000..cca244c5bb --- /dev/null +++ b/demo/AriesPostmanDemo.md @@ -0,0 +1,81 @@ +# Aries Postman Demo + +In these demos we will use Postman as our controller client. + +# Contents + +- [Getting Started](#getting-started) + - [Installing Postman](#install-postman) + - [Creating a workspace](#create-workspace) + - [Importing the environment](#import-environment) + - [Importing the collections](#import-collections) + - [Postman basics](#postman-101) +- [Experimenting with the vc-api endpoints](#vc-api) + - [Register new dids](#register-dids) + - [Issue credentials](#issue-credentials) + - [Store and retrieve credentials](#store-credentials) + - [Verify credentials](#verify-credentials) + - [Prove a presentation](#prove-presentation) + - [Verify a presentation](#verify-presentation) + +## Getting Started +Welcome to the Postman demo. This is an addition to the available OpenAPI demo, providing a set of collections to test and demonstrate various aca-py funcitonalities. + +### Installing Postman +Download, install and launch [postman](https://www.postman.com/downloads/). + +### Creating a workspace +Create a new postman workspace labeled "acapy-demo". + +### Importing the enviroment +In the environment tab from the left, click the import button. You can paste this [link](https://raw.githubusercontent.com/hyperledger/aries-cloudagent-python/main/demo/postman/environment.json) or copy the json from the [environment file](./postman/environment.json). + +Make sure you have the environment set as your active environment. + +### Importing the collections +In the collections tab from the left, click the import button. + +The following collections are available: +- [vc-api](https://raw.githubusercontent.com/hyperledger/aries-cloudagent-python/main/demo/postman/collections/vc-api.json) + +### Postman basics +Once you are setup, you will be ready to run postman requests. The order of the request is important, since some values are saved dynamically as environment variables for subsequent calls. + +You have your envrionment where you define variables to be accessed by your collections. + +Each collection consists of a series of requests which can be configured independently. + +## Experimenting with the vc-api endpoints + +Make sure you have a demo agent available. You can use the following command to deploy one: +`LEDGER_URL=http://dev.greenlight.bcovrin.vonx.io ./run_demo faber --events --no-auto --bg` + +When running for the first time, please allow some time for the images to build. + +### Register new dids +The first 2 requests for this collection will create 2 did:keys. We will use those in subsequent calls to issue `Ed25519Signature2020` and `BbsBlsSignature2020` credentials. +Run the 2 did creation requests. These requests will use the `/wallet/did/create` endpoint. + +### Issue credentials +For issuing, you must input a credential and some options in your request body. Some examples have been pre-configured in the collection. Each credential will get a random uuid generated. Notice the options field in both requests. The signature suite indicated in the options must match the provided issuer did stored in the agent's wallet. + +Run the requests and inspect the result. Feel free to experiment with different credentials, however make sure to leave the issuer field as the indicated variable. + +### Store and retrieve credentials +Your last issued credential will be stored as an environment variable for subsequent calls, such as storing, verifying and including in a presentation. + +Try running the store credential request, then retrieve the credential with the list and fetch requests. Try going back and forth between the issuance endpoints and the storage endpoints to store multiple different credentials. + +### Verify credentials +You can verify your last issued credential with this endpoint, or any issued credential you provide to it. + +### Prove a presentation +Proving a presentation is an action where a holder will prove ownership of a credential by signing or demonstrating authority over a presentation. +This request will generate a random challenge for the presentation. + +### Verify a presentation +The final request is to verify a presentation. + + + + diff --git a/demo/postman/collections/vc-api.json b/demo/postman/collections/vc-api.json new file mode 100644 index 0000000000..f3a49dc228 --- /dev/null +++ b/demo/postman/collections/vc-api.json @@ -0,0 +1,402 @@ +{ + "info": { + "_postman_id": "f6a6fe37-a18c-47ef-a235-424d30ab043d", + "name": "vc-api", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "31640062" + }, + "item": [ + { + "name": "Create DID Ed25519Signature2020", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const { result } = pm.response.json();\r", + "pm.globals.set(\"did_ed\", result.did);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"method\": \"key\",\r\n \"options\": {\r\n \"key_type\": \"ed25519\"\r\n }\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/wallet/did/create", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "wallet", + "did", + "create" + ] + } + }, + "response": [] + }, + { + "name": "Create DID BbsBlsSignature2020", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const { result } = pm.response.json();\r", + "pm.globals.set(\"did_bls\", result.did);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"method\": \"key\",\r\n \"options\": {\r\n \"key_type\": \"bls12381g2\"\r\n }\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/wallet/did/create", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "wallet", + "did", + "create" + ] + } + }, + "response": [] + }, + { + "name": "Issue VC Ed25519Signature2020", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const {verifiableCredential} = pm.response.json();\r", + "pm.collectionVariables.set(\"verifiableCredential\", JSON.stringify(verifiableCredential));\r", + "pm.collectionVariables.set(\"credential_id\", verifiableCredential.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"credential\": {\r\n \"@context\": [\r\n \"https://www.w3.org/2018/credentials/v1\"\r\n ],\r\n \"credentialSubject\": {\r\n \"id\": \"did:example:ebfeb1f712ebc6f1c276e12ec21\"\r\n },\r\n \"id\": \"urn:uuid:{{$randomUUID}}\",\r\n \"issuanceDate\": \"2010-01-01T19:23:24Z\",\r\n \"issuer\": \"{{did_ed}}\",\r\n \"type\": [\r\n \"VerifiableCredential\"\r\n ]\r\n },\r\n \"options\": {\r\n \"type\": \"Ed25519Signature2020\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/issue", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "issue" + ] + } + }, + "response": [] + }, + { + "name": "Issue VC BbsBlsSignature2020", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const {verifiableCredential} = pm.response.json();\r", + "pm.collectionVariables.set(\"verifiableCredential\", JSON.stringify(verifiableCredential));\r", + "pm.collectionVariables.set(\"credential_id\", verifiableCredential.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"credential\": {\r\n \"@context\": [\r\n \"https://www.w3.org/2018/credentials/v1\"\r\n ],\r\n \"credentialSubject\": {\r\n \"id\": \"did:example:ebfeb1f712ebc6f1c276e12ec21\"\r\n },\r\n \"id\": \"urn:uuid:{{$randomUUID}}\",\r\n \"issuanceDate\": \"2010-01-01T19:23:24Z\",\r\n \"issuer\": \"{{did_bls}}\",\r\n \"type\": [\r\n \"VerifiableCredential\"\r\n ]\r\n },\r\n \"options\": {\r\n \"type\": \"BbsBlsSignature2020\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/issue", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "issue" + ] + } + }, + "response": [] + }, + { + "name": "Verify Credential", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"options\": {},\r\n \"verifiableCredential\": {{verifiableCredential}}\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/verify", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "verify" + ] + } + }, + "response": [] + }, + { + "name": "Store Credential", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"options\": {},\r\n \"verifiableCredential\": {{verifiableCredential}}\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/store", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "store" + ] + } + }, + "response": [] + }, + { + "name": "List Credentials", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials" + ] + } + }, + "response": [] + }, + { + "name": "Fetch Credential", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/{{credential_id}}", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "{{credential_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Prove presentation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const {verifiablePresentation} = pm.response.json();\r", + "pm.collectionVariables.set(\"verifiablePresentation\", JSON.stringify(verifiablePresentation));\r", + "pm.collectionVariables.set(\"challenge\", verifiablePresentation.proof.challenge);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"presentation\": {\r\n \"@context\": [\r\n \"https://www.w3.org/2018/credentials/v1\"\r\n ],\r\n \"type\": [\r\n \"VerifiablePresentation\"\r\n ],\r\n \"holder\": \"{{did_ed}}\",\r\n \"verifiableCredential\": [{{verifiableCredential}}]\r\n },\r\n \"options\": {\r\n \"type\": \"Ed25519Signature2018\",\r\n \"challenge\": \"{{$randomUUID}}\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/presentations/prove", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "presentations", + "prove" + ] + } + }, + "response": [] + }, + { + "name": "Verify Presentation", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"options\": {\r\n \"challenge\": \"{{challenge}}\"\r\n },\r\n \"verifiablePresentation\": {{verifiablePresentation}}\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/presentations/verify", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "presentations", + "verify" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "verifiableCredential", + "value": "" + }, + { + "key": "credential_id", + "value": "" + }, + { + "key": "verifiablePresentation", + "value": "" + }, + { + "key": "challenge", + "value": "" + } + ] +} \ No newline at end of file diff --git a/demo/postman/environment.json b/demo/postman/environment.json new file mode 100644 index 0000000000..3cf464c40e --- /dev/null +++ b/demo/postman/environment.json @@ -0,0 +1,15 @@ +{ + "id": "af2c8f79-d6b5-4009-b9b9-20781d0849ff", + "name": "aca-py", + "values": [ + { + "key": "ADMIN_ENDPOINT", + "value": "http://localhost:8021", + "type": "default", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2024-01-24T20:22:38.205Z", + "_postman_exported_using": "Postman/10.22.1" +} \ No newline at end of file From 5fe7c4169a0b68277fd73648005b9bf9c9e42afd Mon Sep 17 00:00:00 2001 From: pstlouis Date: Thu, 25 Jan 2024 21:47:54 +0000 Subject: [PATCH 25/26] added storage tests, suite derivation and record_id generation Signed-off-by: pstlouis --- JsonLdCredentials.md | 16 + README.md | 4 + aries_cloudagent/vc/routes.py | 89 +++-- aries_cloudagent/vc/vc_ld/manager.py | 22 ++ .../vc/vc_ld/models/linked_data_proof.py | 4 +- .../vc/vc_ld/models/web_schemas.py | 11 +- .../vc/vc_ld/tests/test_manager.py | 25 ++ demo/AriesPostmanDemo.md | 96 +++++ demo/postman/environment.json | 0 demo/postman/vc-api.collection.json | 373 ++++++++++++++++++ demo/run_demo | 4 +- 11 files changed, 610 insertions(+), 34 deletions(-) create mode 100644 demo/AriesPostmanDemo.md create mode 100644 demo/postman/environment.json create mode 100644 demo/postman/vc-api.collection.json diff --git a/JsonLdCredentials.md b/JsonLdCredentials.md index 314dabdcde..d0c56bbce6 100644 --- a/JsonLdCredentials.md +++ b/JsonLdCredentials.md @@ -16,6 +16,7 @@ By design Hyperledger Aries is credential format agnostic. This means you can us - [Issuing Credentials](#issuing-credentials) - [Retrieving Issued Credentials](#retrieving-issued-credentials) - [Present Proof](#present-proof) +- [VC-API Endpoints](#vc-api) ## General Concept @@ -210,3 +211,18 @@ Call the `/credentials/w3c` endpoint to retrieve all JSON-LD credentials in your ## Present Proof > ⚠️ TODO: https://github.com/hyperledger/aries-cloudagent-python/pull/1125 + +## VC-API + +In order to support these functionalities outside of the respective DIDComm protocols, a set of endpoints conforming to the [vc-api](https://w3c-ccg.github.io/vc-api) specification are available. These endpoints should be used by a controller when building an identity platform. + +These endpoints include: +- `GET /vc/credentials` -> returns a list of all stored json-ld credentials +- `GET /vc/credentials/{id}` -> returns a json-ld credential based on it's ID +- `POST /vc/credentials/issue` -> signs a credential +- `POST /vc/credentials/verify` -> verifies a credential +- `POST /vc/credentials/store` -> stores an issued credential +- `POST /vc/presentations/prove` -> proves a presentation +- `POST /vc/presentations/verify` -> verifies a presentation + +To learn more about using these endpoints, please refer to the available postman collection. \ No newline at end of file diff --git a/README.md b/README.md index aab7293411..74f29fd3fd 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,10 @@ ACA-Py supports a Transaction Endorsement protocol, for agents that don't have w ACA-Py supports deployments in scaled environments such as in Kubernetes environments where ACA-Py and its storage components can be horizontally scaled as needed to handle the load. +### VC-API Endpoints + +A set of endpoints conforming to the vc-api specification are included to manage w3c credentials and presentations. They are documented [here](JsonLdCredentials.md#vc-api) and a postman demo is available [here](./demo/AriesPostmanDemo.md#vc-api). + ## Example Uses The business logic you use with ACA-Py is limited only by your imagination. Possible applications include: diff --git a/aries_cloudagent/vc/routes.py b/aries_cloudagent/vc/routes.py index b0b227787f..0676fe9f92 100644 --- a/aries_cloudagent/vc/routes.py +++ b/aries_cloudagent/vc/routes.py @@ -3,9 +3,11 @@ from aiohttp import web from aiohttp_apispec import docs, request_schema, response_schema from marshmallow.exceptions import ValidationError +import uuid from ..admin.request_context import AdminRequestContext -from ..storage.error import StorageError, StorageNotFoundError +from ..storage.error import StorageError, StorageNotFoundError, StorageDuplicateError from ..wallet.error import WalletError +from ..wallet.base import BaseWallet from ..config.base import InjectionError from ..resolver.base import ResolverError from ..storage.vc_holder.base import VCHolder @@ -55,13 +57,8 @@ async def fetch_credential_route(request: web.BaseRequest): holder = context.inject(VCHolder) try: credential_id = request.match_info["credential_id"].strip('"') - search = holder.search_credentials(given_id=credential_id) - record = [record.serialize()["cred_value"] for record in await search.fetch()] - if len(record) < 1: - return web.json_response({"message": "No credential found"}, status=404) - if len(record) > 1: - return web.json_response(record, status=200) - return web.json_response(record[0], status=200) + record = await holder.retrieve_credential_by_id(record_id=credential_id) + return web.json_response(record.serialize()["cred_value"], status=200) except (StorageError, StorageNotFoundError) as err: return web.json_response({"message": err.roll_up}, status=400) @@ -80,15 +77,30 @@ async def issue_credential_route(request: web.BaseRequest): context: AdminRequestContext = request["context"] manager = context.inject(VcLdpManager) try: - credential = VerifiableCredential.deserialize(body["credential"]) + credential = body["credential"] options = {} if "options" not in body else body["options"] - # Our request uses the "type" key to represent the proof type (suite) to use - # We must pass this value as "proofType" to the LDProofVCOptions instance - # Default to Ed25519Signature2020 if no proof type is provided - options["proofType"] = ( - options.pop("type") if "type" in options else "Ed25519Signature2020" - ) + + # We derive the proofType from the issuer DID if not provided in options + if not options.get("type", None) and not options.get("proofType", None): + issuer = credential["issuer"] + did = issuer if isinstance(issuer, str) else issuer["id"] + async with context.session() as session: + wallet: BaseWallet | None = session.inject_or(BaseWallet) + info = await wallet.get_local_did(did) + key_type = info.key_type.key_type + + if key_type == "ed25519": + options["proofType"] = "Ed25519Signature2020" + elif key_type == "bls12381g2": + options["proofType"] = "BbsBlsSignature2020" + else: + options["proofType"] = ( + options.pop("type") if "type" in options else options["proofType"] + ) + + credential = VerifiableCredential.deserialize(credential) options = LDProofVCOptions.deserialize(options) + vc = await manager.issue(credential, options) response = {"verifiableCredential": vc.serialize()} return web.json_response(response, status=201) @@ -138,13 +150,25 @@ async def store_credential_route(request: web.BaseRequest): manager = context.inject(VcLdpManager) try: - vc = VerifiableCredential.deserialize(body["verifiableCredential"]) + vc = body["verifiableCredential"] + cred_id = vc["id"] if "id" in vc else f"urn:uuid:{str(uuid.uuid4())}" options = {} if "options" not in body else body["options"] + + vc = VerifiableCredential.deserialize(vc) options = LDProofVCOptions.deserialize(options) + await manager.verify_credential(vc) - await manager.store_credential(vc, options) - return web.json_response({"message": "Credential stored"}, status=200) - except (ValidationError, VcLdpManagerError, WalletError, InjectionError) as err: + await manager.store_credential(vc, options, cred_id) + + return web.json_response({"credentialId": cred_id}, status=200) + + except ( + ValidationError, + VcLdpManagerError, + WalletError, + InjectionError, + StorageDuplicateError, + ) as err: return web.json_response({"message": str(err)}, status=400) @@ -162,17 +186,30 @@ async def prove_presentation_route(request: web.BaseRequest): manager = context.inject(VcLdpManager) body = await request.json() try: - presentation = VerifiablePresentation.deserialize(body["presentation"]) + presentation = body["presentation"] options = {} if "options" not in body else body["options"] - # Our request uses the "type" key to represent the proof type (suite) to use - # We must pass this value as "proofType" to the LDProofVCOptions instance - # Default to Ed25519Signature2020 if no proof type is provided - options["proofType"] = ( - options.pop("type") if "type" in options else "Ed25519Signature2020" - ) + + # We derive the proofType from the holder DID if not provided in options + if not options.get("type", None): + holder = presentation["holder"] + did = holder if isinstance(holder, str) else holder["id"] + async with context.session() as session: + wallet: BaseWallet | None = session.inject_or(BaseWallet) + info = await wallet.get_local_did(did) + key_type = info.key_type.key_type + + if key_type == "ed25519": + options["proofType"] = "Ed25519Signature2020" + elif key_type == "bls12381g2": + options["proofType"] = "BbsBlsSignature2020" + else: + options["proofType"] = options.pop("type") + + presentation = VerifiablePresentation.deserialize(presentation) options = LDProofVCOptions.deserialize(options) vp = await manager.prove(presentation, options) return web.json_response({"verifiablePresentation": vp.serialize()}, status=201) + except (ValidationError, VcLdpManagerError, WalletError, InjectionError) as err: return web.json_response({"message": str(err)}, status=400) diff --git a/aries_cloudagent/vc/vc_ld/manager.py b/aries_cloudagent/vc/vc_ld/manager.py index 0a50e1281a..0881e83323 100644 --- a/aries_cloudagent/vc/vc_ld/manager.py +++ b/aries_cloudagent/vc/vc_ld/manager.py @@ -277,6 +277,27 @@ async def prepare_credential( return credential + async def prepare_presentation( + self, + presentation: VerifiablePresentation, + options: LDProofVCOptions, + ) -> VerifiableCredential: + """Prepare a presentation for issuance.""" + # Add BBS context if not present yet + if ( + options.proof_type == BbsBlsSignature2020.signature_type + and SECURITY_CONTEXT_BBS_URL not in presentation.context_urls + ): + presentation.add_context(SECURITY_CONTEXT_BBS_URL) + # Add ED25519-2020 context if not present yet + elif ( + options.proof_type == Ed25519Signature2020.signature_type + and SECURITY_CONTEXT_ED25519_2020_URL not in presentation.context_urls + ): + presentation.add_context(SECURITY_CONTEXT_ED25519_2020_URL) + + return presentation + async def _get_suite_for_document( self, document: Union[VerifiableCredential, VerifiablePresentation], @@ -416,6 +437,7 @@ async def prove( self, presentation: VerifiablePresentation, options: LDProofVCOptions ) -> VerifiablePresentation: """Sign a VP with a Linked Data Proof.""" + presentation = await self.prepare_presentation(presentation, options) # Get signature suite, proof purpose and document loader suite = await self._get_suite_for_document(presentation, options) diff --git a/aries_cloudagent/vc/vc_ld/models/linked_data_proof.py b/aries_cloudagent/vc/vc_ld/models/linked_data_proof.py index 81091b7977..40e5a2b7db 100644 --- a/aries_cloudagent/vc/vc_ld/models/linked_data_proof.py +++ b/aries_cloudagent/vc/vc_ld/models/linked_data_proof.py @@ -105,12 +105,14 @@ class Meta: domain = fields.Str( required=False, + # TODO the domain can be more than a Uri, provide a less restrictive validation + # https://www.w3.org/TR/vc-data-integrity/#defn-domain validate=Uri(), metadata={ "description": ( "A string value specifying the restricted domain of the signature." ), - "example": "example.com", + "example": "https://example.com", }, ) diff --git a/aries_cloudagent/vc/vc_ld/models/web_schemas.py b/aries_cloudagent/vc/vc_ld/models/web_schemas.py index 38ed843717..3349ad2c4e 100644 --- a/aries_cloudagent/vc/vc_ld/models/web_schemas.py +++ b/aries_cloudagent/vc/vc_ld/models/web_schemas.py @@ -28,11 +28,12 @@ class IssuanceOptionsSchema(Schema): created = fields.Str(required=False, metadata={"example": RFC3339_DATETIME_EXAMPLE}) domain = fields.Str(required=False, metadata={"example": "website.example"}) challenge = fields.Str(required=False, metadata={"example": UUID4_EXAMPLE}) - credential_status = fields.Dict( - data_key="credentialStatus", - required=False, - metadata={"example": {"type": "StatusList2021"}}, - ) + # TODO, implement status list publication through a plugin + # credential_status = fields.Dict( + # data_key="credentialStatus", + # required=False, + # metadata={"example": {"type": "StatusList2021"}}, + # ) class ListCredentialsResponse(OpenAPISchema): diff --git a/aries_cloudagent/vc/vc_ld/tests/test_manager.py b/aries_cloudagent/vc/vc_ld/tests/test_manager.py index f1f67ce980..4ac479445d 100644 --- a/aries_cloudagent/vc/vc_ld/tests/test_manager.py +++ b/aries_cloudagent/vc/vc_ld/tests/test_manager.py @@ -9,6 +9,7 @@ from ....resolver.default.key import KeyDIDResolver from ....resolver.did_resolver import DIDResolver from ....wallet.base import BaseWallet +from ....storage.vc_holder.base import VCHolder from ....wallet.default_verification_key_strategy import ( BaseVerificationKeyStrategy, DefaultVerificationKeyStrategy, @@ -37,6 +38,7 @@ TEST_DID_SOV = "did:sov:LjgpST2rjsoxYegQDRm7EL" TEST_DID_KEY = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" +TEST_UUID = "urn:uuid:dc86e95c-dc85-4f91-b563-82657d095c44" VC = { "credential": { "@context": [ @@ -366,3 +368,26 @@ async def test_get_all_suites(manager: VcLdpManager): ) for suite in suites: assert isinstance(suite, types) + + +@pytest.mark.asyncio +async def test_store( + profile: Profile, + manager: VcLdpManager, + vc: VerifiableCredential, + options: LDProofVCOptions, +): + async with profile.session() as session: + wallet = session.inject(BaseWallet) + did = await wallet.create_local_did( + method=KEY, + key_type=ED25519, + ) + vc.issuer = did.did + options.proof_type = Ed25519Signature2018.signature_type + cred = await manager.issue(vc, options) + await manager.store_credential(cred, options, TEST_UUID) + async with profile.session() as session: + holder = session.inject(VCHolder) + record = await holder.retrieve_credential_by_id(record_id=TEST_UUID) + assert record diff --git a/demo/AriesPostmanDemo.md b/demo/AriesPostmanDemo.md new file mode 100644 index 0000000000..46d296e9f8 --- /dev/null +++ b/demo/AriesPostmanDemo.md @@ -0,0 +1,96 @@ +# Aries Postman Demo + +In these demos we will use Postman as our controller client. + +# Contents + +- [Getting Started](#getting-started) + - [Installing Postman](#install-postman) + - [Creating a workspace](#create-workspace) + - [Importing the environment](#import-environment) + - [Importing the collections](#import-collections) + - [Postman basics](#postman-basics) +- [Experimenting with the vc-api endpoints](#vc-api) + - [Register new dids](#register-dids) + - [Issue credentials](#issue-credentials) + - [Store and retrieve credentials](#store-credentials) + - [Verify credentials](#verify-credentials) + - [Prove a presentation](#prove-presentation) + - [Verify a presentation](#verify-presentation) + +## Getting Started +Welcome to the Postman demo. This is an addition to the available OpenAPI demo, providing a set of collections to test and demonstrate various aca-py funcitonalities. + +### Installing Postman +Download, install and launch [postman](https://www.postman.com/downloads/). + +### Creating a workspace +Create a new postman workspace labeled "acapy-demo". + +### Importing the enviroment +In the environment tab from the left, click the import button. You can paste this [link](https://raw.githubusercontent.com/hyperledger/aries-cloudagent-python/main/demo/postman/environment.json) or copy the json from the [environment file](./postman/environment.json). + +Make sure you have the environment set as your active environment. + +### Importing the collections +In the collections tab from the left, click the import button. + +The following collections are available: +- [vc-api](https://raw.githubusercontent.com/hyperledger/aries-cloudagent-python/main/demo/postman/collections/vc-api.json) + +### Postman basics +Once you are setup, you will be ready to run postman requests. The order of the request is important, since some values are saved dynamically as environment variables for subsequent calls. + +You have your envrionment where you define variables to be accessed by your collections. + +Each collection consists of a series of requests which can be configured independently. + +## Experimenting with the vc-api endpoints + +Make sure you have a demo agent available. You can use the following command to deploy one: +```bash +LEDGER_URL=http://dev.greenlight.bcovrin.vonx.io ./run_demo faber --bg +``` + +When running for the first time, please allow some time for the images to build. + +### Register new dids +The first 2 requests for this collection will create 2 did:keys. We will use those in subsequent calls to issue `Ed25519Signature2020` and `BbsBlsSignature2020` credentials. +Run the 2 did creation requests. These requests will use the `/wallet/did/create` endpoint. + +### Issue credentials +For issuing, you must input a [w3c compliant json-ld credential](https://www.w3.org/TR/vc-data-model/) and [issuance options](https://w3c-ccg.github.io/vc-api/#issue-credential) in your request body. The issuer field must be a registered did from the agent's wallet. The suite will be derived from the did method. +```json +{ + "credential": { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": [ + "VerifiableCredential" + ], + "issuer": "did:example:123", + "issuanceDate": "2022-05-01T00:00:00Z", + "credentialSubject": { + "id": "did:example:123" + } + }, + "options": {} +} +``` + +Some examples have been pre-configured in the collection. Run the requests and inspect the results. Experiment with different credentials. + +### Store and retrieve credentials +Your last issued credential will be stored as an environment variable for subsequent calls, such as storing, verifying and including in a presentation. + +Try running the store credential request, then retrieve the credential with the list and fetch requests. Try going back and forth between the issuance endpoints and the storage endpoints to store multiple different credentials. + +### Verify credentials +You can verify your last issued credential with this endpoint or any issued credential you provide to it. + +### Prove a presentation +Proving a presentation is an action where a holder will prove ownership of a credential by signing or demonstrating authority over the document. + +### Verify a presentation +The final request is to verify a presentation. diff --git a/demo/postman/environment.json b/demo/postman/environment.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demo/postman/vc-api.collection.json b/demo/postman/vc-api.collection.json new file mode 100644 index 0000000000..060454052e --- /dev/null +++ b/demo/postman/vc-api.collection.json @@ -0,0 +1,373 @@ +{ + "info": { + "_postman_id": "f6a6fe37-a18c-47ef-a235-424d30ab043d", + "name": "vc-api", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "31640062" + }, + "item": [ + { + "name": "Create DID Ed25519Signature2020", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const { result } = pm.response.json();\r", + "pm.globals.set(\"did\", result.did);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"method\": \"key\",\r\n \"options\": {\r\n \"key_type\": \"ed25519\"\r\n }\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/wallet/did/create", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "wallet", + "did", + "create" + ] + } + }, + "response": [] + }, + { + "name": "Create DID BbsBlsSignature2020", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const { result } = pm.response.json();\r", + "pm.globals.set(\"did\", result.did);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"method\": \"key\",\r\n \"options\": {\r\n \"key_type\": \"bls12381g2\"\r\n }\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/wallet/did/create", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "wallet", + "did", + "create" + ] + } + }, + "response": [] + }, + { + "name": "Issue Credential", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const {verifiableCredential} = pm.response.json();\r", + "pm.collectionVariables.set(\"verifiableCredential\", JSON.stringify(verifiableCredential));" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"credential\": {\r\n \"@context\": [\r\n \"https://www.w3.org/2018/credentials/v1\"\r\n ],\r\n \"credentialSubject\": {\r\n \"id\": \"did:example:ebfeb1f712ebc6f1c276e12ec21\"\r\n },\r\n \"id\": \"urn:uuid:{{$randomUUID}}\",\r\n \"issuanceDate\": \"2010-01-01T19:23:24Z\",\r\n \"issuer\": \"{{did}}\",\r\n \"type\": [\r\n \"VerifiableCredential\"\r\n ]\r\n },\r\n \"options\": {}\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/issue", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "issue" + ] + } + }, + "response": [] + }, + { + "name": "Verify Credential", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"options\": {},\r\n \"verifiableCredential\": {{verifiableCredential}}\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/verify", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "verify" + ] + } + }, + "response": [] + }, + { + "name": "Store Credential", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const {credentialId} = pm.response.json();\r", + "pm.collectionVariables.set(\"credentialId\", credentialId);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"options\": {},\r\n \"verifiableCredential\": {{verifiableCredential}}\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/store", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "store" + ] + } + }, + "response": [] + }, + { + "name": "List Credentials", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials" + ] + } + }, + "response": [] + }, + { + "name": "Fetch Credential", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/credentials/{{credentialId}}", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "credentials", + "{{credentialId}}" + ] + } + }, + "response": [] + }, + { + "name": "Prove presentation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const {verifiablePresentation} = pm.response.json();\r", + "pm.collectionVariables.set(\"verifiablePresentation\", JSON.stringify(verifiablePresentation));\r", + "pm.collectionVariables.set(\"challenge\", verifiablePresentation.proof.challenge);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"presentation\": {\r\n \"@context\": [\r\n \"https://www.w3.org/2018/credentials/v1\"\r\n ],\r\n \"type\": [\r\n \"VerifiablePresentation\"\r\n ],\r\n \"holder\": \"{{did}}\",\r\n \"verifiableCredential\": [{{verifiableCredential}}]\r\n },\r\n \"options\": {\r\n \"domain\": \"https://example.com\",\r\n \"challenge\": \"{{$randomUUID}}\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/presentations/prove", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "presentations", + "prove" + ] + } + }, + "response": [] + }, + { + "name": "Verify Presentation", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"options\": {\r\n \"domain\": \"example.com\",\r\n \"challenge\": \"{{challenge}}\"\r\n },\r\n \"verifiablePresentation\": {{verifiablePresentation}}\r\n}\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ADMIN_ENDPOINT}}/vc/presentations/verify", + "host": [ + "{{ADMIN_ENDPOINT}}" + ], + "path": [ + "vc", + "presentations", + "verify" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "verifiableCredential", + "value": "" + }, + { + "key": "credential_id", + "value": "" + }, + { + "key": "verifiablePresentation", + "value": "" + }, + { + "key": "challenge", + "value": "" + }, + { + "key": "credentialId", + "value": "" + } + ] +} \ No newline at end of file diff --git a/demo/run_demo b/demo/run_demo index b451cb72fe..45fc7d813d 100755 --- a/demo/run_demo +++ b/demo/run_demo @@ -156,8 +156,8 @@ if [ ! -z "$AGENT_PORT_OVERRIDE" ]; then fi echo "Preparing agent image..." -docker build -q -t acapy-base -f ../docker/Dockerfile .. || exit 1 -docker build -q -t faber-alice-demo -f ../docker/Dockerfile.demo --build-arg from_image=acapy-base .. || exit 1 +docker build -t acapy-base -f ../docker/Dockerfile .. || exit 1 +docker build -t faber-alice-demo -f ../docker/Dockerfile.demo --build-arg from_image=acapy-base .. || exit 1 if [ ! -z "$DOCKERHOST" ]; then # provided via APPLICATION_URL environment variable From f8d398d29e6c69a479a5f6796ab6a7eb96ab5ad9 Mon Sep 17 00:00:00 2001 From: pstlouis Date: Thu, 25 Jan 2024 22:01:37 +0000 Subject: [PATCH 26/26] merge artifacts in readme Signed-off-by: pstlouis --- JsonLdCredentials.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/JsonLdCredentials.md b/JsonLdCredentials.md index 9ef5a10768..728608ee5f 100644 --- a/JsonLdCredentials.md +++ b/JsonLdCredentials.md @@ -212,10 +212,6 @@ Call the `/credentials/w3c` endpoint to retrieve all JSON-LD credentials in your > ⚠️ TODO: https://github.com/hyperledger/aries-cloudagent-python/pull/1125 -<<<<<<< HEAD -======= - ->>>>>>> e09dc55461195736f0fb68978f09b9f0c09cc07b ## VC-API In order to support these functionalities outside of the respective DIDComm protocols, a set of endpoints conforming to the [vc-api](https://w3c-ccg.github.io/vc-api) specification are available. These endpoints should be used by a controller when building an identity platform. @@ -229,8 +225,4 @@ These endpoints include: - `POST /vc/presentations/prove` -> proves a presentation - `POST /vc/presentations/verify` -> verifies a presentation -<<<<<<< HEAD -To learn more about using these endpoints, please refer to the available postman collection. -======= To learn more about using these endpoints, please refer to the available [postman collection](./demo/AriesPostmanDemo.md#experimenting-with-the-vc-api-endpoints). ->>>>>>> e09dc55461195736f0fb68978f09b9f0c09cc07b