1. Introduction
This specification defines the Aggregator Protocol, an HTTP-based interface that lets a client create and manage Aggregator Instances and configure Aggregator Services that execute data transformations.
Transformations are described and discovered using the Function Ontology (FnO) [FNO]; a service is configured by referencing a transformation (or execution graph) and providing its inputs, after which the client can retrieve the derived result from the service’s advertised location.
TODO clarify whether Aggregator Services may reference transformations not advertised in the server/instance transformation catalogs, and how servers validate and authorize execution of arbitrary FnO graphs.
Clients start from the Aggregator Server Description at the server base URL to discover the registration endpoint, supported registration flows, and the server’s transformation catalog (§ 4 Aggregator Server Metadata). Using the registration endpoint, a client creates (or manages) an Aggregator Instance (§ 5.1 Aggregator Registration Endpoint) and then follows the instance’s Aggregator Description to find the instance’s service collection and transformations endpoint (§ 7.1 Aggregator Description and § 8 Aggregator Service Management).
All management operations are authenticated and authorized. This protocol integrates with OAuth 2.0 / OpenID Connect [OIDC-Core] for identity and uses UMA-style authorization [UMA] for protected resources, scopes, and tickets as described in § 6 Aggregator Security Model (Authentication & Authorization).
Servers MUST support JSON (application/json) where specified and MAY additionally provide semantically annotated RDF representations (e.g., JSON-LD or Turtle) via HTTP content negotiation.
The Aggregator vocabulary (§ 9 Vocabulary) provides stable IRIs for classes and predicates used throughout the specification.
2. Definitions
This section defines terminology used throughout this specification. Where applicable, terms are aligned with external specifications such as WebID Profiles, OpenID Connect (OIDC) [OIDC-Core], OAuth 2.0 [RFC6749], and User-Managed Access (UMA) [UMA].
2.1. Core Roles and Components
-
Client: An application acting on behalf of an end-user to create Aggregator Instances and configure Aggregator Services.
-
Aggregator Server: The server deployment that exposes public discovery metadata and a registration API used to create and manage Aggregator Instances.
-
Aggregator Instance (often shortened to “Aggregator”): A user- or tenant-scoped logical instance created via the registration endpoint. An instance exposes an Aggregator Description and an authenticated management API for configuring services.
-
Aggregator Service (or “Service”): A configured data processing pipeline inside an Aggregator Instance. A service references a transformation/execution graph and exposes a
locationwhere the derived result can be retrieved (see § 8 Aggregator Service Management). -
Transformation Catalog: A catalog that describes the transformations supported by the Aggregator Server or Aggregator Instance (see § 4.3 Public Transformation Catalog and § 7.2 Transformations Endpoint).
2.2. Identity, Authorization, and Tokens
-
User (End-user): A person or agent that owns or controls resources and uses a Clienbt to configure an Aggregator deployment.
-
WebID: An HTTP(S) IRI that identifies an agent and can be dereferenced to obtain a WebID Profile document as defined in [WEBID-PROFILE].
-
Identity Provider (IdP): An OpenID Connect Provider following the SOLID-OIDC spec ([SOLID-OIDC]) that authenticates a user based on it’s WebID Profile ([WEBID-PROFILE]) and issues ID tokens used by this protocol during registration and authorization workflows.
-
Authorization Server (AS): An OAuth 2.0 Authorization Server that supports UMA as defined in ([A4DS]) and issues Requesting Party Tokens (RPTs) for protected resources.
-
Resource Server (RS): An HTTP server that hosts protected resources. In UMA terminology, a Resource Server protects resources and interacts with an Authorization Server to obtain UMA tickets and validate RPTs.
-
UMA Ticket: A value returned in a
WWW-Authenticate: UMA ...challenge when a client requests a protected resource without sufficient authorization. The client presents the ticket to the Authorization Server to obtain an RPT. -
Requesting Party Token (RPT): An OAuth 2.0 bearer token issued by an Authorization Server under UMA that encodes permissions/scopes for a protected resource (see [RFC6750]).
-
ID Token: An OpenID Connect ID token representing the authenticated user (and, depending on the deployment, the client). The protocol uses ID tokens as claim tokens in UMA exchanges and during registration flows as described in § 6 Aggregator Security Model (Authentication & Authorization).
-
Client Identifier Document: A dereferenceable client metadata document that provides the
client_idvalue and associated OpenID Connect Dynamic Client Registration metadata as required by the deployment (see § 4.2 Client Identifier Document).
2.3. Namespaces
The following namespace prefixes are used throughout this specification and SHOULD appear in RDF serializations (e.g., Turtle, JSON-LD contexts):
-
aggr:→https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/# -
dct:→http://purl.org/dc/terms/ -
fno:→https://w3id.org/function/ontology# -
rdf:→http://www.w3.org/1999/02/22-rdf-syntax-ns# -
xsd:→http://www.w3.org/2001/XMLSchema#
3. Architecture & Resource Model
This section describes the high-level architecture of an Aggregator deployment and the resource model exposed by this specification. It connects the terminology in § 2 Definitions to the endpoint definitions in later sections.
3.1. Actors and Responsibilities
The protocol distinguishes the following parties:
-
Client: An application acting on behalf of an end-user to create Aggregator Instances and configure Aggregator Services.
-
Aggregator Server: The server that exposes public discovery information and a registration API to create Aggregator Instances.
-
Aggregator Instance: A user-specific (or tenant-specific) logical instance created via registration, exposing instance metadata and a management API.
-
Aggregator Service: A configured data-processing pipeline created and managed within an Aggregator Instance.
-
Identity Provider (IdP): Issues OIDC tokens used to prove identity as part of registration and upstream authorization flows.
-
Authorization Server (AS): A UMA-capable OAuth2 Authorization Server that issues RPTs for protected resources.
-
Resource Server (RS): An upstream resource server hosting data that the Aggregator Service may access on behalf of the user.
3.2. Resource Types
This specification defines HTTP resources at three levels:
-
Aggregator Server resources: metadata and instance registration (see § 4 Aggregator Server Metadata and § 5.1 Aggregator Registration Endpoint).
-
Aggregator Instance resources: instance metadata and service management (see § 7 Aggregator Metadata and § 8 Aggregator Service Management).
-
Aggregator Service resources: a service collection and individual services managed under the instance (see § 8.1 Service Collection and § 8.2 Service Resource).
3.3. Base URLs and Addressing
An implementation MUST define a stable base URL for:
-
the Aggregator Server (the
aggregator-server-url); and -
each Aggregator Instance (the
aggregator-url).
All paths in this specification are expressed relative to either the server base URL or the instance base URL:
-
Server-relative resources: the server metadata resource at
{aggregator-server-url}/(see § 4 Aggregator Server Metadata) and the discovery endpoints it links to, such as a registration API (e.g.,{aggregator-server-url}/registration/; see § 5 Aggregator Management), the Client Identifier Document, and the public transformation catalog (see § 4.2 Client Identifier Document and § 4.3 Public Transformation Catalog). -
Instance-relative resources: the instance metadata resource at
{aggregator-url}/(see § 7 Aggregator Metadata) and the management endpoints that the instance advertises (e.g.,{aggregator-url}/services; see § 8 Aggregator Service Management).
An implementation MAY use either of the following instance addressing patterns:
-
Host-based instances:
https://{instance-id}.aggregator.example/ -
Path-based instances:
https://aggregator.example/{instance-id}/
If an implementation supports multiple patterns, it MUST ensure that URLs returned in representations are self-consistent for a given instance (i.e., all links for that instance share the same instance base URL). Clients SHOULD treat server-provided URLs as authoritative and avoid constructing URLs by string concatenation. Unless a path is explicitly fixed, the concrete URLs shown in this document serve as illustrative defaults; deployments MAY use different locations as long as the relevant metadata resources advertise the authoritative links.
3.4. Discovery and Entry Points
-
The Aggregator Server exposes a public discovery resource at its server base URL (see § 4.1 Aggregator Server Description).
-
Clients create (or obtain access to) an Aggregator Instance via the registration API (see § 5.1 Aggregator Registration Endpoint).
-
The resulting instance base URL is the entry point for instance metadata (see § 7 Aggregator Metadata) and instance management (see § 8 Aggregator Service Management).
3.5. Security Boundaries
All security requirements are defined in § 6 Aggregator Security Model (Authentication & Authorization). At a high level:
-
Public (no authentication): the server metadata resource (see § 4.1 Aggregator Server Description) and the resources it links to, such as the transformation catalog and Client Identifier Document (see § 4.3 Public Transformation Catalog and § 4.2 Client Identifier Document).
-
Protected (UMA): the instance metadata resource (see § 7 Aggregator Metadata) and all resources under the management API (see § 8 Aggregator Service Management).
TODO clarify the boundary between the Aggregator Instance (management API) and the Aggregator Service output resources (the location URLs), including whether outputs are always protected by the same Authorization Server and UMA policies.
3.6. Example URL Layout (Non-normative)
Given an Aggregator Server at https://aggregator.example/ and a path-based Aggregator instance at https://aggregator.example/abc123/:
-
Server metadata:
https://aggregator.example/ -
Registration:
https://aggregator.example/registration -
Transformation catalog:
https://aggregator.example/transformations -
Instance metadata:
https://aggregator.example/abc123/ -
Instance Transformation catalog:
https://aggregator.example/abc123/config/transformations -
Service collection:
https://aggregator.example/abc123/config/services
4. Aggregator Server Metadata
This section describes the public endpoints exposed by the Aggregator Server for discovery and metadata retrieval. Except for the Aggregator Server Description at the server base URL, implementations MAY expose the remaining endpoints at deployment-specific URLs; the server description document MUST include absolute URLs for each resource so that clients can discover them.
4.1. Aggregator Server Description
The Aggregator Server Description is a public metadata document that allows clients to discover the Aggregator Server’s endpoints and capabilities.
This document MUST be available at the server base URL (i.e., {aggregator-server-url}/), MUST be accessible without authentication, and MUST provide at least the following information.
Each JSON member is paired with an RDF predicate from § 9 Vocabulary so the document can also be served as JSON-LD or other RDF formats using content negotiation based on [RFC9110]:
In semantically annotated representations, the Aggregator Server Description MUST state that the described resource has RDF type aggr:AggregatorServer (§ 9.1.3 aggr:AggregatorServer) (e.g., via @type in JSON-LD or a aggr:AggregatorServer in Turtle).
Clients MAY rely on this type statement when consuming semantic representations.
- registration_endpoint (REQUIRED):
-
The value is a string containing the absolute URL of the Aggregator Registration Endpoint (§ 5.1 Aggregator Registration Endpoint); in the RDF representations, this member maps to the predicate
aggr:registrationEndpoint(§ 9.2.11 aggr:registrationEndpoint). - supported_registration_types (REQUIRED):
-
The value is a JSON array of strings identifying the supported registration flow tokens at
registration_endpoint; in the RDF representations, each entry maps to anaggr:supportedRegistrationTypetriple (§ 9.2.12 aggr:supportedRegistrationType) whose object is the corresponding flow class IRI.Each member MUST be one of the registration flow tokens defined in § 5.1 Aggregator Registration Endpoint:
-
"provision"(RDF classaggr:ProvisionFlow(§ 9.1.7 aggr:ProvisionFlow)) -
"authorization_code"(RDF classaggr:AuthorizationCodeFlow(§ 9.1.8 aggr:AuthorizationCodeFlow)) -
"client_credentials"(RDF classaggr:ClientCredentialsFlow(§ 9.1.9 aggr:ClientCredentialsFlow)) -
"device_code"(RDF classaggr:DeviceCodeFlow(§ 9.1.10 aggr:DeviceCodeFlow))
- version (REQUIRED):
-
The value is a string containing the version of the Aggregator specification that the server adheres to; in the RDF representations, this member maps to the predicate
aggr:specVersion(§ 9.2.13 aggr:specVersion). - client_identifier (REQUIRED):
-
The value is a string containing the absolute URL of the Client Identifier Document (§ 4.2 Client Identifier Document); in the RDF representations, this member maps to the predicate
aggr:clientIdentifier(§ 9.2.14 aggr:clientIdentifier). - transformation_catalog (REQUIRED):
-
The value is a string containing the absolute URL of the Public Transformation Catalog (§ 4.3 Public Transformation Catalog); in the RDF representations, this member maps to the predicate
aggr:transformationCatalog(§ 9.2.15 aggr:transformationCatalog).
{ "@context" : { "aggr" : "https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#" , "provision" : "aggr:ProvisionFlow" , "authorization_code" : "aggr:AuthorizationCodeFlow" , "client_credentials" : "aggr:ClientCredentialsFlow" , "device_code" : "aggr:DeviceCodeFlow" , "registration_endpoint" : { "@id" : "aggr:registrationEndpoint" , "@type" : "@id" }, "supported_registration_types" : { "@id" : "aggr:supportedRegistrationType" , "@type" : "@vocab" }, "version" : { "@id" : "aggr:specVersion" }, "client_identifier" : { "@id" : "aggr:clientIdentifier" , "@type" : "@id" }, "transformation_catalog" : { "@id" : "aggr:transformationCatalog" , "@type" : "@id" } }, "@id" : "https://aggregator.example/" , "@type" : "aggr:AggregatorServer" , "registration_endpoint" : "https://aggregator.example/registration" , "supported_registration_types" : [ "provision" , "authorization_code" ], "version" : "1.0.0" , "client_identifier" : "https://aggregator.example/client.json" , "transformation_catalog" : "https://aggregator.example/transformations" }
4.2. Client Identifier Document
Endpoint that exposes the client identifier of the aggregator used for authorization.
Servers MAY host this document at any URL; the client_identifier property in the Aggregator Server Description MUST contain the authoritative absolute URL.
The Client Identifier Document MUST conform to the Solid specification [SOLID-OIDC] and uses the fields from the OpenID Connect Dynamic Client Registration specification [OIDC-Registration].
Only for the aggregator the redirect_uris property is OPTIONAL instead of required, as multiple clients can create an Aggregator on the same Aggregator Server.
Adding this property can allow an Aggregator Server implementation to restrict which clients can create aggregators on the server.
4.3. Public Transformation Catalog
This endpoint returns a RDF document describing the transformations supported by the aggregator server on a server level.
Servers MAY publish this catalog at any deployment-specific URL; the Aggregator Server Description MUST advertise it via the transformation_catalog field.
This RDF document SHOULD be exposed using content negotiation based on HTTP.
The transformations MUST be described using FnO [FNO].
@prefix aggr: <https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#> . @prefix trans: <http://aggregator.example.org/transformations#> . @prefix fno: <https://w3id.org/function/ontology#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <> a aggr : TransformationCollection ; dct : title "Aggregator transformations" ; aggr : hasTransformation trans : AggregateSources . aggr : hasTransformation trans : AggregateSources2 . trans : AggregateSources a fno : Function ; fno : name "A Aggregator Service that combines a list of sources" ^^ xsd : string ; fno : expects ( trans : Sources ) ; fno : returns ( trans : Result ) . trans : Sources a fno : Parameter ; fno : predicate trans : sources ; fno : type rdf : List ; fno : required "true" ^^ xsd : boolean . trans : Result a fno : Output ; fno : predicate trans : result ; fno : type xsd : string .
The specificity of the transformation is up to the server owner.
The transformations CAN have a link to a implementation with fno:Implementation if needed.
External FnO functions MAY be used using rdfs:seeAlso.
Pre defined pipelines MAY be used using fno:Compositions.
TODO how do we allow an aggregator that can run any transformation?
5. Aggregator Management
This section describes how Aggregator Instances are managed at the Aggregator Server level. Deployments define their own authorization policy for these endpoints, but they MUST require authenticated requests so the Aggregator provider can authorize a user to manage their aggregators. The tokens used in these requests (IDP_client_token) prove the identity of the user and the client (Client Identifier) used to access the Aggregator Server.
All representations defined in this section MUST be accessible as JSON using application/json.
Servers MAY additionally expose semantically annotated RDF representations (for example JSON-LD or Turtle) using HTTP content negotiation based on [RFC9110].
Deployments MAY expose the same functionality at different paths, provided that the Aggregator Server Description advertises the authoritative URLs.
5.1. Aggregator Registration Endpoint
This section specifies the behavior of theregistration_endpoint advertised by the Aggregator Server Description (§ 4.1 Aggregator Server Description).
The endpoint supports creating Aggregator Instances, replacing the stored token set for an existing instance, and deleting an instance.
The endpoint MUST reject unauthenticated requests with 401 Unauthorized.
TODO specify whether and how IDP_client_token can be sender-constrained (e.g., DPoP).
POST-
Creates an Aggregator Instance or replaces the stored token set for an existing instance. The request body MUST be a JSON object with
Content-Type: application/jsonand MUST include:-
registration_type (REQUIRED): The value is a string token; it MUST be one of the
supported_registration_typesadvertised in the Aggregator Server Description (§ 4.1 Aggregator Server Description). The following string tokens are defined, each corresponding to an RDF class in the Aggregator vocabulary (§ 9 Vocabulary) for semantically annotated representations:-
"provision"↔aggr:ProvisionFlow(§ 9.1.7 aggr:ProvisionFlow) -
"authorization_code"↔aggr:AuthorizationCodeFlow(§ 9.1.8 aggr:AuthorizationCodeFlow) -
"client_credentials"↔aggr:ClientCredentialsFlow(§ 9.1.9 aggr:ClientCredentialsFlow) -
"device_code"↔aggr:DeviceCodeFlow(§ 9.1.10 aggr:DeviceCodeFlow)
-
-
aggregator_id (string, OPTIONAL): When present, the request targets an existing Aggregator Instance and the server MUST replace its stored access token and refresh token with a new set obtained from the Identity Provider (IdP). This is not a refresh-token grant; it is a full re-authentication to obtain a fresh access token and refresh token.
Depending on
registration_type, additional members are defined:-
registration_type: "provision"
-
No additional members are required. ISSUE: TODO specify that the Aggregator Server should register an account at the IdP for the new WebID, and a account at an Authorization Server for UMA to manage aggregator resource permissions.
-
-
registration_type: "authorization_code"
-
authorization_server (string, REQUIRED): URL of the UMA Authorization Server that governs the user’s resources.
The
authorization_codeflow has twoPOSTmessages:-
Start request (bootstraps PKCE [RFC7636]): The request MUST NOT include
code,redirect_uri, orstate. The server MUST respond with201 Createdand a JSON object containing:-
client_id (string, REQUIRED): The client identifier (dereferenceable client metadata document).
-
code_challenge (string, REQUIRED)
-
code_challenge_method (string, REQUIRED)
-
state (string, REQUIRED) The server MAY also include IdP discovery hints (for example
issuerorauthorization_endpoint) if the client cannot determine them through other means.
-
-
Finish request (redeems the authorization code): The request MUST include:
-
code (string, REQUIRED): The authorization code issued by the IdP.
-
redirect_uri (string, REQUIRED): The redirect URI used in the authorization request.
-
state (string, REQUIRED): The
statereturned by the start request.
-
-
-
registration_type: "client_credentials"
-
authorization_server (string, REQUIRED): URL of the UMA Authorization Server that governs the user’s resources.
-
webid (string, REQUIRED): The WebID that the Aggregator Instance should act as.
-
client_id (string, REQUIRED)
-
client_secret (string, REQUIRED)
-
-
registration_type: "device_code"
-
Not specified.
-
For successful
POSTrequests that create/update an Aggregator Instance (i.e.,provision,client_credentials, and theauthorization_codefinish request), the server MUST respond with:-
201 Createdwhen it created a new Aggregator Instance (i.e., noaggregator_idwas provided). -
200 OKwhen it replaced the token set for an existing Aggregator Instance (i.e.,aggregator_idwas provided).
For successful
POSTrequests that create/update an Aggregator Instance (i.e., all types except theauthorization_codestart request), the response MUST be a JSON object and MUST include:-
aggregator_id (string, REQUIRED): Opaque identifier for the Aggregator Instance (used for subsequent management operations).
-
authorization_server (string, OPTIONAL): Included when relevant for the registration type.
The response SHOULD also include:
-
aggregator (string, OPTIONAL): Absolute URL of the Aggregator Instance base URL that dereferences to the Aggregator Description (§ 7.1 Aggregator Description).
The server MUST NOT return any IdP access tokens, refresh tokens, or client credentials to the client.
-
DELETE-
Deletes an existing Aggregator Instance. The request MUST include
Authorization: Bearer <IDP_client_token>. The request body MUST be a JSON object withContent-Type: application/jsonand MUST include:-
aggregator_id (string, REQUIRED): Opaque identifier for the Aggregator Instance to delete.
If deletion succeeds the server MUST respond with
204 No Content. -
For error conditions, the server MUST respond with:
-
400 Bad Requestfor malformed JSON or missing/invalid request members for the selectedregistration_type. -
401 Unauthorizedwhen the request is missing authentication or when theIDP_client_tokenis invalid. -
403 Forbiddenwhen the authenticated user is not allowed to manage the requested Aggregator Instance. -
404 Not Foundwhenaggregator_idis provided but does not identify an existing Aggregator Instance.
5.2. Aggregator Management Flows (Non-normative)
This section gives non-normative examples of how a client can use theregistration_endpoint to create, delete, and re-authenticate an Aggregator Instance.
5.2.1. Creation provision Flow
The provision flow allows clients to create an Aggregator with its own identity.
This lets resource owners target access-control policies at the aggregator’s dedicated WebID instead of having the aggregator impersonate another user’s WebID.
1. Client starts flow with Aggregator Server
The client calls the registration endpoint authenticated with its IDP_client_token.
POST /registration HTTP / 1.1 Authorization : Bearer <IDP_client_token> Content-Type : application/json { "registration_type" : "provision" }
2. Aggregator Server provisions a WebID and registers it at the IDP
The Aggregator Server creates a WebID document that conforms to the WebID Profile specification [WEBID-PROFILE] and registers a new account with an IDP for that WebID.
Using the credentials of this new account the Aggregator Server CAN perform a client credentials flow to obtain the IDP_aggregator_token (and accompanying refresh token) to authorize the aggregator acting under its own WebID.
3. Aggregator Server creates an aggregator
Using the obtained tokens, the Aggregator Server creates an aggregator linked to the user, and returns the aggregator description (§ 7.1 Aggregator Description). The aggregator SHOULD NOT give these tokens or client credentials to the client.
5.2.2. Creation authorization_code Flow
The authorization_code flow allows clients to create an aggregator that acts on behalf of the end-user, but with a token that is scoped specifically for the aggregator.
1. Client starts flow with Aggregator Server
The client begins by asking the Aggregator to bootstrap an authorization_code registration and indicate which authorization server should be used. The Aggregator responds with the public parameters required for the OIDC authorization request.
POST /registration HTTP / 1.1 Authorization : Bearer <IDP_client_token> Content-Type : application/json { "registration_type" : "authorization_code" , "authorization_server" : "https://as.example" }
1.1 Aggregator dereferences the WebID to discover the IDP
Using the UMA authorization context, the Aggregator dereferences the user’s WebID profile document to locate the Solid/OIDC issuer metadata and determine which IDP endpoints must be used for the next steps.
1.2 Aggregator responds with public parameters
After finishing WebID discovery and storing the PKCE verifier/state, the Aggregator returns the public parameters required for the IDP authorization request.
HTTP / 1.1 201 Created Content-Type : application/json { "client_id" : "https://aggregator.example/client.jsonld" , "code_challenge" : "1uLSZp2..." , "code_challenge_method" : "S256" , "state" : "1eb7c8f5..." }
The Aggregator generates the PKCE verifier/challenge pair plus a random state, persists them together with the pending registration, and returns only the public portions (client_id, code_challenge, state) to the client application.
The authorization_server value identifies the UMA Authorization Server (AS) that governs resource policies; once the Aggregator evaluates the user’s authorization token it can dereference its WebID and determine which Identity Provider (IDP) must be used for the subsequent OIDC exchange.
2. Client sends the end-user through the IDP authorization endpoint
Using the information supplied by the Aggregator, the client constructs an authorization request against the Identity Provider.
The redirect_uri is under control of the client application and MUST already be registered in the JSON-LD client metadata document hosted at the dereferenceable client_id.
GET https://idp.example/authorize?
response_type=code&
client_id=https%3A%2F%2Faggregator.example%2Fclient.jsonld&
redirect_uri=https%3A%2F%2Fapp.example%2Fcallback&
scope=openid%20webid%20offline_access&
code_challenge=1uLSZp2...&
code_challenge_method=S256&
state=1eb7c8f5...
3. User authenticates and consents at the IDP
The IDP performs its usual login and consent screens, after which it issues an authorization_code tied to the Aggregator’s confidential client.
4. IDP redirects the user agent back to the client’s redirect_uri
HTTP / 1.1 302 Found Location : https://app.example/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=1eb7c8f5...
5. Client posts the authorization code back to the Aggregator
The client sends the code, redirect URI, and echoed state to the registration endpoint so the Aggregator can finish the flow.
POST /registration HTTP / 1.1 Authorization : Bearer <IDP_client_token> Content-Type : application/json { "registration_type" : "authorization_code" , "code" : "SplxlOBeZQQYbYS6WxSbIA" , "redirect_uri" : "https://app.example/callback" , "state" : "1eb7c8f5..." }
5.1 Aggregator dereferences the client metadata
The Aggregator dereferences the client_id JSON-LD document to confirm the registered redirect URIs, contact metadata, and other security requirements, then verifies that the supplied redirect_uri belongs to that set and that the returned state matches the stored nonce.
5.2 Aggregator redeems the authorization code at the IDP token endpoint
POST /token HTTP / 1.1 Host : idp.example Content-Type : application/x-www-form-urlencoded Authorization : Basic <aggregator-client-auth> grant_type = authorization_code & code = SplxlOBeZQQYbYS6WxSbIA & redirect_uri = https%3A%2F%2Fapp.example%2Fcallback & client_id = https%3A%2F%2Faggregator.example%2Fclient.jsonld & code_verifier = Hjs8...stored...
The IDP verifies the authorization_code, ensures the redirect_uri matches the original authorization request, and recomputes the PKCE challenge from the supplied code_verifier. If everything matches, it returns:
HTTP / 1.1 200 OK Content-Type : application/json { "access_token" : "<IDP_aggregator_token>" , "refresh_token" : "<refresh_token>" , "token_type" : "Bearer" , "expires_in" : 3600 }
5.3 Aggregator finalizes the account and responds
Using the issued tokens, the Aggregator creates the aggregator account linked to the user and returns the aggregator description (§ 7.1 Aggregator Description).
HTTP / 1.1 201 Created Content-Type : application/json { "aggregator_id" : "agg-7890" , "authorization_server" : "https://as.example" , "aggregator" : "https://aggregator.example/aggregators/agg-7890/" }
5.2.3. Creation client_credentials Flow
The client_credentials flow allows clients to create an aggregator by using the OAuth2 Client Credentials Flow to obtain an OIDC token from an Identity Provider (IDP) server.
NOTE: This flow gives the aggregator complete access to the user’s resources and policies without user consent. This flow should only be used in trusted environments, or when a user creates an account for the aggregator.
1. Client starts flow with Aggregator Server
The client explicitly asks the Aggregator to act with full credentials for the provided WebID, indicating which UMA Authorization Server manages the protected resources. Because this flow hands the Aggregator long-lived client credentials, it should only be used when the user intentionally provisions the Aggregator as a trusted service account.
POST /registration HTTP / 1.1 Authorization : Bearer <IDP_client_token> Content-Type : application/json { "registration_type" : "client_credentials" , "authorization_server" : "https://as.example" , "webid" : "https://user.example/webid#me" , "client_id" : "aggregator-service-account" , "client_secret" : "s3cr3t-client-secret" }
2. Aggregator Server performs client credentials grant with the IDP
The Aggregator uses the supplied client_id/client_secret (plus the WebID context) to authenticate against the Identity Provider’s token endpoint and runs an OAuth 2.0 client_credentials grant to mint an IDP_aggregator_token scoped to the user’s WebID.
POST /token HTTP / 1.1 Host : idp.example Content-Type : application/x-www-form-urlencoded Authorization : Basic <aggregator-client-auth> grant_type = client_credentials & webid = https%3A%2F%2Fuser.example%2Fwebid%23me & scope = openid%20webid%20offline_access
The IDP issues access and refresh tokens that grant the Aggregator the same capabilities as the user’s own credentials.
HTTP / 1.1 200 OK Content-Type : application/json { "access_token" : "<IDP_aggregator_token>" , "refresh_token" : "<refresh_token>" , "token_type" : "Bearer" , "expires_in" : 7200 }
3. Aggregator Server creates (or updates) the aggregator account
Armed with the IDP_aggregator_token, the Aggregator persists the account for the specified WebID, associates it with the requesting user, and returns the aggregator description (§ 7.1 Aggregator Description) to the client.
5.2.4. Creation device_code Flow
This flow is not yet specified.
5.2.5. Token Update Flow
This flow allows users to replace the stored access token and refresh token for an existing Aggregator Instance. This is not a refresh-token grant: even refresh tokens can expire, so the client repeats the original registration flow to obtain a new set of tokens (and refresh tokens) for the Aggregator Instance.
The flow is the same as creating an Aggregator Instance but an aggregator_id member is provided in the start request.
The exact steps depend on the registration_type used when creating the Aggregator Instance.
For example, for the authorization_code flow:
POST /registration HTTP / 1.1 Authorization : Bearer <IDP_client_token> Content-Type : application/json {"registration_type" : "authorization_code" , "aggregator_id" : "agg-7890" }
5.2.6. Aggregator Deletion Flow
This flow allows users to delete an existing Aggregator Instance by sending a DELETE request to the registration_endpoint with the aggregator_id member.
DELETE /registration HTTP / 1.1 Authorization : Bearer <IDP_client_token> Content-Type : application/json {"aggregator_id" : "agg-7890" }
6. Aggregator Security Model (Authentication & Authorization)
This section describes how the Aggregator handles authentication and authorization for:
-
outgoing requests from the Aggregator to upstream Resource Servers; and
-
incoming requests from Clients to the Aggregator.
The Aggregator relies on the Authorization for Data Spaces (A4DS) specification [A4DS] to authenticate Clients and authorize access to resources. For streaming or non-HTTP interfaces, the Aggregator MAY additionally use the Service Authorization for Data Spaces (SA4DS) specification [SA4DS]. All Aggregator endpoints are protected using User-Managed Access (UMA) [UMA].
NOTE: The following behavior extends the A4DS specification and is intended to be incorporated in a future version of A4DS.
TODO we should maybe split this up into a normative section and a non-normative explanation with sequence diagrams.
6.1. Upstream Access (Requesting)
TODO: how does the Aggregator tell the Authorization Server (AS) which transformation it intends to perform on the data?
Equipped with an identity token (ID token) from an Identity Provider (IdP) as described in § 5.1 Aggregator Registration Endpoint, the Aggregator Service follows the Authorization for Data Spaces (A4DS) specification to obtain access tokens for upstream Resource Servers.
1. Requesting the upstream resource without token
The Aggregator Service requests the upstream resource without an access token. If the resource is protected with UMA, the Upstream Resource Server responds with a 401 Unauthorized status and a UMA ticket.
1.1 Upstream Resource Server requests ticket from Upstream Authorization Server
The Upstream Resource Server requests a UMA ticket from its Upstream Authorization Server.
1.2 Upstream Resource Server returns ticket
The Upstream Resource Server returns the UMA ticket to the Aggregator Service.
HTTP / 1.1 401 Unauthorized WWW-Authenticate : UMA realm="solid", as_uri="https://upstream.as.example.org/uma", ticket="tkt-URS"
2. Requesting an access token from the Upstream Authorization Server
Using the ID token obtained from the IdP during registration, the Aggregator Service requests an access token from the Upstream Authorization Server (of the Upstream Resource Server).
In this request, the Aggregator Service SHOULD request the additional scope urn:knows:uma:scopes:derivation-creation to enable the Aggregator functionality.
The Upstream Authorization Server MAY require additional claims to issue the access token.
TODO: if this resource has already been requested, the Upstream Authorization Server already has a derivation_resource_id for this Aggregator. Does the Aggregator need to request a new one, or can it reuse the existing one?
POST /token HTTP / 1.1 Host : upstream.as.example.org Content-Type : application/json {"grant_type" : "urn:ietf:params:oauth:grant-type:uma-ticket" , "ticket" : "tkt-URS" , "scope" : "urn:knows:uma:scopes:derivation-creation" , "claim_tokens" : [ { "claim_token" : "<IDP_aggregator_token>" , "claim_token_format" : "http://openid.net/specs/openid-connect-core-1_0.html#IDToken" } ] }
2.1 Upstream Authorization Server validates the ID token
The Upstream Authorization Server validates the ID token with the Identity Provider that issued it.
2.2 Upstream Authorization Server returns access token and derivation resource identifier
Adding the derivation-creation scope signals to the Authorization Server that the Aggregator intends to create a derived resource based on the requested upstream resource.
The Authorization Server MUST then include a derivation_resource_id in the response.
The derivation_resource_id is a unique identifier that the Aggregator will use to reference this upstream resource when creating derived resources.
The Authorization Server can link this identifier to the Aggregator’s identity to manage and track derived resources.
HTTP / 1.1 200 OK Content-Type : application/json {"access_token" : "<upstream_access_token>" , "derivation_resource_id" : "handle-id-1" }
3. Accessing the upstream resource with token
The Aggregator Service then requests the resource from the Upstream Resource Server using the access token obtained from the Upstream Authorization Server. This access token MAY be used multiple times until it expires or is revoked.
4. Resource registration of the Aggregator Service
Finally, the Aggregator Service MUST update the resource registration at its own Authorization Server to signal that it used this derivation_resource_id to create derived resources.
The Authorization Server MUST expire all previous access tokens for this resource.
PUT /resource-registration/agg-service-123 HTTP / 1.1 Host : as.example.org Content-Type : application/json {"resource_id" : "agg-service-123" , "resource_relations" : { "prov:wasDerivedFrom" : [ { "issuer" : "https://as.example.org" , "derivation_resource_id" : "handle-id-1" } ] } }
If a resource isn’t used anymore by the Aggregator Service, the Aggregator Service SHOULD update the resource registration to remove the derivation_resource_id from the prov:wasDerivedFrom relations, and MAY expire all previous access tokens for this resource.
Also the Aggregator Service SHOULD delete the resource from its Upstream Resource Server, by following the Resource ID deletion procedure.
6.2. Client Access (Serving)
When a Client requests access to resources from the Aggregator Service, the Aggregator Service acts as a Resource Server and relies on UMA to authorize access. For each incoming request:
-
The Client sends a request for a (derived) resource to the Aggregator Service, with or without a valid access token.
-
The Aggregator Service requests a UMA ticket for that resource from its Authorization Server and, if necessary, returns a
401 Unauthorizedresponse containing the ticket to the Client. -
The Client interacts with the Aggregator Authorization Server (and, if required, upstream Authorization Servers) to obtain the access tokens needed to access the derived resource.
-
Once authorization succeeds, the Client retries the request to the Aggregator Service with a valid access token, and the Aggregator Service returns the derived resource.
1. Client requests derived resource from Aggregator Service without token The Client sends a request to the Aggregator Service for a derived resource without including a valid Requesting Party Token (RPT), or with an RPT that does not grant sufficient permission.
When a Client requests access to a derived resource from the Aggregator Service, a normal UMA flow follows.
1.1 Aggregator Service requests UMA ticket from its Authorization Server
The Aggregator Service, acting as a UMA Resource Server, requests a UMA ticket for the requested derived resource from its Authorization Server.
The Aggregator includes the internal identifier of the derived resource in the permission request.
During ticket creation, the Aggregator SHOULD validate that the derivation_resource_id used to create the derived resource is still valid.
This validation can be delegated to the Authorization Server by including the derivation_resource_id (and its issuer) in the permission request, so that the Authorization Server can verify it with the upstream Authorization Server.
If the derivation_resource_id is still valid, the Authorization Server returns a UMA ticket as usual.
If it is no longer valid (for example, because the upstream Authorization Server has removed the referenced resource), the Aggregator MUST treat the derived resource as invalid and MUST recreate the Aggregator Service (including its resource registrations).
1.2 Aggregator Service returns 401 Unauthorized with ticket
If the Client did not present a valid RPT, or if the RPT does not cover the requested permission, the Aggregator Service returns a 401 Unauthorized response containing the UMA ticket issued by its Authorization Server.
HTTP / 1.1 401 Unauthorized WWW-Authenticate : UMA realm="aggregator", as_uri="https://agg-as.example.org/uma", ticket="tkt-A2"
2. Client presents ticket to Aggregator Authorization Server
The Client discovers the Aggregator Authorization Server (for example, via the as_uri parameter in the WWW-Authenticate header) and sends a UMA grant request to exchange the ticket for an RPT.
The Client includes any claim tokens it already has (for example, its ID token) in the request.
{ "grant_type" : "urn:ietf:params:oauth:grant-type:uma-ticket" , "ticket" : "tkt-A2" , "claim_tokens" : [ { "claim_token" : "<ID_token>" , "claim_token_format" : "http://openid.net/specs/openid-connect-core-1_0.html#IDToken" } ] }
2.1 Aggregator Authorization Server introspects Client access tokens The Aggregator Authorization Server validates the claim tokens (for example, by introspecting access tokens and/or verifying ID tokens) and evaluates its authorization policies for the requested derived resource.
2.2 Aggregator Authorization Server returns need_info (if upstream access is required)
If access to the derived resource depends on access to upstream resources, and the Client has not yet presented suitable upstream access tokens, the Aggregator Authorization Server MAY respond with a need_info error requesting additional claim tokens for the upstream resources.
In that case, the Authorization Server MUST add the issuer, derivation_resource_id, and resource_scopes entries to the required_claims array to indicate which upstream Authorization Server and which resource the Client must obtain access to.
-
**
issuer:** identifies the upstream Authorization Server. -
**
derivation_resource_id:** contains the identifier (or identifiers) provided when the Aggregator Service requested an upstream access token. -
**
resource_scopes:** list enumerates the scopes required to access the upstream resource and MUST include a derivation scope.
{ "error" : "need_info" , "ticket" : "tkt-A2" , "required_claims" : [ { "claim_token_format" : "urn:ietf:params:oauth:token-type:access_token" , "details" : { "issuer" : "https://a.example.org" , "derivation_resource_id" : "handle-id-1" , "resource_scopes" : [ "urn:knows:uma:scopes:derivation-read" ] } } ] }
3. Client requests upstream access tokens
The Client SHOULD then request access tokens from the Authorization Server of the upstream Resource Server with the required scopes, including the derivation scope indicated in the required_claims.
{ "grant_type" : "urn:ietf:params:oauth:grant-type:uma-ticket" , "permissions" : [ { "resource_id" : "handle-id-1" , "resource_scopes" : [ "urn:knows:uma:scopes:derivation-read" ] } ], "claim_tokens" : [ { "claim_token" : "<ID_token>" , "claim_token_format" : "http://openid.net/specs/openid-connect-core-1_0.html#IDToken" } ] }
4. Client presents upstream tokens to Aggregator Authorization Server Once the Client has obtained the required upstream access tokens, it sends another UMA grant request to the Aggregator Authorization Server, presenting both its ID token and the upstream access tokens as claim tokens together with the original Aggregator ticket.
{ "grant_type" : "urn:ietf:params:oauth:grant-type:uma-ticket" , "ticket" : "tkt-A2" , "claim_tokens" : [ { "claim_token" : "<ID_token>" , "claim_token_format" : "http://openid.net/specs/openid-connect-core-1_0.html#IDToken" }, { "claim_token_format" : "urn:ietf:params:oauth:token-type:access_token" , "claim_token" : "<upstream_access_token>" } ] }
The Aggregator Authorization Server MUST verify the provided access tokens with the upstream Authorization Servers to confirm that the Client is authorized to access the upstream resources. If all policy checks succeed, the Aggregator Authorization Server issues an RPT for the requested derived resource.
5. Client requests derived resource from Aggregator Service with RPT Finally, the Client retries the original request to the Aggregator Service, this time including the RPT it obtained from the Aggregator Authorization Server. The Aggregator Service validates or introspects the RPT and, if it is active and grants the required permissions, returns the derived resource to the Client.
The Aggregator MAY implement the SA4DS specification to guard endpoints with streaming or other non-HTTP based interfaces.
7. Aggregator Metadata
This endpoint provides metadata about the Aggregator Instance.
Except for the Aggregator Description (the instance base URL), deployments MAY choose arbitrary paths for other instance-level endpoints.
The Aggregator Metadata representation MUST include absolute URLs for those resources (e.g., the transformation_catalog and service_collection fields) so clients can discover the deployment-specific layout.
7.1. Aggregator Description
The Aggregator Metadata resource ({aggregator-url}) allows clients to retrieve the current status of their aggregator.
This endpoint MUST be guarded by the authentication and authorization mechanisms described in the § 6 Aggregator Security Model (Authentication & Authorization).
It MUST be accessible as JSON using application/json and MAY additionally expose semantically annotated RDF representations (for example JSON-LD or Turtle) using HTTP content negotiation based on [RFC9110].
The endpoint MUST return at least the following information about the aggregator, but additional fields MAY be included as needed. Each field SHOULD be expressed using the RDF properties defined in § 9 Vocabulary so the document MAY be served as JSON-LD or other RDF formats:
In semantically annotated representations, the Aggregator Description MUST state that the described resource has RDF type aggr:Aggregator (§ 9.1.1 aggr:Aggregator) (e.g., via @type in JSON-LD or a aggr:Aggregator in Turtle).
Clients MAY rely on this type statement when consuming semantic representations.
- id (OPTIONAL):
-
The value is a string containing the absolute URL that identifies the Aggregator Instance (typically the instance base URL itself); in the RDF representations, this is the RDF subject (i.e.,
@id) of theaggr:Aggregatorresource (§ 9.1.1 aggr:Aggregator). - created_at (REQUIRED):
-
The value is a string timestamp (recommended:
xsd:dateTimelexical form, e.g., RFC 3339 [RFC3339]); in the RDF representations, this member maps to the predicateaggr:createdAt(§ 9.2.1 aggr:createdAt). - login_status (REQUIRED):
-
The value is a boolean that indicates whether the stored token set for the aggregator is currently valid; in the RDF representations, this member maps to the predicate
aggr:loginStatus(§ 9.2.2 aggr:loginStatus). - token_expiry (OPTIONAL):
-
The value is a string timestamp indicating when the aggregator’s access token will expire (recommended:
xsd:dateTimelexical form, e.g., RFC 3339 [RFC3339]); in the RDF representations, this member maps to the predicateaggr:tokenExpiry(§ 9.2.3 aggr:tokenExpiry). - transformation_catalog (REQUIRED):
-
The value is a string containing the absolute URL of the instance’s Transformations Endpoint (§ 7.2 Transformations Endpoint); in the RDF representations, this member maps to the predicate
aggr:transformationsEndpoint(§ 9.2.4 aggr:transformationsEndpoint). - service_collection (REQUIRED):
-
The value is a string containing the absolute URL of the instance’s Service Collection (§ 8.1 Service Collection); in the RDF representations, this member maps to the predicate
aggr:servicesEndpoint(§ 9.2.5 aggr:servicesEndpoint).
This document CAN be the WebID of the Aggregator Instance when the provision flow § 5.2.1 Creation provision Flow was used.
In that case this document MUST be an RDF document that conforms to the WebID Profile specification [WEBID-PROFILE].
{ "@context" : { "id" : "@id" , "aggr" : "https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#" , "solid" : "http://www.w3.org/ns/solid/terms#" , "xsd" : "http://www.w3.org/2001/XMLSchema#" , "created_at" : { "@id" : "aggr:createdAt" , "@type" : "xsd:dateTime" }, "login_status" : { "@id" : "aggr:loginStatus" , "@type" : "xsd:boolean" }, "token_expiry" : { "@id" : "aggr:tokenExpiry" , "@type" : "xsd:dateTime" }, "transformation_catalog" : { "@id" : "aggr:transformationsEndpoint" , "@type" : "@id" }, "service_collection" : { "@id" : "aggr:servicesEndpoint" , "@type" : "@id" } }, "id" : "https://aggregator.example/aggregators/agg-7890/" , "@type" : "aggr:Aggregator" , "created_at" : "2025-12-17T17:20:00Z" , "login_status" : true , "token_expiry" : "2025-12-17T18:20:00Z" , "transformation_catalog" : "https://aggregator.example/aggregators/agg-7890/transformations" , "service_collection" : "https://aggregator.example/aggregators/agg-7890/config/services" , "solid:oidcIssuer" : "https://issuer.example/" }
7.2. Transformations Endpoint
This endpoint is the instance-level extension on the public Transformation Catalog defined in § 4.3 Public Transformation Catalog.
Implementations MAY expose it at any URL, but the Aggregator Description MUST advertise the correct location via its transformation_catalog field (aggr:transformationsEndpoint).
It allows aggregator implementations to expose user-specific transformations, or protected/private transformations.
This endpoint, contrasting to the public Transformation Catalog, MAY be user specific and MUST require authentication.
The endpoint MAY return a 404 Not Found if no user-specific transformations are available.
A client SHOULD combine the information from this endpoint with the public Transformation Catalog to get a complete view on the available transformations.
The endpoint follows the same content negotiation rules and other requirements as the public Transformation Catalog.
8. Aggregator Service Management
The Aggregator Management API gives an authenticated client a complete view on the Aggregator: it exposes the transformations that can be used to assemble a pipeline and it lets the client create, inspect, and remove concrete Aggregator Services. Implementations MAY use different URLs as long as the Aggregator Metadata document (described in § 7.1 Aggregator Description) links to the concrete entry points. All configuration routes:
-
MUST be protected by the authentication and authorization mechanisms defined in § 6 Aggregator Security Model (Authentication & Authorization); an unauthorized request MUST fail before reaching the handler.
-
MUST answer CORS preflight requests by responding to
OPTIONSwith204 No Contentand the permissiveAccess-Control-Allow-*headers shown in the reference implementation (AuthorizationMUST be listed inAccess-Control-Allow-Headers). -
MUST respond with JSON using
Content-Type: application/jsonunless explicitly stated otherwise.
8.1. Service Collection
This resource represents the collection of configured Aggregator Services.
The location of this resource is advertised in the Aggregator Description (§ 7.1 Aggregator Description) via the service_collection field.
Clients MUST treat that advertised URL as authoritative and MUST NOT assume a fixed path (the examples in this section use /services purely for illustration).
The Aggregator MUST register this UMA resource with the Authorization Server and advertise the read and create scopes so that clients can both inspect and add members.
HEAD-
Returns the collection metadata. The server MUST respond with
200 OK,Content-Type: application/json, and anETagheader whose value increases whenever a service is added or removed. TheETagallows clients to detect collection changes without re-downloading it. GET-
Returns the current list of service resources. The server MUST set the same
ETagvalue as theHEADresponse. The server MAY additionally expose semantically annotated RDF representations (for example JSON-LD or Turtle) using HTTP content negotiation based on [RFC9110]. The payload MUST be a JSON object and MUST include at least the following fields:- services (REQUIRED):
-
The value is a JSON array of strings.
Each member MUST be an absolute URL (IRI) of a Service Resource that can be dereferenced by the client.
In semantically annotated representations, this member maps to the predicate
aggr:service(§ 9.2.6 aggr:service). - id (OPTIONAL):
-
The value is a string containing the absolute URL that identifies this Service Collection (typically the same URL as the request target).
In semantically annotated representations, this is the RDF subject (i.e.,
@id) of theaggr:ServiceCollectionresource (§ 9.1.4 aggr:ServiceCollection).
{ "@context" : { "id" : "@id" , "services" : { "@id" : "aggr:service" , "@container" : "@set" , "@type" : "@id" }, "aggr" : "https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#" }, "id" : "https://aggregator.example.org/services" , "services" : [ "https://aggregator.example.org/services/410b093c-04b3-4fac-87be-4d393f40b2e5" , "https://aggregator.example.org/services/42" ] } POST-
Creates a new service. The request body MUST contain a pipeline description that references the available transformations (implementations MAY decide on the exact media type using HTTP content negotiation based on [RFC9110]).
-
Persist the new service and increment the collection
ETag. -
Register a new UMA resource for the created Service Resource URL (e.g.,
/services/{service_id}) with thereadanddeletescopes so the creator—or any other party with an RPT containing those scopes—can manage the service. -
Return
201 Created, setContent-Type: application/json, and include the full JSON representation of the service in the response body.
If the request body is invalid the server MUST respond with
400 Bad Request. Failures while instantiating the service MUST result in500 Internal Server Error. -
8.2. Service Resource
Operations on an individual service require the read and delete scopes on the Service Resource URL (e.g., /services/{service_id}).
The service URL MUST be one of the URLs returned by the collection resource; a request for a non-existent service MUST return 404 Not Found, while malformed service URLs MUST yield 400 Bad Request.
HEAD-
Returns the service metadata. The server MUST respond with
200 OKandETag, andContent-Typeheaders whose value MUST change whenever the service state changes. GET-
A JSON representation of the service SHOULD be returned with
200 OKand with aContent-Type. These representations MAY include a JSON-LD context that maps theaggr:terms defined in § 9 Vocabulary so clients can consume typed data, and content negotiation SHOULD be supported. The representation MUST include at least the following fields:- id (REQUIRED):
-
The value is a string containing the absolute URL of this Service Resource.
In semantically annotated representations, this is the RDF subject (i.e.,
@id) of theaggr:Serviceresource (§ 9.1.2 aggr:Service). - status (REQUIRED):
-
The value is a string indicating the current status of the service (e.g.,
"running","restarting","stopped", or"errored").In semantically annotated representations, this member maps to the predicate
aggr:status(§ 9.2.8 aggr:status). - transformation (REQUIRED):
-
The value is either a string containing an IRI of the transformation/execution graph, or a JSON object embedding an FnO execution description.
In semantically annotated representations, this member maps to the predicate
aggr:transformation(§ 9.2.9 aggr:transformation). - created_at (REQUIRED):
-
The value is a string timestamp (recommended:
xsd:dateTimelexical form, e.g., RFC 3339 [RFC3339]).In semantically annotated representations, this member maps to the predicate
aggr:createdAt(§ 9.2.1 aggr:createdAt). - location (REQUIRED):
-
The value is a string containing an absolute URL where the service output can be accessed.
In semantically annotated representations, this member maps to the predicate
aggr:location(§ 9.2.10 aggr:location).
DELETE-
Stops and removes the service. The Aggregator MUST stop the running pipeline, delete the persisted service entry, increment the collection
ETag, unregister the service’s UMA resource (e.g.,/services/{service_id}), and respond with200 OK. Clients that held the service identifier MUST treat it as invalid after receiving the success response.
8.3. Service Management Flows (Non-normative)
This section gives some examples on how a client can create, find, use and delete services on the Aggregator. This section is non-normative, and is only meant to illustrate the usage of the various endpoints defined in this specification. This section assumes the client has already created an Aggregator using the Aggregator Registration API (§ 5.1 Aggregator Registration Endpoint) and is able to authenticate using the mechanisms defined in § 6 Aggregator Security Model (Authentication & Authorization).
8.3.1. Creating a Service
To create a new Aggregator Service, a client starts by doing a POST request to the Service Collection endpoint (i.e., the URL advertised via service_collection in the Aggregator Description; this section uses /services as an example).
The body of the post is an execution of an FnO function [FNO]; the details will be provided later as this request fails due to missing authentication.
POST /services HTTP / 1.1 Host : aggregator.example.org Content-Type : text/turtle @prefix trans: <http://aggregator.example.org/transformations> @prefix fno: <https://w3id.org/function/ontology#> _ : execution a fno : Execution ; fno : executes trans : AggregateSources ; trans : sources ( <http://example.org/source/1> <http://example.org/source/2> ) .
The Aggregator fetches a ticket from the Authorization Server with the resource_id 1a2b-creation-endpoint it got during asset creation.
HTTP/1.1 /ticket
Host: as.example.org
Content-Type: application/json
{
"resource_id": "1a2b-creation-endpoint",
"resource_scopes": ["https://example.org/modes/create"]
}
This returns a ticket that discribes the request done to the RS (the Aggregator in this case).
This ticket is then returned to the client in a 401 Unauthorized response.
HTTP / 1.1 401 Unauthorized WWW-Authenticate : UMA realm="example", as_uri="https://as.example.org", ticket="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
The client then requests an RPT from the AS using the ticket, as defined in § 6 Aggregator Security Model (Authentication & Authorization).
The original request can then be retried, this time including the RPT in the Authorization header.
POST /services HTTP / 1.1 Host : aggregator.example.org Authorization : Bearer ey... Content-Type : text/turtle @prefix trans: <http://aggregator.example.org/transformations> @prefix fno: <https://w3id.org/function/ontology#> _ : execution a fno : Execution ; fno : executes trans : AggregateSources ; trans : sources ( <http://example.org/source/1> <http://example.org/source/2> ) .
If the request is valid, the Aggregator will create a new service, register the appropriate UMA resource, and return a 201 Created response with the service representation in the body.
HTTP / 1.1 200 OK Content-Type : text/turtle @prefix aggr: <https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#> . @prefix fno: <https://w3id.org/function/ontology#> . @prefix trans: <http://aggregator.example.org/transformations#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <https://aggregator.example.org/services/410b093c-04b3-4fac-87be-4d393f40b2e5> a aggr : Service ; aggr : status "running" ; aggr : createdAt "2024-01-01T12:00:00Z" ^^ xsd : dateTime ; aggr : location <https://example.org/410b093c-04b3-4fac-87be-4d393f40b2e5> ; aggr : transformation [ a fno : Execution ; fno : executes trans : AggregateSources ; trans : sources ( <http://example.org/source/1> <http://example.org/source/2> ) ] .
8.3.2. Discovering Services
To discover the services currently registered on the Aggregator, a client can do a GET request to the Service Collection endpoint (this section uses /services as an example).
After authenticating using the mechanisms defined in § 6 Aggregator Security Model (Authentication & Authorization), the Aggregator will return a list with the registered service from § 8.3.1 Creating a Service.
HTTP / 1.1 200 OK Content-Type : text/turtle @prefix aggr: <https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <> a aggr : ServiceCollection ; aggr : service <https://aggregator.example.org/services/410b093c-04b3-4fac-87be-4d393f40b2e5> .
Dereferencing this URL will return the full service representation.
HTTP / 1.1 201 Created Content-Type : text/turtle @prefix aggr: <https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#> . @prefix fno: <https://w3id.org/function/ontology#> . @prefix trans: <http://aggregator.example.org/transformations#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <https://aggregator.example.org/services/410b093c-04b3-4fac-87be-4d393f40b2e5> a aggr : Service ; aggr : status "running" ; aggr : createdAt "2024-01-01T12:00:00Z" ^^ xsd : dateTime ; aggr : location <https://example.org/410b093c-04b3-4fac-87be-4d393f40b2e5> ; aggr : transformation [ a fno : Execution ; fno : executes trans : AggregateSources ; trans : sources ( <http://example.org/source/1> <http://example.org/source/2> ) ] .
8.3.3. Using a Simple Service
After discovering the service, the client can use the location URL to access the output of the service.
For example, if the service produces a JSON output, the client can do a GET request to the location URL.
This will again require authentication using the mechanisms defined in § 6 Aggregator Security Model (Authentication & Authorization) to access this resource.
This time the client might need to gather multiple access claims from the AS’s of http://example.org/source/1 and http://example.org/source/2.
8.3.4. Using a Complex Service
As a complex example the resulting service could be an aggregator that combines multiple data sources into a single output stream available at the location URL.
For example we assume this results is a kafka stream.
TODO add the example flow here
9. Vocabulary
TODO ensure all example predicates/classes are defined or referenced.
The Aggregator vocabulary is defined in the aggr: namespace (https://spec.knows.idlab.ugent.be/aggregator-protocol/latest/#).
The following classes and properties are used throughout this specification.
9.1. Classes
9.1.1. aggr:Aggregator
Describes an Aggregator Instance (its base URL is the Aggregator Description resource).type: rdfs:Class
subClassOf: schema:Service
subClassOf: foaf:Agent
9.1.2. aggr:Service
Represents a configured Aggregator pipeline that can be created, inspected, and removed via the Service Management API (e.g.,/config/services/{service_id}).
type: rdfs:Class
subClassOf: prov:Activity
9.1.3. aggr:AggregatorServer
Describes the Aggregator Server Description document that advertises discovery metadata.type: rdfs:Class
subClassOf: schema:Service
9.1.4. aggr:ServiceCollection
Describes the service collection resource (e.g.,/config/services) and the metadata returned when listing configured services.
type: rdfs:Class
subClassOf: schema:Collection, hydra:Collection
9.1.5. aggr:TransformationCollection
Describes a transformation catalog resource that lists the transformations supported by an Aggregator Server (and optionally instance-specific transformations).type: rdfs:Class
subClassOf: schema:Collection, hydra:Collection
9.1.6. aggr:RegistrationFlow
Describes a registration flow supported by an Aggregator Server. This specification models each flow as an RDF class so thataggr:supportedRegistrationType can be semantically annotated by referencing the relevant flow class (e.g., aggr:ClientCredentialsFlow).
type: rdfs:Class
subClassOf: rdfs:Class
9.1.7. aggr:ProvisionFlow
Registration flow where the Aggregator Server provisions an Aggregator Instance with its own identity.type: rdfs:Class
subClassOf: aggr:RegistrationFlow
9.1.8. aggr:AuthorizationCodeFlow
Registration flow based on OAuth 2.0 Authorization Code [RFC6749] (via OpenID Connect), where the Aggregator acts on behalf of an end-user with a token scoped to the Aggregator.type: rdfs:Class
subClassOf: aggr:RegistrationFlow
9.1.9. aggr:ClientCredentialsFlow
Registration flow based on OAuth 2.0 Client Credentials [RFC6749], where the Aggregator obtains a token using user-provided long-lived client credentials.type: rdfs:Class
subClassOf: aggr:RegistrationFlow
9.1.10. aggr:DeviceCodeFlow
Registration flow based on OAuth 2.0 Device Authorization Grant [RFC8628].type: rdfs:Class
subClassOf: aggr:RegistrationFlow
9.2. Properties
9.2.1. aggr:createdAt
Timestamp when anaggr:Aggregator or aggr:Service was created.
type: rdf:Property
domain: aggr:Aggregator, aggr:Service
range: xsd:dateTime
9.2.2. aggr:loginStatus
Indicates whether the stored token set for anaggr:Aggregator is currently valid.
type: rdf:Property
domain: aggr:Aggregator
range: xsd:boolean
9.2.3. aggr:tokenExpiry
Timestamp when the current access token for anaggr:Aggregator will expire.
type: rdf:Property
domain: aggr:Aggregator
range: xsd:dateTime
9.2.4. aggr:transformationsEndpoint
Links anaggr:Aggregator to its (possibly private) transformations endpoint.
type: rdf:Property
domain: aggr:Aggregator
range: xsd:anyURI
9.2.5. aggr:servicesEndpoint
Links anaggr:Aggregator to its services endpoint.
type: rdf:Property
domain: aggr:Aggregator
range: xsd:anyURI
9.2.6. aggr:service
Links anaggr:ServiceCollection to the aggr:Service instances it advertises.
type: rdf:Property
domain: aggr:ServiceCollection
range: aggr:Service
9.2.7. aggr:hasTransformation
Links anaggr:TransformationCollection to the transformations it advertises.
type: rdf:Property
domain: aggr:TransformationCollection
range: fno:Function
9.2.8. aggr:status
Provides the lifecycle phase of anaggr:Service (values such as running, stopped, or error).
type: rdf:Property
domain: aggr:Service
range: xsd:string
9.2.9. aggr:transformation
Associates anaggr:Service with the FnO execution graph that describes how inputs are transformed.
type: rdf:Property
domain: aggr:Service
range: fno:Execution
9.2.10. aggr:location
Links anaggr:Service to the URL where its output can be accessed.
type: rdf:Property
domain: aggr:Service
range: xsd:anyURI
9.2.11. aggr:registrationEndpoint
Links anaggr:AggregatorServer to its registration endpoint.
type: rdf:Property
domain: aggr:AggregatorServer
range: xsd:anyURI
9.2.12. aggr:supportedRegistrationType
Lists the registration flows advertised by anaggr:AggregatorServer.
type: rdf:Property
domain: aggr:AggregatorServer
range: rdfs:Class (expected to be an aggr:RegistrationFlow class)
9.2.13. aggr:specVersion
States which version of this specification anaggr:AggregatorServer implements.
type: rdf:Property
domain: aggr:AggregatorServer
range: xsd:string
9.2.14. aggr:clientIdentifier
Links anaggr:AggregatorServer to the client metadata document that contains the client_id value.
type: rdf:Property
domain: aggr:AggregatorServer
range: xsd:anyURI
9.2.15. aggr:transformationCatalog
References the Aggregator Server’s public transformation catalog.type: rdf:Property
domain: aggr:AggregatorServer
range: xsd:anyURI