From 8cfa83f921604b819ce69b6a966ef088fd270720 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 6 Nov 2024 10:08:37 +0100 Subject: [PATCH 1/8] add snapshot schema and credential template --- idhub/templates/credentials/snapshot.json | 50 +++++++++++ schemas/snapshot.json | 103 ++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 idhub/templates/credentials/snapshot.json create mode 100644 schemas/snapshot.json diff --git a/idhub/templates/credentials/snapshot.json b/idhub/templates/credentials/snapshot.json new file mode 100644 index 0000000..7d9ded3 --- /dev/null +++ b/idhub/templates/credentials/snapshot.json @@ -0,0 +1,50 @@ +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://idhub.pangea.org/context/base.jsonld", + "https://idhub.pangea.org/context/snapshot.jsonld" + ], + "id": "{{ vc_id }}", + "type": [ + "VerifiableCredential", + "VerifiableAttestation", + "Snapshot" + ], + "issuer": { + "id": "{{ issuer_did }}", + "name": "{{ organisation }}" + }, + "issuanceDate": "{{ issuance_date }}", + "validFrom": "{{ issuance_date }}", + "validUntil": "{{ validUntil }}", + "name": [ + { + "value": "Snapshot of Workbench script", + "lang": "en" + } + ], + "description": [ + { + "value": "Snapshot of Workbench script software for discover hardware", + "lang": "en" + } + ], + "credentialSubject": { + "id": "{{ token_hash }}", + "uuid": "{{ uuid }}", + "type": "{{ type }}", + "software": "{{ software }}", + "timestamp": "{{ timestamp }}", + "data": "{{ data }}", + "erase": "{{ erase }}" + }, + "credentialStatus": { + "id": "{{ credential_status_id}}", + "type": "RevocationBitmap2022", + "revocationBitmapIndex": "{{ id_credential }}" + }, + "credentialSchema": { + "id": "https://idhub.pangea.org/vc_schemas/snapshot.json", + "type": "FullJsonSchemaValidator2021" + } +} diff --git a/schemas/snapshot.json b/schemas/snapshot.json new file mode 100644 index 0000000..c6fa095 --- /dev/null +++ b/schemas/snapshot.json @@ -0,0 +1,103 @@ +{ + "$id": "https://idhub.pangea.org/vc_schemas/v1/snapshot.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Snapshot", + "description": "Snapshot create by workbench-script, software for discover hardware in one device.", + "name": [ + { + "value": "Snapshot", + "lang": "en" + }, + ], + "type": "object", + "allOf": [ + { + "$ref": "https://idhub.pangea.org/vc_schemas/ebsi/attestation.json" + }, + { + "properties": { + "credentialSubject": { + "description": "Defines additional properties on credentialSubject", + "type": "object", + "properties": { + "id": { + "description": "Defines a hash of token", + "type": "string", + "minLength": 36 + }, + "uuid": { + "description": "Defines a unique identifier of the snapshot", + "type": "string", + "minLength": 36 + }, + "type": { + "type": "string", + "enum": [ + "Snapshot" + ], + "minLength": 1 + }, + "software": { + "description": "Name of software used.", + "type": "string", + "enum": [ + "workbench-script" + ], + "minLength": 1 + }, + "timestamp": { + "description": "Time when is make this snapshot.", + "type": "string" + }, + "data": { + "description": "Device details discovery data.", + "type": "object", + "allOf": [ + { + "lshw": { + "description": "Result of execution of lshw program", + "type": "string", + "minlength": 0 + }, + "disks": { + "description": "Result of execution of smartctl program", + "type": "string", + "minlength": 0 + }, + "hwinfo": { + "description": "Result of execution of hwinfo program", + "type": "string", + "minlength": 0 + }, + "dmidecode": { + "description": "Result of execution of dmidecode program", + "type": "string", + "minlength": 0 + }, + "lspci": { + "description": "Result of execution of lspci program", + "type": "string", + "minlength": 0 + } + } + ] + }, + "erase": { + "description": "Datas of erase disk process", + "type": "string", + "minLength": 0 + } + }, + "required": [ + "id", + "uuid", + "type", + "software", + "timestamp", + "data" + ] + } + } + } + ] +} From 717b4ab6d50de29dfbbf483d9dfcf365542ac8a2 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 6 Nov 2024 10:50:09 +0100 Subject: [PATCH 2/8] change data --- schemas/snapshot.json | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/schemas/snapshot.json b/schemas/snapshot.json index c6fa095..7fea9c8 100644 --- a/schemas/snapshot.json +++ b/schemas/snapshot.json @@ -21,7 +21,7 @@ "type": "object", "properties": { "id": { - "description": "Defines a hash of token", + "description": "Defines a hash of token sign_token", "type": "string", "minLength": 36 }, @@ -51,36 +51,7 @@ }, "data": { "description": "Device details discovery data.", - "type": "object", - "allOf": [ - { - "lshw": { - "description": "Result of execution of lshw program", - "type": "string", - "minlength": 0 - }, - "disks": { - "description": "Result of execution of smartctl program", - "type": "string", - "minlength": 0 - }, - "hwinfo": { - "description": "Result of execution of hwinfo program", - "type": "string", - "minlength": 0 - }, - "dmidecode": { - "description": "Result of execution of dmidecode program", - "type": "string", - "minlength": 0 - }, - "lspci": { - "description": "Result of execution of lspci program", - "type": "string", - "minlength": 0 - } - } - ] + "type": "string", }, "erase": { "description": "Datas of erase disk process", From baf5c1e924c8a19cb8eec7d35dae268f51a8d13c Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Sat, 9 Nov 2024 19:00:39 +0100 Subject: [PATCH 3/8] fix schema workbench and credential --- idhub/templates/credentials/snapshot.json | 10 ++++------ schemas/{snapshot.json => workbench.json} | 14 +++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) rename schemas/{snapshot.json => workbench.json} (79%) diff --git a/idhub/templates/credentials/snapshot.json b/idhub/templates/credentials/snapshot.json index 7d9ded3..2781a23 100644 --- a/idhub/templates/credentials/snapshot.json +++ b/idhub/templates/credentials/snapshot.json @@ -4,11 +4,10 @@ "https://idhub.pangea.org/context/base.jsonld", "https://idhub.pangea.org/context/snapshot.jsonld" ], - "id": "{{ vc_id }}", + "id": "urn:uuid:{{ vc_id }}", "type": [ "VerifiableCredential", - "VerifiableAttestation", - "Snapshot" + "DeviceSnapshot" ], "issuer": { "id": "{{ issuer_did }}", @@ -16,7 +15,6 @@ }, "issuanceDate": "{{ issuance_date }}", "validFrom": "{{ issuance_date }}", - "validUntil": "{{ validUntil }}", "name": [ { "value": "Snapshot of Workbench script", @@ -36,7 +34,7 @@ "software": "{{ software }}", "timestamp": "{{ timestamp }}", "data": "{{ data }}", - "erase": "{{ erase }}" + "dataDeletion": "{{ erase }}" }, "credentialStatus": { "id": "{{ credential_status_id}}", @@ -44,7 +42,7 @@ "revocationBitmapIndex": "{{ id_credential }}" }, "credentialSchema": { - "id": "https://idhub.pangea.org/vc_schemas/snapshot.json", + "id": "https://idhub.pangea.org/vc_schemas/v1/workbench.json", "type": "FullJsonSchemaValidator2021" } } diff --git a/schemas/snapshot.json b/schemas/workbench.json similarity index 79% rename from schemas/snapshot.json rename to schemas/workbench.json index 7fea9c8..128e1c5 100644 --- a/schemas/snapshot.json +++ b/schemas/workbench.json @@ -1,7 +1,7 @@ { - "$id": "https://idhub.pangea.org/vc_schemas/v1/snapshot.json", + "$id": "https://idhub.pangea.org/vc_schemas/v1/workbench.json", "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "Snapshot", + "title": "DeviceSnapshot", "description": "Snapshot create by workbench-script, software for discover hardware in one device.", "name": [ { @@ -12,16 +12,16 @@ "type": "object", "allOf": [ { - "$ref": "https://idhub.pangea.org/vc_schemas/ebsi/attestation.json" + "$ref": "https://www.w3.org/2018/credentials/v1" }, { "properties": { "credentialSubject": { - "description": "Defines additional properties on credentialSubject", + "description": "Define the properties of a digital device snapshot", "type": "object", "properties": { "id": { - "description": "Defines a hash of token sign_token", + "description": "Defines a hash of id token", "type": "string", "minLength": 36 }, @@ -47,13 +47,13 @@ }, "timestamp": { "description": "Time when is make this snapshot.", - "type": "string" + "type": "date-time" }, "data": { "description": "Device details discovery data.", "type": "string", }, - "erase": { + "dataDeletion": { "description": "Datas of erase disk process", "type": "string", "minLength": 0 From 9ebd3b18a42fc6ef6d01ef793aab0b0243b0561b Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 21 Nov 2024 12:39:34 +0100 Subject: [PATCH 4/8] create credential snapshots --- .../credentials/device-snapshot.json | 67 ++++++++++ idhub/templates/credentials/snapshot.json | 48 ------- schemas/device-snapshot.json | 122 ++++++++++++++++++ schemas/workbench.json | 74 ----------- 4 files changed, 189 insertions(+), 122 deletions(-) create mode 100644 idhub/templates/credentials/device-snapshot.json delete mode 100644 idhub/templates/credentials/snapshot.json create mode 100644 schemas/device-snapshot.json delete mode 100644 schemas/workbench.json diff --git a/idhub/templates/credentials/device-snapshot.json b/idhub/templates/credentials/device-snapshot.json new file mode 100644 index 0000000..6038c95 --- /dev/null +++ b/idhub/templates/credentials/device-snapshot.json @@ -0,0 +1,67 @@ +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://idhub.pangea.org/vc_schemas/v1/device-snapshot.json" + ], + "type": ["VerifiableCredential", "DeviceSnapshot"], + "issuer": "{{ issuer_did }}", + "issuanceDate": "{{ issuance_date }}", + "credentialSubject": { + "operatorId": "{{ operatorid }}", + "uuid": "{{ uuid }}", + "type": "hardwareList", + "software": "workbench-script", + "deviceId": [ + { + "name": "Manufacturer", + "value": "{{ manufacturer }}" + }, + { + "name": "Model", + "value": "{{ model }}" + }, + { + "name": "Serial", + "value": "{{ serial_number }}" + }, + { + "name": "SKU", + "value": "{{ sku }}" + }, + { + "name": "EthernetMacAddress", + "value": "{{ mac }}" + } + ], + "timestamp": "{{ issuance_date }}" + }, + "evidence": [ + { + "type": "HardwareList", + "operation": "dmidecode", + "output": "{{ dmidecode }}", + "timestamp": "{{ issuance_date }}" + }, + { + "type": "HardwareList", + "operation": "{{ smartctl }}", + "output": "{{ smartctl }}", + "timestamp": "{{ issuance_date }}" + }, + { + "type": "HardwareList", + "operation": "{{ inxi }}", + "output": "{{ inxi }}", + "timestamp": "{{ issuance_date }}" + } + ], + "credentialStatus": { + "id": "{{ credential_status_id}}", + "type": "RevocationBitmap2022", + "revocationBitmapIndex": "{{ id_credential }}" + }, + "credentialSchema": { + "id": "https://idhub.pangea.org/vc_schemas/device-snapshot.json", + "type": "FullJsonSchemaValidator2021" + } +} diff --git a/idhub/templates/credentials/snapshot.json b/idhub/templates/credentials/snapshot.json deleted file mode 100644 index 2781a23..0000000 --- a/idhub/templates/credentials/snapshot.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://idhub.pangea.org/context/base.jsonld", - "https://idhub.pangea.org/context/snapshot.jsonld" - ], - "id": "urn:uuid:{{ vc_id }}", - "type": [ - "VerifiableCredential", - "DeviceSnapshot" - ], - "issuer": { - "id": "{{ issuer_did }}", - "name": "{{ organisation }}" - }, - "issuanceDate": "{{ issuance_date }}", - "validFrom": "{{ issuance_date }}", - "name": [ - { - "value": "Snapshot of Workbench script", - "lang": "en" - } - ], - "description": [ - { - "value": "Snapshot of Workbench script software for discover hardware", - "lang": "en" - } - ], - "credentialSubject": { - "id": "{{ token_hash }}", - "uuid": "{{ uuid }}", - "type": "{{ type }}", - "software": "{{ software }}", - "timestamp": "{{ timestamp }}", - "data": "{{ data }}", - "dataDeletion": "{{ erase }}" - }, - "credentialStatus": { - "id": "{{ credential_status_id}}", - "type": "RevocationBitmap2022", - "revocationBitmapIndex": "{{ id_credential }}" - }, - "credentialSchema": { - "id": "https://idhub.pangea.org/vc_schemas/v1/workbench.json", - "type": "FullJsonSchemaValidator2021" - } -} diff --git a/schemas/device-snapshot.json b/schemas/device-snapshot.json new file mode 100644 index 0000000..db3ffb5 --- /dev/null +++ b/schemas/device-snapshot.json @@ -0,0 +1,122 @@ +{ + "$id": "https://idhub.pangea.org/vc_schemas/v1/device-snapshot.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "DeviceSnapshot", + "description": "Snapshot create by workbench-script, software for discover hardware in one device.", + "name": [ + { + "value": "Snapshot", + "lang": "en" + } + ], + "type": "object", + "allOf": [ + { + "$ref": "https://www.w3.org/2018/credentials/v1" + }, + { + "properties": { + "credentialSubject": { + "description": "Define the properties of a digital device snapshot", + "type": "object", + "properties": { + "operatorId": { + "description": "Indentifier related to the product operator, defined a hash of an Id token (10 chars enough)", + "type": "string", + "minLength": 10 + }, + "uuid": { + "description": "Unique identifier of the snapshot.", + "type": "string", + "minLength": 36 + }, + "type": { + "description": "Defines a snapshot type, e.g., hardwareList, dataDeletion (need to adjust the enum values).", + "type": "string", + "enum": [ + "hardwareList", "dataDeletion" + ], + "minLength": 1 + }, + "software": { + "description": "Name of the snapshot software used.", + "type": "string", + "enum": [ + "workbench-script" + ], + "minLength": 1 + }, + "deviceId": { + "description": "List of identification properties for the device, each with a name and value.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The type of device identifier information, e.g., ManufacturerSerial, EthernetMacAddress.", + "type": "string" + }, + "value": { + "description": "The value of the device identifier information.", + "type": "string" + } + }, + "required": ["name", "value"] + } + }, + "timestamp": { + "description": "Date and time of this snapshot.", + "type": "string", + "format": "date-time" + } + }, + "required": [ + "uuid", + "type", + "timestamp" + ] + }, + "evidence": { + "description": "Contains supporting evidence about the process which resulted in the issuance of this credential as a result of system operations.", + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "description": "Type of evidence, linked to credentialSubject.type.", + "type": "string", + "enum": [ + "HardwareList", + "DataDeletion" + ] + }, + "operation": { + "description": "Specifies the command executed for evidence generation.", + "type": "string", + "enum": [ + "inxi", + "dmidecode", + "smartctl" + ] + }, + "output": { + "description": "Output from the executed command.", + "type": "string" + }, + "timestamp": { + "description": "Timestamp of the evidence generation if needed.", + "type": "string", + "format": "date-time" + } + }, + "required": [ + "type", + "operation", + "output" + ] + } + } + } + } + ] +} diff --git a/schemas/workbench.json b/schemas/workbench.json deleted file mode 100644 index 128e1c5..0000000 --- a/schemas/workbench.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "$id": "https://idhub.pangea.org/vc_schemas/v1/workbench.json", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "DeviceSnapshot", - "description": "Snapshot create by workbench-script, software for discover hardware in one device.", - "name": [ - { - "value": "Snapshot", - "lang": "en" - }, - ], - "type": "object", - "allOf": [ - { - "$ref": "https://www.w3.org/2018/credentials/v1" - }, - { - "properties": { - "credentialSubject": { - "description": "Define the properties of a digital device snapshot", - "type": "object", - "properties": { - "id": { - "description": "Defines a hash of id token", - "type": "string", - "minLength": 36 - }, - "uuid": { - "description": "Defines a unique identifier of the snapshot", - "type": "string", - "minLength": 36 - }, - "type": { - "type": "string", - "enum": [ - "Snapshot" - ], - "minLength": 1 - }, - "software": { - "description": "Name of software used.", - "type": "string", - "enum": [ - "workbench-script" - ], - "minLength": 1 - }, - "timestamp": { - "description": "Time when is make this snapshot.", - "type": "date-time" - }, - "data": { - "description": "Device details discovery data.", - "type": "string", - }, - "dataDeletion": { - "description": "Datas of erase disk process", - "type": "string", - "minLength": 0 - } - }, - "required": [ - "id", - "uuid", - "type", - "software", - "timestamp", - "data" - ] - } - } - } - ] -} From baa4d87a1194ff1462d00f9d51f47359eb097e9f Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 25 Nov 2024 20:18:47 +0100 Subject: [PATCH 5/8] sign snapschot credential from webhook --- idhub/management/commands/initial_datas.py | 1 + idhub/mixins.py | 18 +++--- ...-snapshot.json => device-snapshot-v1.json} | 16 ++---- ...-snapshot.json => device-snapshot-v1.json} | 4 +- trustchain_idhub/settings.py | 1 + webhook/urls.py | 1 + webhook/views.py | 56 ++++++++++++++++++- 7 files changed, 75 insertions(+), 22 deletions(-) rename idhub/templates/credentials/{device-snapshot.json => device-snapshot-v1.json} (72%) rename schemas/{device-snapshot.json => device-snapshot-v1.json} (97%) diff --git a/idhub/management/commands/initial_datas.py b/idhub/management/commands/initial_datas.py index b005dc3..462e944 100644 --- a/idhub/management/commands/initial_datas.py +++ b/idhub/management/commands/initial_datas.py @@ -105,6 +105,7 @@ class Command(BaseCommand): assert dname assert title except Exception: + ldata = {} title = '' _name = '' diff --git a/idhub/mixins.py b/idhub/mixins.py index a32e7f7..055f867 100644 --- a/idhub/mixins.py +++ b/idhub/mixins.py @@ -33,10 +33,11 @@ class UserView(LoginRequiredMixin): ] def get(self, request, *args, **kwargs): - err_txt = "User domain is {} which does not match server domain {}".format( - request.get_host(), settings.DOMAIN - ) - assert request.get_host() == settings.DOMAIN, err_txt + if not settings.DEVELOPMENT: + err_txt = "User domain is {} which does not match server domain {}".format( + request.get_host(), settings.DOMAIN + ) + assert request.get_host() == settings.DOMAIN, err_txt self.admin_validated = cache.get("KEY_DIDS") response = super().get(request, *args, **kwargs) @@ -55,10 +56,11 @@ class UserView(LoginRequiredMixin): return url or response def post(self, request, *args, **kwargs): - err_txt = "User domain is {} which does not match server domain {}".format( - request.get_host(), settings.DOMAIN - ) - assert request.get_host() == settings.DOMAIN, err_txt + if not settings.DEVELOPMENT: + err_txt = "User domain is {} which does not match server domain {}".format( + request.get_host(), settings.DOMAIN + ) + assert request.get_host() == settings.DOMAIN, err_txt self.admin_validated = cache.get("KEY_DIDS") response = super().post(request, *args, **kwargs) url = self.check_gdpr() diff --git a/idhub/templates/credentials/device-snapshot.json b/idhub/templates/credentials/device-snapshot-v1.json similarity index 72% rename from idhub/templates/credentials/device-snapshot.json rename to idhub/templates/credentials/device-snapshot-v1.json index 6038c95..ded926d 100644 --- a/idhub/templates/credentials/device-snapshot.json +++ b/idhub/templates/credentials/device-snapshot-v1.json @@ -1,13 +1,12 @@ { "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://idhub.pangea.org/vc_schemas/v1/device-snapshot.json" + "https://www.w3.org/2018/credentials/v1" ], "type": ["VerifiableCredential", "DeviceSnapshot"], "issuer": "{{ issuer_did }}", "issuanceDate": "{{ issuance_date }}", "credentialSubject": { - "operatorId": "{{ operatorid }}", + "operatorId": "123456789011121314", "uuid": "{{ uuid }}", "type": "hardwareList", "software": "workbench-script", @@ -44,24 +43,19 @@ }, { "type": "HardwareList", - "operation": "{{ smartctl }}", + "operation": "smartctl", "output": "{{ smartctl }}", "timestamp": "{{ issuance_date }}" }, { "type": "HardwareList", - "operation": "{{ inxi }}", + "operation": "inxi", "output": "{{ inxi }}", "timestamp": "{{ issuance_date }}" } ], - "credentialStatus": { - "id": "{{ credential_status_id}}", - "type": "RevocationBitmap2022", - "revocationBitmapIndex": "{{ id_credential }}" - }, "credentialSchema": { - "id": "https://idhub.pangea.org/vc_schemas/device-snapshot.json", + "id": "https://idhub.pangea.org/vc_schemas/device-snapshot-v1.json", "type": "FullJsonSchemaValidator2021" } } diff --git a/schemas/device-snapshot.json b/schemas/device-snapshot-v1.json similarity index 97% rename from schemas/device-snapshot.json rename to schemas/device-snapshot-v1.json index db3ffb5..c9ce093 100644 --- a/schemas/device-snapshot.json +++ b/schemas/device-snapshot-v1.json @@ -1,7 +1,7 @@ { - "$id": "https://idhub.pangea.org/vc_schemas/v1/device-snapshot.json", + "$id": "https://idhub.pangea.org/vc_schemas/device-snapshot-v1.json", "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "DeviceSnapshot", + "title": "DeviceSnapshotV1", "description": "Snapshot create by workbench-script, software for discover hardware in one device.", "name": [ { diff --git a/trustchain_idhub/settings.py b/trustchain_idhub/settings.py index 473fa24..7610a49 100644 --- a/trustchain_idhub/settings.py +++ b/trustchain_idhub/settings.py @@ -31,6 +31,7 @@ SECRET_KEY = config('SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = config('DEBUG', default=False, cast=bool) +DEVELOPMENT = config('DEVELOPMENT', default=False, cast=bool) DOMAIN = config("DOMAIN") assert DOMAIN not in [None, ''], "DOMAIN var is MANDATORY" diff --git a/webhook/urls.py b/webhook/urls.py index c0c863a..c2d4bd2 100644 --- a/webhook/urls.py +++ b/webhook/urls.py @@ -7,6 +7,7 @@ app_name = 'webhook' urlpatterns = [ path('verify/', views.webhook_verify, name='verify'), + path('sign/', views.webhook_issue, name='sign'), path('tokens/', views.WebHookTokenView.as_view(), name='tokens'), path('tokens/new', views.TokenNewView.as_view(), name='new_token'), path('tokens//del', views.TokenDeleteView.as_view(), name='delete_token'), diff --git a/webhook/views.py b/webhook/views.py index 2536eea..60ecc5e 100644 --- a/webhook/views.py +++ b/webhook/views.py @@ -11,6 +11,8 @@ from pyvckit.verify import verify_vp, verify_vc from uuid import uuid4 from idhub.mixins import AdminView +from idhub_auth.models import User +from idhub.models import DID, Schemas, VerificableCredential from webhook.models import Token from webhook.tables import TokensTable @@ -51,6 +53,59 @@ def webhook_verify(request): return JsonResponse({'error': 'Invalid request method'}, status=400) +@csrf_exempt +def webhook_issue(request): + if request.method == 'POST': + auth_header = request.headers.get('Authorization') + if not auth_header or not auth_header.startswith('Bearer '): + return JsonResponse({'error': 'Invalid or missing token'}, status=401) + + token = auth_header.split(' ')[1] + tk = Token.objects.filter(token=token).first() + if not tk: + return JsonResponse({'error': 'Invalid or missing token'}, status=401) + + try: + data = json.loads(request.body) + except json.JSONDecodeError: + return JsonResponse({'error': 'Invalid JSON'}, status=400) + + typ = data.get("type") + vc = data.get("data") + try: + vc = json.dumps(vc) + except Exception: + return JsonResponse({'error': 'Invalid JSON'}, status=400) + + user = User.objects.filter(email=data.get("user")).first() + if not typ or not vc or not user: + return JsonResponse({'error': 'Invalid JSON'}, status=400) + + did = DID.objects.filter(user__isnull=True).first() + if not did: + return JsonResponse({'error': 'Invalid DID'}, status=400) + + schema = Schemas.objects.filter(file_schema=typ).first() + if not schema: + return JsonResponse({'error': 'Invalid credential'}, status=400) + + cred = VerificableCredential( + csv_data=vc, + issuer_did=did, + schema=schema, + user=user + ) + + cred.set_type() + vc_signed = cred.issue(did, domain=request.get_host(), encrypt=False) + + return JsonResponse({'status': 'success', "data": vc_signed}, status=200) + + return JsonResponse({'status': 'fail'}, status=200) + + return JsonResponse({'error': 'Invalid request method'}, status=400) + + class WebHookTokenView(AdminView, SingleTableView): template_name = "token.html" title = _("Credential management") @@ -93,4 +148,3 @@ class TokenNewView(AdminView, View): Token.objects.create(token=uuid4()) return redirect('webhook:tokens') - From 3a7eb0f97edbb42a29c07a14defbed3407039b90 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 29 Nov 2024 10:59:36 +0100 Subject: [PATCH 6/8] issue with out save credential --- idhub/models.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/idhub/models.py b/idhub/models.py index e68c905..d6ecfb1 100644 --- a/idhub/models.py +++ b/idhub/models.py @@ -680,7 +680,7 @@ class VerificableCredential(models.Model): credential_subject = ujson.loads(data).get("credentialSubject", {}) return credential_subject.items() - def issue(self, did, domain): + def issue(self, did, domain, encrypt=True): if self.status == self.Status.ISSUED: return @@ -700,6 +700,9 @@ class VerificableCredential(models.Model): if not valid: return + if not encrypt: + return vc_str + self.data = self.user.encrypt_data(vc_str) self.status = self.Status.ISSUED From 4c07920a6acbc59513a54f13ebbef15b43df020b Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 5 Dec 2024 19:25:22 +0100 Subject: [PATCH 7/8] fix sign snapshots --- idhub/models.py | 4 ++-- idhub/templates/credentials/device-snapshot-v1.json | 6 +++--- webhook/views.py | 13 +++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/idhub/models.py b/idhub/models.py index d6ecfb1..73ce848 100644 --- a/idhub/models.py +++ b/idhub/models.py @@ -680,7 +680,7 @@ class VerificableCredential(models.Model): credential_subject = ujson.loads(data).get("credentialSubject", {}) return credential_subject.items() - def issue(self, did, domain, encrypt=True): + def issue(self, did, domain, save=True): if self.status == self.Status.ISSUED: return @@ -700,7 +700,7 @@ class VerificableCredential(models.Model): if not valid: return - if not encrypt: + if not save: return vc_str self.data = self.user.encrypt_data(vc_str) diff --git a/idhub/templates/credentials/device-snapshot-v1.json b/idhub/templates/credentials/device-snapshot-v1.json index ded926d..7e8e0a4 100644 --- a/idhub/templates/credentials/device-snapshot-v1.json +++ b/idhub/templates/credentials/device-snapshot-v1.json @@ -6,7 +6,7 @@ "issuer": "{{ issuer_did }}", "issuanceDate": "{{ issuance_date }}", "credentialSubject": { - "operatorId": "123456789011121314", + "operatorId": "{{ operator_id }}", "uuid": "{{ uuid }}", "type": "hardwareList", "software": "workbench-script", @@ -44,13 +44,13 @@ { "type": "HardwareList", "operation": "smartctl", - "output": "{{ smartctl }}", + "output": {{ smartctl|default:'""'|safe }}, "timestamp": "{{ issuance_date }}" }, { "type": "HardwareList", "operation": "inxi", - "output": "{{ inxi }}", + "output": {{ inxi|default:'""'|safe }}, "timestamp": "{{ issuance_date }}" } ], diff --git a/webhook/views.py b/webhook/views.py index 60ecc5e..71625d7 100644 --- a/webhook/views.py +++ b/webhook/views.py @@ -24,7 +24,7 @@ def webhook_verify(request): if not auth_header or not auth_header.startswith('Bearer '): return JsonResponse({'error': 'Invalid or missing token'}, status=401) - token = auth_header.split(' ')[1] + token = auth_header.split(' ')[1].strip("'").strip('"') tk = Token.objects.filter(token=token).first() if not tk: return JsonResponse({'error': 'Invalid or missing token'}, status=401) @@ -60,7 +60,7 @@ def webhook_issue(request): if not auth_header or not auth_header.startswith('Bearer '): return JsonResponse({'error': 'Invalid or missing token'}, status=401) - token = auth_header.split(' ')[1] + token = auth_header.split(' ')[1].strip("'").strip('"') tk = Token.objects.filter(token=token).first() if not tk: return JsonResponse({'error': 'Invalid or missing token'}, status=401) @@ -72,23 +72,24 @@ def webhook_issue(request): typ = data.get("type") vc = data.get("data") + save = data.get("save", True) try: vc = json.dumps(vc) except Exception: return JsonResponse({'error': 'Invalid JSON'}, status=400) - user = User.objects.filter(email=data.get("user")).first() - if not typ or not vc or not user: + if not typ or not vc: return JsonResponse({'error': 'Invalid JSON'}, status=400) did = DID.objects.filter(user__isnull=True).first() if not did: return JsonResponse({'error': 'Invalid DID'}, status=400) - schema = Schemas.objects.filter(file_schema=typ).first() + schema = Schemas.objects.filter(type=typ).first() if not schema: return JsonResponse({'error': 'Invalid credential'}, status=400) + user = User.objects.filter(is_admin=True).first() cred = VerificableCredential( csv_data=vc, issuer_did=did, @@ -97,7 +98,7 @@ def webhook_issue(request): ) cred.set_type() - vc_signed = cred.issue(did, domain=request.get_host(), encrypt=False) + vc_signed = cred.issue(did, domain=request.get_host(), save=save) return JsonResponse({'status': 'success', "data": vc_signed}, status=200) From 2c3225f08bb21f517af2bafe65e766278fc15a65 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 7 Jan 2025 17:23:55 +0100 Subject: [PATCH 8/8] update cache_context --- cache_context.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache_context.json b/cache_context.json index 035640e..2858662 100644 --- a/cache_context.json +++ b/cache_context.json @@ -1 +1 @@ -{"https://www.w3.org/2018/credentials/v1": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://www.w3.org/2018/credentials/v1", "document": {"@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "VerifiableCredential": {"@id": "https://www.w3.org/2018/credentials#VerifiableCredential", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "credentialSchema": {"@id": "cred:credentialSchema", "@type": "@id", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "JsonSchemaValidator2018": "cred:JsonSchemaValidator2018"}}, "credentialStatus": {"@id": "cred:credentialStatus", "@type": "@id"}, "credentialSubject": {"@id": "cred:credentialSubject", "@type": "@id"}, "evidence": {"@id": "cred:evidence", "@type": "@id"}, "expirationDate": {"@id": "cred:expirationDate", "@type": "xsd:dateTime"}, "holder": {"@id": "cred:holder", "@type": "@id"}, "issued": {"@id": "cred:issued", "@type": "xsd:dateTime"}, "issuer": {"@id": "cred:issuer", "@type": "@id"}, "issuanceDate": {"@id": "cred:issuanceDate", "@type": "xsd:dateTime"}, "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, "refreshService": {"@id": "cred:refreshService", "@type": "@id", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "ManualRefreshService2018": "cred:ManualRefreshService2018"}}, "termsOfUse": {"@id": "cred:termsOfUse", "@type": "@id"}, "validFrom": {"@id": "cred:validFrom", "@type": "xsd:dateTime"}, "validUntil": {"@id": "cred:validUntil", "@type": "xsd:dateTime"}}}, "VerifiablePresentation": {"@id": "https://www.w3.org/2018/credentials#VerifiablePresentation", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "sec": "https://w3id.org/security#", "holder": {"@id": "cred:holder", "@type": "@id"}, "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, "verifiableCredential": {"@id": "cred:verifiableCredential", "@type": "@id", "@container": "@graph"}}}, "EcdsaSecp256k1Signature2019": {"@id": "https://w3id.org/security#EcdsaSecp256k1Signature2019", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "EcdsaSecp256r1Signature2019": {"@id": "https://w3id.org/security#EcdsaSecp256r1Signature2019", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "Ed25519Signature2018": {"@id": "https://w3id.org/security#Ed25519Signature2018", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "RsaSignature2018": {"@id": "https://w3id.org/security#RsaSignature2018", "@context": {"@version": 1.1, "@protected": true, "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "proof": {"@id": "https://w3id.org/security#proof", "@type": "@id", "@container": "@graph"}}}}, "https://idhub.pangea.org/context/base.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/base.jsonld", "document": {"@context": {"credentialSchema": "https://idhub.pangea.org/context/#credentialSchema", "value": "https://idhub.pangea.org/context/#value", "lang": "https://idhub.pangea.org/context/#lang", "description": "https://idhub.pangea.org/context/#description", "name": "https://idhub.pangea.org/context/#name"}}}, "https://idhub.pangea.org/context/course-credential.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/course-credential.jsonld", "document": {"@context": {"firstName": "https://idhub.pangea.org/context/#firstName", "lastName": "https://idhub.pangea.org/context/#lastName", "personalIdentifier": "https://idhub.pangea.org/context/#personalIdentifier", "issuedDate": "https://idhub.pangea.org/context/#issuedDate", "modeOfInstruction": "https://idhub.pangea.org/context/#modeOfInstruction", "courseDuration": "https://idhub.pangea.org/context/#courseDuration", "courseDays": "https://idhub.pangea.org/context/#courseDays", "courseName": "https://idhub.pangea.org/context/#courseName", "courseDescription": "https://idhub.pangea.org/context/#courseDescription", "gradingScheme": "https://idhub.pangea.org/context/#gradingScheme", "scoreAwarded": "https://idhub.pangea.org/context/#scoreAwarded", "qualificationAwarded": "https://idhub.pangea.org/context/#qualificationAwarded", "courseLevel": "https://idhub.pangea.org/context/#courseLevel", "courseFramework": "https://idhub.pangea.org/context/#courseFramework", "courseCredits": "https://idhub.pangea.org/context/#courseCredits", "dateOfAssessment": "https://idhub.pangea.org/context/#dateOfAssessment", "evidenceAssessment": "https://idhub.pangea.org/context/#evidenceAssessment", "email": "https://idhub.pangea.org/context/#email"}}}, "https://w3id.org/security/v2": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://w3c-ccg.github.io/security-vocab/contexts/security-v2.jsonld", "document": {"@context": [{"@version": 1.1}, "https://w3id.org/security/v1", {"AesKeyWrappingKey2019": "sec:AesKeyWrappingKey2019", "DeleteKeyOperation": "sec:DeleteKeyOperation", "DeriveSecretOperation": "sec:DeriveSecretOperation", "EcdsaSecp256k1Signature2019": "sec:EcdsaSecp256k1Signature2019", "EcdsaSecp256r1Signature2019": "sec:EcdsaSecp256r1Signature2019", "EcdsaSecp256k1VerificationKey2019": "sec:EcdsaSecp256k1VerificationKey2019", "EcdsaSecp256r1VerificationKey2019": "sec:EcdsaSecp256r1VerificationKey2019", "Ed25519Signature2018": "sec:Ed25519Signature2018", "Ed25519VerificationKey2018": "sec:Ed25519VerificationKey2018", "EquihashProof2018": "sec:EquihashProof2018", "ExportKeyOperation": "sec:ExportKeyOperation", "GenerateKeyOperation": "sec:GenerateKeyOperation", "KmsOperation": "sec:KmsOperation", "RevokeKeyOperation": "sec:RevokeKeyOperation", "RsaSignature2018": "sec:RsaSignature2018", "RsaVerificationKey2018": "sec:RsaVerificationKey2018", "Sha256HmacKey2019": "sec:Sha256HmacKey2019", "SignOperation": "sec:SignOperation", "UnwrapKeyOperation": "sec:UnwrapKeyOperation", "VerifyOperation": "sec:VerifyOperation", "WrapKeyOperation": "sec:WrapKeyOperation", "X25519KeyAgreementKey2019": "sec:X25519KeyAgreementKey2019", "allowedAction": "sec:allowedAction", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}, "capability": {"@id": "sec:capability", "@type": "@id"}, "capabilityAction": "sec:capabilityAction", "capabilityChain": {"@id": "sec:capabilityChain", "@type": "@id", "@container": "@list"}, "capabilityDelegation": {"@id": "sec:capabilityDelegationMethod", "@type": "@id", "@container": "@set"}, "capabilityInvocation": {"@id": "sec:capabilityInvocationMethod", "@type": "@id", "@container": "@set"}, "caveat": {"@id": "sec:caveat", "@type": "@id", "@container": "@set"}, "challenge": "sec:challenge", "ciphertext": "sec:ciphertext", "controller": {"@id": "sec:controller", "@type": "@id"}, "delegator": {"@id": "sec:delegator", "@type": "@id"}, "equihashParameterK": {"@id": "sec:equihashParameterK", "@type": "xsd:integer"}, "equihashParameterN": {"@id": "sec:equihashParameterN", "@type": "xsd:integer"}, "invocationTarget": {"@id": "sec:invocationTarget", "@type": "@id"}, "invoker": {"@id": "sec:invoker", "@type": "@id"}, "jws": "sec:jws", "keyAgreement": {"@id": "sec:keyAgreementMethod", "@type": "@id", "@container": "@set"}, "kmsModule": {"@id": "sec:kmsModule"}, "parentCapability": {"@id": "sec:parentCapability", "@type": "@id"}, "plaintext": "sec:plaintext", "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab"}, "proofValue": "sec:proofValue", "referenceId": "sec:referenceId", "unwrappedKey": "sec:unwrappedKey", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}, "verifyData": "sec:verifyData", "wrappedKey": "sec:wrappedKey"}]}}, "https://w3id.org/security/v1": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://w3c-ccg.github.io/security-vocab/contexts/security-v1.jsonld", "document": {"@context": {"id": "@id", "type": "@type", "dc": "http://purl.org/dc/terms/", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "EcdsaKoblitzSignature2016": "sec:EcdsaKoblitzSignature2016", "Ed25519Signature2018": "sec:Ed25519Signature2018", "EncryptedMessage": "sec:EncryptedMessage", "GraphSignature2012": "sec:GraphSignature2012", "LinkedDataSignature2015": "sec:LinkedDataSignature2015", "LinkedDataSignature2016": "sec:LinkedDataSignature2016", "CryptographicKey": "sec:Key", "authenticationTag": "sec:authenticationTag", "canonicalizationAlgorithm": "sec:canonicalizationAlgorithm", "cipherAlgorithm": "sec:cipherAlgorithm", "cipherData": "sec:cipherData", "cipherKey": "sec:cipherKey", "created": {"@id": "dc:created", "@type": "xsd:dateTime"}, "creator": {"@id": "dc:creator", "@type": "@id"}, "digestAlgorithm": "sec:digestAlgorithm", "digestValue": "sec:digestValue", "domain": "sec:domain", "encryptionKey": "sec:encryptionKey", "expiration": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "initializationVector": "sec:initializationVector", "iterationCount": "sec:iterationCount", "nonce": "sec:nonce", "normalizationAlgorithm": "sec:normalizationAlgorithm", "owner": {"@id": "sec:owner", "@type": "@id"}, "password": "sec:password", "privateKey": {"@id": "sec:privateKey", "@type": "@id"}, "privateKeyPem": "sec:privateKeyPem", "publicKey": {"@id": "sec:publicKey", "@type": "@id"}, "publicKeyBase58": "sec:publicKeyBase58", "publicKeyPem": "sec:publicKeyPem", "publicKeyWif": "sec:publicKeyWif", "publicKeyService": {"@id": "sec:publicKeyService", "@type": "@id"}, "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"}, "salt": "sec:salt", "signature": "sec:signature", "signatureAlgorithm": "sec:signingAlgorithm", "signatureValue": "sec:signatureValue"}}}, "https://idhub.pangea.org/context/federation-membership.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/federation-membership.jsonld", "document": {"@context": {"federation": "https://idhub.pangea.org/context/#federation", "legalName": "https://idhub.pangea.org/context/#legalName", "shortName": "https://idhub.pangea.org/context/#shortName", "registrationIdentifier": "https://idhub.pangea.org/context/#registrationIdentifier", "publicRegistry": "https://idhub.pangea.org/context/#publicRegistry", "streetAddress": "https://idhub.pangea.org/context/#streetAddress", "postCode": "https://idhub.pangea.org/context/#postCode", "city": "https://idhub.pangea.org/context/#city", "taxReference": "https://idhub.pangea.org/context/#taxReference", "membershipType": "https://idhub.pangea.org/context/#membershipType", "membershipStatus": "https://idhub.pangea.org/context/#membershipStatus", "membershipId": "https://idhub.pangea.org/context/#membershipId", "membershipSince": "https://idhub.pangea.org/context/#membershipSince", "email": "https://idhub.pangea.org/context/#email", "phone": "https://idhub.pangea.org/context/#phone", "website": "https://idhub.pangea.org/context/#website", "evidence": "https://idhub.pangea.org/context/#evidence", "certificationDate": "https://idhub.pangea.org/context/#certificationDate"}}}, "https://idhub.pangea.org/context/membership-card.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/membership-card.jsonld", "document": {"@context": {"firstName": "https://idhub.pangea.org/context/#firstName", "lastName": "https://idhub.pangea.org/context/#lastName", "email": "https://idhub.pangea.org/context/#email", "organisation": "https://idhub.pangea.org/context/#organisation", "membershipType": "https://idhub.pangea.org/context/#membershipType", "membershipId": "https://idhub.pangea.org/context/#membershipId", "affiliatedSince": "https://idhub.pangea.org/context/#iaffiliatedSince", "affiliatedUntil": "https://idhub.pangea.org/context/#affiliatedUntil", "typeOfPerson": "https://idhub.pangea.org/context/#typeOfPerson", "identityDocType": "https://idhub.pangea.org/context/#identityDocType", "identityNumber": "https://idhub.pangea.org/context/#identityNumber"}}}, "https://idhub.pangea.org/context/financial-vulnerability.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/financial-vulnerability.jsonld", "document": {"@context": {"firstName": "https://idhub.pangea.org/context/#firstName", "lastName": "https://idhub.pangea.org/context/#lastName", "email": "https://idhub.pangea.org/context/#email", "phoneNumber": "https://idhub.pangea.org/context/#phoneNumber", "identityDocType": "https://idhub.pangea.org/context/#identityDocType", "identityNumber": "https://idhub.pangea.org/context/#identityNumber", "streetAddress": "https://idhub.pangea.org/context/#streetAddress", "socialWorkerName": "https://idhub.pangea.org/context/#socialWorkerName", "socialWorkerSurname": "https://idhub.pangea.org/context/#socialWorkerSurname", "financialVulnerabilityScore": "https://idhub.pangea.org/context/#financialVulnerabilityScore", "amountCoveredByOtherAids": "https://idhub.pangea.org/context/#amountCoveredByOtherAids", "connectivityOptionList": "https://idhub.pangea.org/context/#connectivityOptionList", "assessmentDate": "https://idhub.pangea.org/context/#assessmentDate"}}}, "https://idhub.pangea.org/context/e-operator-claim.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/e-operator-claim.jsonld", "document": {"@context": {"legalName": "https://idhub.pangea.org/context/#legalName", "accreditedBy": "https://idhub.pangea.org/context/#accreditedBy", "operatorNumber": "https://idhub.pangea.org/context/#operatorNumber", "limitJurisdiction": "https://idhub.pangea.org/context/#limitJurisdiction", "accreditedFor": "https://idhub.pangea.org/context/#accreditedFor", "role": "https://idhub.pangea.org/context/#role", "email": "https://idhub.pangea.org/context/#email"}}}} \ No newline at end of file +{"https://www.w3.org/2018/credentials/v1": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://www.w3.org/2018/credentials/v1", "document": {"@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "VerifiableCredential": {"@id": "https://www.w3.org/2018/credentials#VerifiableCredential", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "credentialSchema": {"@id": "cred:credentialSchema", "@type": "@id", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "JsonSchemaValidator2018": "cred:JsonSchemaValidator2018"}}, "credentialStatus": {"@id": "cred:credentialStatus", "@type": "@id"}, "credentialSubject": {"@id": "cred:credentialSubject", "@type": "@id"}, "evidence": {"@id": "cred:evidence", "@type": "@id"}, "expirationDate": {"@id": "cred:expirationDate", "@type": "xsd:dateTime"}, "holder": {"@id": "cred:holder", "@type": "@id"}, "issued": {"@id": "cred:issued", "@type": "xsd:dateTime"}, "issuer": {"@id": "cred:issuer", "@type": "@id"}, "issuanceDate": {"@id": "cred:issuanceDate", "@type": "xsd:dateTime"}, "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, "refreshService": {"@id": "cred:refreshService", "@type": "@id", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "ManualRefreshService2018": "cred:ManualRefreshService2018"}}, "termsOfUse": {"@id": "cred:termsOfUse", "@type": "@id"}, "validFrom": {"@id": "cred:validFrom", "@type": "xsd:dateTime"}, "validUntil": {"@id": "cred:validUntil", "@type": "xsd:dateTime"}}}, "VerifiablePresentation": {"@id": "https://www.w3.org/2018/credentials#VerifiablePresentation", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "cred": "https://www.w3.org/2018/credentials#", "sec": "https://w3id.org/security#", "holder": {"@id": "cred:holder", "@type": "@id"}, "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, "verifiableCredential": {"@id": "cred:verifiableCredential", "@type": "@id", "@container": "@graph"}}}, "EcdsaSecp256k1Signature2019": {"@id": "https://w3id.org/security#EcdsaSecp256k1Signature2019", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "EcdsaSecp256r1Signature2019": {"@id": "https://w3id.org/security#EcdsaSecp256r1Signature2019", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "Ed25519Signature2018": {"@id": "https://w3id.org/security#Ed25519Signature2018", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "RsaSignature2018": {"@id": "https://w3id.org/security#RsaSignature2018", "@context": {"@version": 1.1, "@protected": true, "challenge": "sec:challenge", "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, "domain": "sec:domain", "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "jws": "sec:jws", "nonce": "sec:nonce", "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab", "@context": {"@version": 1.1, "@protected": true, "id": "@id", "type": "@type", "sec": "https://w3id.org/security#", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}}}, "proofValue": "sec:proofValue", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}}}, "proof": {"@id": "https://w3id.org/security#proof", "@type": "@id", "@container": "@graph"}}}}, "https://idhub.pangea.org/context/base.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/base.jsonld", "document": {"@context": {"credentialSchema": "https://idhub.pangea.org/context/#credentialSchema", "value": "https://idhub.pangea.org/context/#value", "lang": "https://idhub.pangea.org/context/#lang", "description": "https://idhub.pangea.org/context/#description", "name": "https://idhub.pangea.org/context/#name"}}}, "https://idhub.pangea.org/context/course-credential.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/course-credential.jsonld", "document": {"@context": {"firstName": "https://idhub.pangea.org/context/#firstName", "lastName": "https://idhub.pangea.org/context/#lastName", "personalIdentifier": "https://idhub.pangea.org/context/#personalIdentifier", "issuedDate": "https://idhub.pangea.org/context/#issuedDate", "modeOfInstruction": "https://idhub.pangea.org/context/#modeOfInstruction", "courseDuration": "https://idhub.pangea.org/context/#courseDuration", "courseDays": "https://idhub.pangea.org/context/#courseDays", "courseName": "https://idhub.pangea.org/context/#courseName", "courseDescription": "https://idhub.pangea.org/context/#courseDescription", "gradingScheme": "https://idhub.pangea.org/context/#gradingScheme", "scoreAwarded": "https://idhub.pangea.org/context/#scoreAwarded", "qualificationAwarded": "https://idhub.pangea.org/context/#qualificationAwarded", "courseLevel": "https://idhub.pangea.org/context/#courseLevel", "courseFramework": "https://idhub.pangea.org/context/#courseFramework", "courseCredits": "https://idhub.pangea.org/context/#courseCredits", "dateOfAssessment": "https://idhub.pangea.org/context/#dateOfAssessment", "evidenceAssessment": "https://idhub.pangea.org/context/#evidenceAssessment", "email": "https://idhub.pangea.org/context/#email"}}}, "https://w3id.org/security/v2": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://w3c-ccg.github.io/security-vocab/contexts/security-v2.jsonld", "document": {"@context": [{"@version": 1.1}, "https://w3id.org/security/v1", {"AesKeyWrappingKey2019": "sec:AesKeyWrappingKey2019", "DeleteKeyOperation": "sec:DeleteKeyOperation", "DeriveSecretOperation": "sec:DeriveSecretOperation", "EcdsaSecp256k1Signature2019": "sec:EcdsaSecp256k1Signature2019", "EcdsaSecp256r1Signature2019": "sec:EcdsaSecp256r1Signature2019", "EcdsaSecp256k1VerificationKey2019": "sec:EcdsaSecp256k1VerificationKey2019", "EcdsaSecp256r1VerificationKey2019": "sec:EcdsaSecp256r1VerificationKey2019", "Ed25519Signature2018": "sec:Ed25519Signature2018", "Ed25519VerificationKey2018": "sec:Ed25519VerificationKey2018", "EquihashProof2018": "sec:EquihashProof2018", "ExportKeyOperation": "sec:ExportKeyOperation", "GenerateKeyOperation": "sec:GenerateKeyOperation", "KmsOperation": "sec:KmsOperation", "RevokeKeyOperation": "sec:RevokeKeyOperation", "RsaSignature2018": "sec:RsaSignature2018", "RsaVerificationKey2018": "sec:RsaVerificationKey2018", "Sha256HmacKey2019": "sec:Sha256HmacKey2019", "SignOperation": "sec:SignOperation", "UnwrapKeyOperation": "sec:UnwrapKeyOperation", "VerifyOperation": "sec:VerifyOperation", "WrapKeyOperation": "sec:WrapKeyOperation", "X25519KeyAgreementKey2019": "sec:X25519KeyAgreementKey2019", "allowedAction": "sec:allowedAction", "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}, "capability": {"@id": "sec:capability", "@type": "@id"}, "capabilityAction": "sec:capabilityAction", "capabilityChain": {"@id": "sec:capabilityChain", "@type": "@id", "@container": "@list"}, "capabilityDelegation": {"@id": "sec:capabilityDelegationMethod", "@type": "@id", "@container": "@set"}, "capabilityInvocation": {"@id": "sec:capabilityInvocationMethod", "@type": "@id", "@container": "@set"}, "caveat": {"@id": "sec:caveat", "@type": "@id", "@container": "@set"}, "challenge": "sec:challenge", "ciphertext": "sec:ciphertext", "controller": {"@id": "sec:controller", "@type": "@id"}, "delegator": {"@id": "sec:delegator", "@type": "@id"}, "equihashParameterK": {"@id": "sec:equihashParameterK", "@type": "xsd:integer"}, "equihashParameterN": {"@id": "sec:equihashParameterN", "@type": "xsd:integer"}, "invocationTarget": {"@id": "sec:invocationTarget", "@type": "@id"}, "invoker": {"@id": "sec:invoker", "@type": "@id"}, "jws": "sec:jws", "keyAgreement": {"@id": "sec:keyAgreementMethod", "@type": "@id", "@container": "@set"}, "kmsModule": {"@id": "sec:kmsModule"}, "parentCapability": {"@id": "sec:parentCapability", "@type": "@id"}, "plaintext": "sec:plaintext", "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab"}, "proofValue": "sec:proofValue", "referenceId": "sec:referenceId", "unwrappedKey": "sec:unwrappedKey", "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}, "verifyData": "sec:verifyData", "wrappedKey": "sec:wrappedKey"}]}}, "https://w3id.org/security/v1": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://w3c-ccg.github.io/security-vocab/contexts/security-v1.jsonld", "document": {"@context": {"id": "@id", "type": "@type", "dc": "http://purl.org/dc/terms/", "sec": "https://w3id.org/security#", "xsd": "http://www.w3.org/2001/XMLSchema#", "EcdsaKoblitzSignature2016": "sec:EcdsaKoblitzSignature2016", "Ed25519Signature2018": "sec:Ed25519Signature2018", "EncryptedMessage": "sec:EncryptedMessage", "GraphSignature2012": "sec:GraphSignature2012", "LinkedDataSignature2015": "sec:LinkedDataSignature2015", "LinkedDataSignature2016": "sec:LinkedDataSignature2016", "CryptographicKey": "sec:Key", "authenticationTag": "sec:authenticationTag", "canonicalizationAlgorithm": "sec:canonicalizationAlgorithm", "cipherAlgorithm": "sec:cipherAlgorithm", "cipherData": "sec:cipherData", "cipherKey": "sec:cipherKey", "created": {"@id": "dc:created", "@type": "xsd:dateTime"}, "creator": {"@id": "dc:creator", "@type": "@id"}, "digestAlgorithm": "sec:digestAlgorithm", "digestValue": "sec:digestValue", "domain": "sec:domain", "encryptionKey": "sec:encryptionKey", "expiration": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, "initializationVector": "sec:initializationVector", "iterationCount": "sec:iterationCount", "nonce": "sec:nonce", "normalizationAlgorithm": "sec:normalizationAlgorithm", "owner": {"@id": "sec:owner", "@type": "@id"}, "password": "sec:password", "privateKey": {"@id": "sec:privateKey", "@type": "@id"}, "privateKeyPem": "sec:privateKeyPem", "publicKey": {"@id": "sec:publicKey", "@type": "@id"}, "publicKeyBase58": "sec:publicKeyBase58", "publicKeyPem": "sec:publicKeyPem", "publicKeyWif": "sec:publicKeyWif", "publicKeyService": {"@id": "sec:publicKeyService", "@type": "@id"}, "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"}, "salt": "sec:salt", "signature": "sec:signature", "signatureAlgorithm": "sec:signingAlgorithm", "signatureValue": "sec:signatureValue"}}}, "https://idhub.pangea.org/context/federation-membership.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/federation-membership.jsonld", "document": {"@context": {"federation": "https://idhub.pangea.org/context/#federation", "legalName": "https://idhub.pangea.org/context/#legalName", "shortName": "https://idhub.pangea.org/context/#shortName", "registrationIdentifier": "https://idhub.pangea.org/context/#registrationIdentifier", "publicRegistry": "https://idhub.pangea.org/context/#publicRegistry", "streetAddress": "https://idhub.pangea.org/context/#streetAddress", "postCode": "https://idhub.pangea.org/context/#postCode", "city": "https://idhub.pangea.org/context/#city", "taxReference": "https://idhub.pangea.org/context/#taxReference", "membershipType": "https://idhub.pangea.org/context/#membershipType", "membershipStatus": "https://idhub.pangea.org/context/#membershipStatus", "membershipId": "https://idhub.pangea.org/context/#membershipId", "membershipSince": "https://idhub.pangea.org/context/#membershipSince", "email": "https://idhub.pangea.org/context/#email", "phone": "https://idhub.pangea.org/context/#phone", "website": "https://idhub.pangea.org/context/#website", "evidence": "https://idhub.pangea.org/context/#evidence", "certificationDate": "https://idhub.pangea.org/context/#certificationDate"}}}, "https://idhub.pangea.org/context/membership-card.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/membership-card.jsonld", "document": {"@context": {"firstName": "https://idhub.pangea.org/context/#firstName", "lastName": "https://idhub.pangea.org/context/#lastName", "email": "https://idhub.pangea.org/context/#email", "organisation": "https://idhub.pangea.org/context/#organisation", "membershipType": "https://idhub.pangea.org/context/#membershipType", "membershipId": "https://idhub.pangea.org/context/#membershipId", "affiliatedSince": "https://idhub.pangea.org/context/#iaffiliatedSince", "affiliatedUntil": "https://idhub.pangea.org/context/#affiliatedUntil", "typeOfPerson": "https://idhub.pangea.org/context/#typeOfPerson", "identityDocType": "https://idhub.pangea.org/context/#identityDocType", "identityNumber": "https://idhub.pangea.org/context/#identityNumber"}}}, "https://idhub.pangea.org/context/financial-vulnerability.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/financial-vulnerability.jsonld", "document": {"@context": {"firstName": "https://idhub.pangea.org/context/#firstName", "lastName": "https://idhub.pangea.org/context/#lastName", "email": "https://idhub.pangea.org/context/#email", "phoneNumber": "https://idhub.pangea.org/context/#phoneNumber", "identityDocType": "https://idhub.pangea.org/context/#identityDocType", "identityNumber": "https://idhub.pangea.org/context/#identityNumber", "streetAddress": "https://idhub.pangea.org/context/#streetAddress", "socialWorkerName": "https://idhub.pangea.org/context/#socialWorkerName", "socialWorkerSurname": "https://idhub.pangea.org/context/#socialWorkerSurname", "financialVulnerabilityScore": "https://idhub.pangea.org/context/#financialVulnerabilityScore", "amountCoveredByOtherAids": "https://idhub.pangea.org/context/#amountCoveredByOtherAids", "connectivityOptionList": "https://idhub.pangea.org/context/#connectivityOptionList", "assessmentDate": "https://idhub.pangea.org/context/#assessmentDate"}}}, "https://idhub.pangea.org/context/e-operator-claim.jsonld": {"contentType": "application/ld+json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/context/e-operator-claim.jsonld", "document": {"@context": {"legalName": "https://idhub.pangea.org/context/#legalName", "accreditedBy": "https://idhub.pangea.org/context/#accreditedBy", "operatorNumber": "https://idhub.pangea.org/context/#operatorNumber", "limitJurisdiction": "https://idhub.pangea.org/context/#limitJurisdiction", "accreditedFor": "https://idhub.pangea.org/context/#accreditedFor", "role": "https://idhub.pangea.org/context/#role", "email": "https://idhub.pangea.org/context/#email"}}}, "https://idhub.pangea.org/vc_schemas/device-snapshot-v1.json": {"contentType": "application/json", "contextUrl": null, "documentUrl": "https://idhub.pangea.org/vc_schemas/device-snapshot-v1.json", "document": {"$id": "https://idhub.pangea.org/vc_schemas/device-snapshot-v1.json", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "DeviceSnapshot", "description": "Snapshot create by workbench-script, software for discover hardware in one device.", "name": [{"value": "Snapshot", "lang": "en"}], "type": "object", "allOf": [{"$ref": "https://www.w3.org/2018/credentials/v1"}, {"properties": {"credentialSubject": {"description": "Define the properties of a digital device snapshot", "type": "object", "properties": {"operatorId": {"description": "Indentifier related to the product operator, defined a hash of an Id token (10 chars enough)", "type": "string", "minLength": 10}, "uuid": {"description": "Unique identifier of the snapshot.", "type": "string", "minLength": 36}, "type": {"description": "Defines a snapshot type, e.g., hardwareList, dataDeletion (need to adjust the enum values).", "type": "string", "enum": ["hardwareList", "dataDeletion"], "minLength": 1}, "software": {"description": "Name of the snapshot software used.", "type": "string", "enum": ["workbench-script"], "minLength": 1}, "deviceId": {"description": "List of identification properties for the device, each with a name and value.", "type": "array", "items": {"type": "object", "properties": {"name": {"description": "The type of device identifier information, e.g., ManufacturerSerial, EthernetMacAddress.", "type": "string"}, "value": {"description": "The value of the device identifier information.", "type": "string"}}, "required": ["name", "value"]}}, "timestamp": {"description": "Date and time of this snapshot.", "type": "string", "format": "date-time"}}, "required": ["uuid", "type", "timestamp"]}, "evidence": {"description": "Contains supporting evidence about the process which resulted in the issuance of this credential as a result of system operations.", "type": "array", "items": {"type": "object", "properties": {"type": {"description": "Type of evidence, linked to credentialSubject.type.", "type": "string", "enum": ["HardwareList", "DataDeletion"]}, "operation": {"description": "Specifies the command executed for evidence generation.", "type": "string", "enum": ["inxi", "dmidecode", "smartctl"]}, "output": {"description": "Output from the executed command.", "type": "string"}, "timestamp": {"description": "Timestamp of the evidence generation if needed.", "type": "string", "format": "date-time"}}, "required": ["type", "operation", "output"]}}}}]}}} \ No newline at end of file