# Data Agreements
### Content
* [Admin](#Admin)
* [Tasks](#Tasks)
* [Roadmap](#Roadmap)
* [Minimum Viable Contract](#Minimum-Viable-Contract)
* [User Journey](#User-Journey)
* [Examples](#Examples)
* [Implementation](#Implementation)
* [Structure](#Structure)
* [EEG Use Case](#EEG-Use-Case)
* [P2P Use Case](#P2P-Use-Case)
* [Alignment Checks](#Alignment-Check)
* [Intermediary Integration](#Intermediary-Integration)
## Admin
### Links
* DPV Vocabulatory: https://w3c.github.io/dpv/2.0/dpv/#vocab-processing
* Hermit Reasoner: http://www.hermit-reasoner.com/
### Tasks
- [x] Christoph: describe a minimal example
- [x] Christoph: 2 Use Case Examples
- [x] Fajar: how to specify type of Data Agreement (relevant attributes and matching) for reasoner
### Roadmap
*2024-09-02 done: examples available -> EEG & P2P Use Case*
*2024-09-15 done: Form rendering*
*2024-09-24 done: Taxonomy definition & editing*
*2024-10-15 done: reasoner for alignment checks*
*2024-10-31 done: integration into Data Intermediary Frontend*
## Minimum Viable Contract
**Goal:** descibe the minimum possible example that demonstrates using Data Agreements to form a contract between 2 parties for data exchange
### User Journey
1) login with ID Autria to https://dashboard.go-data.at
result: access to government issued identity
2) bind identity from SSI wallet (e.g. Sphereon) to ID Austria
result: access to DID (incl. public key) from user and stored in account
<details><summary>Notes</summary>
* implement OID4VC to access DID in SSI Wallet
* optionally, also implement OID4VCI to issue "Intermediary Access Credential" to SSI Wallet and
* allow login via OID4VP (instead of ID Austria); this might motivate the initial OID4VC flow
</details>
3) User (Data Provider) creates D2A
[`D2Amini`](https://soya.ownyourdata.eu/D2Amini/yaml) - minimalistic domain-specific data agreement ([edit](https://soya-form.ownyourdata.eu/?schemaDri=D2Amini) | [example](https://soya-form.ownyourdata.eu/?schemaDri=D2Amini&data=%7B%22subject%22%3A%5B%7B%22value%22%3A%22payload%22%7D%5D%2C%22condition%22%3A%7B%22dpv%3AhasPurpose%22%3A%5B%22dpv%3AResearchAndDevelopment%22%5D%7D%2C%22trigger%22%3A%5B%7B%22name%22%3A%22inform%22%2C%22action%22%3A%22email%22%7D%5D%7D))
<details><summary>Notes</summary>
```json=
{
"subject": [{"value": "payload"}],
"condition": {"dpv:hasPurpose": ["dpv:ResearchAndDevelopment"]},
"trigger": [{"name": "inform", "action": "email"}]
}
```
* subject: should be JSON-LD document with the following options:
* independent object (example: intent and data for P2P electricity contract)
* pointer to resources (example: data in intermediary repo)
* combination of both (example: credentials to access MQTT server)
* conditions: JSON-LD document that holds ISO 27560:2023 consent statements (or other consent statements) supported by the reasoner
* trigger: proprietary (intermediary specific) actions to be executed in case a D2A is used to form a contract (e.g., email notification to data provider)
</details>
4) User (Data Provider) signes D2A
<details><summary>Notes</summary>
* use OID4VCI Flow to sign VC with wallet
(i.e., butto "Sign" opens window with QR code and input field for online wallet)
* Issuer is Data Provider (use DID from Step 2)
* Holder is Intermediary (configured DID)
* after VC is created and issued add an entry in the Data Catalog
</details>
5) User (Data Consumer) selects record from Data Catalog and creates D3A
[`D3Amini`](https://soya.ownyourdata.eu/D3Amini/yaml) - minimalistic domain-specific data disclosure agreement ([edit](https://soya-form.ownyourdata.eu/?schemaDri=D3Amini) | [example](https://soya-form.ownyourdata.eu/?schemaDri=D3Amini&data=%7B%22subject%22%3A%5B%5D%2C%22trigger%22%3A%5B%7B%22name%22%3A%22data+transfer%22%2C%22action%22%3A%22REST+endpoint%22%2C%22endpoint%22%3A%22https%3A%2F%2Fplayground.data-container.net%22%7D%5D%2C%22condition%22%3A%7B%22dpv%3AhasPurpose%22%3A%5B%22dpv%3AResearchAndDevelopment%22%5D%7D%7D))
<details><summary>Notes</summary>
```json=
{
"subject": [],
"condition": {"dpv:hasPurpose": ["dpv:ResearchAndDevelopment"]},
"trigger": [{
"name": "data transfer",
"action": "REST endpoint",
"endpoint": "https://playground.data-container.net"
}]
}
```
* subject: should be JSON-LD document with the following options:
* independent object (example: data for P2P electricity contract)
* pointer to resources for accepting data
* combination of both
* conditions: JSON-LD document that holds ISO 27560:2023 consent statements (or other consent statements) supported by the reasoner
* trigger: proprietary (intermediary specific) actions to be executed in case a D2A is used to form a contract (e.g., email notification to data provider)
</details>
6) User (Data Consumer) signs D3A
<details><summary>Notes</summary>
* use OID4VCI Flow to sign VC with wallet
(i.e., butto "Sign" opens window with QR code and input field for online wallet)
* Issuer is Data Consumer (use DID from onboarding in Step 2)
* Holder is Intermediary (configured DID)
* after successful signing `subject` is evaluated (might be a sequence of processing steps)
* a reasoner checks for each step if input (D2A) matches the output (D3A)
* if the reasoner does not proof compliance a report for non-compliance is shown (-> possibility to adapt or "use manual approval")
* if the reasoner proofs compliance all triggers are executed
* document everything in logs
* D3As are also used for entries in the service catalogue, the subject of which specifies the service and the expected input and output data formats
* it is also possible that manual approval must be obtained from the data provider and/or data consumer for free text parts in D2A/D3A
</details>
7) Data Consumer has access to data provided by Data Provider
### Examples
**Contract:**
```json=
{
"d2a": {
"credential": "https://credential.go-data.at/credentials/zQmevw6Ra6MVYF2oXzgDT5yAMCQTM2ChvKXLZvNzAD6mLsm"
},
"d3a": {
"credential": "https://credential.go-data.at/credentials/zQmPCx7Sdh2E29BQ4jfH4KvtLMjPWpLGvJwyGiF5dVA3zuM"
},
"reasoner": {
"srv-version": "0.1",
"timestamp": 1725963104
"zkp": "string"
},
"trigger": [
{
"inform": "mail",
"srv-version": "0.1",
"timestamp": 1725963105,
"arguments": {"user": "did:oyd:data-provider"}
}, {
"transfer": "data",
"srv-version": "0.1",
"timestamp": 1725963106,
"arguments": {"user": "did:oyd:data-consumer", "payload-hash": "c25236d2e22f4573cf5faa3b259b307ee56f442f9d38d27fb419e8791fe41fc1", "endpoint": "https://playground.data-container.net/api/data"}
}
]
}
```
### Implementation
- [ ] Abstimmung mit Christoph K.
* process meaningful & comprehensible?
* ask legal expert: When 2 parties sign a contract with an intermediary (data agreements) and a new contract is created in an automated way from these inputs, is this new contract then valid & legally binding?
- [ ] Abstimmung mit SOyA Team
* Prozess sinnvoll & nachvollziehbar
* JSON-LD spezifizieren für
- [ ] subject
- [ ] consent
- [ ] triggers
- [ ] GUI mit Jakob abstimmen
- [ ] Darstellung von Button (bei User Page?) zur Erstellung von D2A
- [ ] Liste von Data Agreements
- [ ] Data Catalog Liste
- [ ] "Access" Button bei jedem Data Catalog Eintrag
- [ ] Contract Liste
- [ ] Log Liste
- [ ] Funktionalität zum Signieren in Sphereon Wallet
- [ ] implementation
- [ ] OID4VC um DID bei User abzulegen
- [ ] OID4VCI für Credential zum Login (optional, aber motiviert OID4VC)
- [ ] OID4VP beim Login (optional)
- [ ] Trigger Service zum Ausführen Aktionen
- [ ] Reasoner der D2A und D3A vergleicht
- [ ] Logging Service / Struktur für Logging
## Reasoner
D2A - Domain-specific Data sharing Agreement (Provider)
D3A - Domain-specific Data Disclosure Agreement (Consumer)
### Interface
- `PUT /api/match`
```json
{
"d2aConsent": {
"model": "D2Aeeg",
"hasPurpose": [
"PublicBenefit",
"ResearchAndDevelopment",
"ServiceProvision"
],
"hasProcessing": [
"Organise",
"Store",
"Transform",
"Use"
],
"hasExpiryTime": 123
},
"d3aConsent": {
"model": "D3Aeeg",
"hasPurpose": [
"ResearchAndDevelopment"
],
"hasProcessing": [
"Store",
"Organise",
"Transform",
"Use"
],
"hasExpiryTime": 124
}
}
```
- Response:
```json
{
"version": string,
"match": boolean,
"messages": []
}
```
### Roadmap:
- Docker Image & deploy auf K8s
- [x] CFA: Anleitung & deployment.yaml für `reasoner.go-data.at`
### Test Cases
- item
## Structure
### EEG Use Case
inital work: https://hackmd.io/3GhuO47oRXu3_mpGO_pXvw#Data-Agreements
* [`D2Aeeg`](https://soya.ownyourdata.eu/D2Aeeg/yaml) - EEG domain-specific data agreement ([edit](https://soya-form.ownyourdata.eu/?schemaDri=D2Aeeg) | [example](https://soya-form.ownyourdata.eu/?schemaDri=D2Aeeg&data=%7B%22subject%22%3A%7B%22eegType%22%3A%22Verein%22%2C%22eegRegisteredNumber%22%3A%22123%22%2C%22contact%22%3A%7B%22name%22%3A%22John+Doe%22%2C%22addresse%22%3A%22Hauptstra%C3%9Fe+15%2C+7000+Eisenstadt%22%7D%7D%2C%22consent%22%3A%7B%22hasPurpose%22%3A%5B%22PublicBenefit%22%2C%22ResearchAndDevelopment%22%2C%22ServiceProvision%22%5D%2C%22hasProcessing%22%3A%5B%22Organise%22%2C%22Store%22%2C%22Transform%22%2C%22Use%22%5D%2C%22hasExpiryTime%22%3A%226+Monate%22%7D%2C%22trigger%22%3A%5B%7B%22name%22%3A%22inform%22%2C%22action%22%3A%22Email%22%7D%5D%7D))
* [`D3Aeeg`](https://soya.ownyourdata.eu/D3Aeeg/yaml) - EEG domain-specific data disclosure agreement ([edit](https://soya-form.ownyourdata.eu/?schemaDri=D3Aeeg) | [example](https://soya-form.ownyourdata.eu/?schemaDri=D3Aeeg&data=%7B%22subject%22%3A%7B%22receiverType%22%3A%22K%C3%B6rperschaft+des+%C3%B6ffentlichen+Rechts%22%2C%22receiverRegisteredNumber%22%3A%22456%22%2C%22contact%22%3A%7B%22name%22%3A%22Jane+Doe%22%2C%22addresse%22%3A%22Karlsplatz+1%2C+1010+Wien%22%7D%7D%2C%22consent%22%3A%7B%22hasPurpose%22%3A%5B%22ResearchAndDevelopment%22%5D%2C%22hasProcessing%22%3A%5B%22Store%22%2C%22Organise%22%2C%22Transform%22%2C%22Use%22%5D%2C%22hasExpiryTime%22%3A%223+Monate%22%7D%2C%22trigger%22%3A%5B%7B%22name%22%3A%22data+transfer%22%2C%22action%22%3A%22REST+endpoint%22%2C%22endpoint%22%3A%22https%3A%2F%2Fplayground.data-container.net%22%7D%5D%7D))
<details><summary>Attributes</summary>
* Purpose: R&D, disclosure for members
* Processing: read, analyse, no restriction
* Storage Location: EU, no restriction
* Storage Duration: 6 months
* define data source
* allowed data users
</details>
### P2P Use Case
article: https://www.360ee.at/elwg-check-peer-to-peer-vertraege-strom-von-mir-zu-dir/
* [`D2Ap2p`](https://soya.ownyourdata.eu/D2Ap2p/yaml) - P2P domain-specific data agreement ([edit](https://soya-form.ownyourdata.eu/?schemaDri=D2Ap2p) | [example](https://soya-form.ownyourdata.eu/?schemaDri=D2Ap2p&data=%7B%22subject%22%3A%7B%22zaehlpunkt_provider%22%3A%221234%22%2C%22betriebsart%22%3A%22Photovoltaik%22%2C%22anteil%22%3A60.5%2C%22beginn%22%3A%222024-09-22%22%2C%22ende%22%3A%222024-09-30%22%2C%22provider%22%3A%7B%22name%22%3A%22Kontakt+1%22%2C%22adresse%22%3A%22Stra%C3%9Fe+1%2C+Ort+1%22%7D%2C%22consumer%22%3A%7B%22name%22%3A%22Kontakt+2%22%2C%22adresse%22%3A%22Stra%C3%9Fe+2%2C+Ort+2%22%7D%7D%2C%22condition%22%3A%7B%22dpv%3AhasPurpose%22%3A%5B%22dpv%3AEstablishContractualAgreement%22%5D%7D%2C%22trigger%22%3A%5B%7B%22name%22%3A%22inform%22%2C%22action%22%3A%22email%22%7D%5D%7D))
* [`D3Ap2p`](https://soya.ownyourdata.eu/D3Ap2p/yaml) - P2P domain-specific data disclosure agreement ([edit](https://soya-form.ownyourdata.eu/?schemaDri=D3Ap2p) | [example](https://soya-form.ownyourdata.eu/?schemaDri=D3Ap2p&data=%7B%22subject%22%3A%7B%22zaehlpunkt_consumer%22%3A%221234%22%2C%22provider%22%3A%7B%22name%22%3A%22Kontakt+1%22%2C%22adresse%22%3A%22Stra%C3%9Fe+1%2C+Ort+1%22%7D%2C%22consumer%22%3A%7B%22name%22%3A%22Kontakt+2%22%2C%22adresse%22%3A%22Stra%C3%9Fe+2%2C+Ort+2%22%7D%7D%2C%22condition%22%3A%7B%22dpv%3AhasPurpose%22%3A%5B%22dpv%3AEstablishContractualAgreement%22%5D%7D%2C%22trigger%22%3A%5B%7B%22name%22%3A%22inform%22%2C%22action%22%3A%22email%22%7D%5D%7D))
<details><summary>Attributes</summary>
* ID Austria Identity
* counting point (Zählpunkt)
* Technology and operating mode of the generation plants
(Technologie- und Betriebsart der Erzeugungsanlagen)
* amount
(Anteil der erzeugten Energiemenge, die der Vertragspartnerin oder dem Vertragspartner zugeteilt wird)
* begin & end date (Beginn und Beendigung des Peer-to-Peer-Vertrages)
</details>
## Alignment Check
*Input Fajar*
Taxonomy example: https://w3c.github.io/dpv/2.0/dpv/#fig-overview-of-purpose-taxonomy-in-dpv-click-here-to-open-diagram-in-a-new-window
for now: use SOyA Repo to store taxonomy
## Reasoner Service
* Github repo: https://github.com/OwnYourData/reasoner_service
* The functionality is visualized under https://github.com/OwnYourData/reasoner_service/blob/main/SOyA.png
* Makes reasoning functionality accessible as a service
* Returns explanation why the contracts are not matching
* The ontology model is read from another service
* In this ontology model the consent levels and class hierachies are defined
* Service URL: https://reasoner.go-data.at/api/match
* The Swagger documentation of the service is accessible under: "https://reasoner.go-data.at/swagger-ui/index.html#/"
Missing functionality
- [x] Time checking
- [ ] Minimization criteria (such as starting from)
### Result Explanation
* If the two consents are not matching an explanation is given
* For each attribute (such as 'hasProcessing') each value in the d3a is checked if it is covered by the d2a
* In the response the service returns all mismatches in a list
### Mini examples
("Use" is a superclass of the other hasProcessing values)
<details><summary>Example A</summary>
- `PUT /api/match`
```json
{
"ontology": "https://soya.ownyourdata.eu/OntologyEEG",
"d2aConsent": {
"model": "D2Aeeg",
"hasPurpose": [
"PublicBenefit",
"ResearchAndDevelopment",
"ServiceProvision"
],
"hasProcessing": [
"Store",
"Organise",
"Use"
],
"hasExpiryTime": 150
},
"d3aConsent": {
"model": "D3Aeeg",
"hasPurpose": [
"ResearchAndDevelopment"
],
"hasProcessing": [
"Store",
"Organise",
"Use"
],
"hasExpiryTime": 123
}
}
```
- Response:
```json
{
"version": "1.0.0",
"match": TRUE,
"messages": []
}
```
</details>
<details><summary>Example B</summary>
```json
{
"ontology": "https://soya.ownyourdata.eu/OntologyEEG",
"d2aConsent": {
"model": "D2Aeeg",
"hasPurpose": [
"PublicBenefit",
"ResearchAndDevelopment",
"ServiceProvision"
],
"hasProcessing": [
"Store",
"Use"
],
"hasExpiryTime": 15
},
"d3aConsent": {
"model": "D3Aeeg",
"hasPurpose": [
"ResearchAndDevelopment"
],
"hasProcessing": [
"Store",
"Organise",
"Use"
],
"hasExpiryTime": 123
}
}
```
- Response:
```json
{
"version": "1.0.0",
"match": TRUE,
"messages": [
"For the usage class hasProcessing, the value Organise is requested by the consumer but not covered by the provider",
"The d2a value for hasExpiryTime must be greater than the one for d3a"
]
}
```
</details>
- `PUT /api/match`
```json
### Checking Service
Service to see for a d2a what values are allowed in the d3a.
<details><summary>Example</summary>
* PUT /api/d3aChecking
```json
{
"ontology": "https://soya.ownyourdata.eu/OntologyEEG",
"d2aConsent": {
"model": "D2Aeeg",
"hasPurpose": [
"PublicBenefit",
"ResearchAndDevelopment",
"ServiceProvision"
],
"hasProcessing": [
"Store",
"Organise",
"Use"
],
"hasExpiryTime": 150
}
}
```
- Response:
```json
{
"hasPurpose":[
"PublicBenefit","ResearchAndDevelopment","ServiceProvision"
],
"hasProcessing":[
"Access","Analyse","Assess","Match","Organise","Profiling","Query","Store","Use"
],
"hasExpiryTime": {
"maximum":150
}
}
```
</details>
### Examples
<details><summary>SimpleConsent</summary>
SOyA: [`SimpleConsent`](https://soya.ownyourdata.eu/SimpleConsent/)
```bash=
echo '{
"ontology":"https://soya.ownyourdata.eu/SimpleConsent/",
"d2a-consent": {
"hasPurpose": [
"Purpose_2"
],
"hasProcessing": [
"Processing_2_2"
]
},
"d3a-consent": {
"hasPurpose": [
"Purpose"
],
"hasProcessing": [
"Processing_2"
]
}
}' | curl -H "Content-Type: application/json" -d @- \
-X PUT https://reasoner.go-data.at/api/match
```
</details>
<details><summary>EEG Use Case</summary>
SOyA: [`OntologyEEG`](https://soya.ownyourdata.eu/OntologyEEG/)
```bash=
echo '{
"ontology": "https://soya.ownyourdata.eu/OntologyEEG",
"d2a-consent": {
"model": "D2Aeeg",
"hasPurpose": [
"PublicBenefit",
"ResearchAndDevelopment",
"ServiceProvision"
],
"hasProcessing": [
"Organise",
"Store",
"Transform",
"Use"
],
"hasExpiryTime": 123
},
"d3a-consent": {
"model": "D3Aeeg",
"hasPurpose": [
"ResearchAndDevelopment"
],
"hasProcessing": [
"Store",
"Organise",
"Transform",
"Use"
],
"hasExpiryTime": 124
}
}' | curl -H "Content-Type: application/json" -d @- \
-X PUT https://reasoner.go-data.at/api/match
```
</details>
## Intermediary Integration
*Input Jakob*