How the data space works
The CitCom.ai Data Space is operated by VRAIN-UPV for the whole of CitCom and uses the FIWARE Data Space Connector (version 10), which follows the recommendations of the Data Spaces Business Alliance. This page describes its parts, the deployment running today and the four flows that make it work.
Shared services
- Trust anchor
- Keeps the Trusted Issuers Registry (TIR): the list of organisations whose credentials are trusted in the data space, by their decentralised identifier (
did:web:…). A verifier rejects any credential issued by an organisation that is not in it. - Onboarding portal
- Where an organisation asks to join. Its legal representative (LEAR) registers the organisation; once approved, it is added to the trust anchor, and the LEAR acts for it with a
LegalPersonCredential. - Marketplace
- The catalogue of offers, built on the TM Forum APIs and the BAE frontend. The LEAR of each organisation logs in with a wallet, sets up the organisation's profile, publishes offers and buys them. See Marketplace.
The deployment today
flowchart TB
subgraph OP["Operated for the whole data space"]
TA["<b>Trust anchor</b><br/>Trusted Issuers Registry"]
ON["<b>Onboarding portal</b><br/>organisations join"]
MK["<b>Marketplace</b><br/>catalogue, offers, orders"]
end
subgraph TV["Ajuntament de València · townhall-vlc"]
TVC["Connector"]
TVD[("City data<br/>VLCi + Lepus, Orion-LD")]
TVC --- TVD
end
subgraph VR["VRAIN-UPV · vrain"]
VRC["Connector"]
VRS["MIAIS<br/>AI service"]
VRC --- VRS
end
W["Wallets<br/>atesta-id-wallet, Lissi"]
ON -- "registers" --> TA
TVC -. "publishes offers" .-> MK
VRC -. "publishes offers" .-> MK
MK -- "contract on purchase" --> TVC
MK -- "contract on purchase" --> VRC
VRS == "reads waste containers<br/>MachineCredential" ==> TVC
W == "people log in<br/>ServiceCredential" ==> VRC
- Each participant runs its own connector. The diagram shows the first two: the Ajuntament de València, which provides city data, and VRAIN-UPV, which provides an AI service and consumes city data. Both are described as worked examples: Valencia and the MIAIS. New participants join the same way.
- The MIAIS reads the waste containers of Valencia through the Ajuntament's connector, after buying the offer in the marketplace. People from other organisations use the MIAIS by logging in with their wallet.
The public services are:
| Service | URL |
|---|---|
| Marketplace | https://marketplace.citcom-vrain-dataspace.eu |
| Onboarding portal | https://onboarding.citcom-vrain-dataspace.eu |
| Trust anchor (TIR) | https://tir.citcom-vrain-dataspace.eu/v4/issuers (list of trusted organisations) |
Connector of a participant <p> |
https://apisix-<p>.citcom-vrain-dataspace.eu (data and services), https://keycloak-<p>… (credentials), https://verifier-<p>… (tokens) |
Inside a connector
Every participant runs the same set of components:
flowchart LR
subgraph CON["Connector of a participant"]
direction LR
KC["<b>Keycloak</b><br/>issues credentials<br/>(OID4VCI)"]
VF["<b>Verifier</b><br/>credential → token<br/>(OID4VP)"]
TIL[("<b>Trusted Issuers List</b><br/>who may access")]
GW["<b>APISIX</b><br/>gateway"]
OPA["<b>OPA</b><br/>policy decision"]
PAP[("<b>ODRL-PAP</b><br/>access policies")]
CM["<b>contract-management</b><br/>applies purchases"]
BR[("<b>NGSI-LD broker</b><br/>Scorpio / Orion-LD / Lepus")]
VF --> TIL
GW --> OPA --> PAP
GW --> BR
CM --> TIL
CM --> PAP
end
CLIENT["Consumer"] -- "1 credential" --> VF
CLIENT -- "2 token + request" --> GW
MKT["Marketplace"] -- "completed order" --> CM
| Component | Role |
|---|---|
| Keycloak | Identity server of the organisation. Issues MachineCredential and ServiceCredential to its programs and people with OpenID for Verifiable Credential Issuance (OID4VCI), as SD-JWT credentials. |
| Verifier | Receives credentials from consumers (OpenID for Verifiable Presentations), checks them against the trust anchor and the local trust list, and returns an access token. |
| Trusted Issuers List (TIL) | The organisations allowed to access this connector, per credential type and role. Filled in when someone buys an offer. |
| APISIX | The gateway in front of the data and services. Checks the token and asks OPA for a decision on every request. |
| OPA + ODRL-PAP | The policy engine. The PAP stores ODRL policies and turns them into rules for OPA, which allows or denies each request by organisation, path, entity type and method. |
| contract-management | Listens to the marketplace. When an order for one of this participant's offers is completed, it adds the buyer to the TIL and loads the offer's policy into the PAP. |
| NGSI-LD broker | The data itself. Scorpio comes with the connector; the Ajuntament also serves its data through Orion-LD and Lepus. |
Flows
Join the data space
- The organisation's LEAR registers it in the onboarding portal.
- Once approved, the organisation's
did:webis added to the trust anchor. - The LEAR logs in to the marketplace with a wallet and completes the organisation's profile. A provider also sets the address of its contract-management there, so purchases reach its connector.
The guide Join the data space has the details.
Purchase an offer
sequenceDiagram
autonumber
actor P as Provider (LEAR)
actor C as Consumer (LEAR)
participant MK as Marketplace
participant CM as Provider contract-management
participant TIL as Provider TIL
participant PAP as Provider ODRL-PAP
P->>MK: Publish offer (credential type, roles, ODRL policy)
C->>MK: Buy offer
MK->>CM: Order completed
CM->>TIL: Trust the consumer's DID for MachineCredential, role clearence1
CM->>PAP: Load the policy (e.g. only WasteContainer under /lepus/ngsi-ld)
An offer carries two settings: which credential and roles the buyer will be allowed to present, and which policy limits what the buyer can do. Both are applied automatically when the order completes; nobody configures the connector by hand.
A machine reads data
This is how a program, such as the MIAIS, reads data from another organisation. The library ds-consumer-auth does steps 1 to 5 for you.
sequenceDiagram
autonumber
participant APP as Consumer program
participant KC as Consumer Keycloak
participant VF as Provider verifier
participant GW as Provider APISIX
participant OPA as Provider OPA
participant BR as Provider broker
APP->>KC: Log in and request a MachineCredential (OID4VCI)
KC-->>APP: Signed credential (SD-JWT)
APP->>VF: Present the credential (vp_token)
VF->>VF: Issuer in the trust anchor? Consumer in the TIL with these roles?
VF-->>APP: Access token (short-lived JWT)
APP->>GW: GET /ngsi-ld/v1/entities?type=WasteContainer + token
GW->>OPA: Allowed?
OPA-->>GW: Yes, a purchased policy matches
GW->>BR: Forward
BR-->>APP: Entities (NGSI-LD)
If the consumer has not bought any offer, step 5 fails: the verifier does not find the consumer in its TIL. If it has bought an offer but not this dataset, step 8 fails: no policy allows that entity type. See Use data from your code.
A person uses a web service
A provider can also offer a web application. People log in with a wallet instead of a password, and the provider's gateway does the login: the application needs no login code of its own.
sequenceDiagram
autonumber
actor U as Person with a wallet
participant GW as Provider APISIX
participant VF as Provider verifier
participant OPA as Provider OPA
participant APP as Web service (e.g. MIAIS)
U->>GW: Open https://apps-vrain.citcom-vrain-dataspace.eu/waste-collection/
GW-->>U: No session: redirect to the verifier
VF-->>U: QR code
U->>VF: Scan with the wallet, present the ServiceCredential
VF->>VF: Issuer trusted? Organisation bought the service, with this role?
VF-->>GW: Authorisation code → token
GW-->>U: Encrypted session cookie
U->>GW: Requests with the session
GW->>OPA: Allowed? (path /waste-collection, role)
GW->>APP: Forward
The person's organisation must have bought the service, and the person must have the role the service asks for in their ServiceCredential. See Publish a web service.
Where to go next
- Valencia: a city platform: a worked example of a city offering its data here.
- Guides: join, read data, publish a dataset or a service.
- Deploy your own connector: how a connector is deployed.