Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
venv/
.venv/
site/
50 changes: 50 additions & 0 deletions docs/api/api-catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# API Catalog

Every EOEPCA+ deployment exposes a machine-readable directory of its services at
`/.well-known/api-catalog`. User clients treat this as the only supported way to
discover endpoints, authentication, and deployment metadata, they MUST NOT
hard-code service URLs or assume a fixed hostname layout.

[RFC 9727](https://www.rfc-editor.org/rfc/rfc9727) well-known URI,
[RFC 9264](https://www.rfc-editor.org/rfc/rfc9264) Linkset JSON
(`application/linkset+json`). Services are link targets keyed by link relation
type (`rel`); relation URIs and extension properties are in
[schema/v1.json](schema/v1.json).

- **Schema:** [schema/v1.json](schema/v1.json)
- **Example:** [schema/example.json](schema/example.json), reference deployment to inspect or validate against

```bash
check-jsonschema --schemafile docs/api/schema/v1.json docs/api/schema/example.json
```

Deployments MUST serve a document that validates against the current schema.
Clients SHOULD fetch `service-desc` from the catalog for the live schema URL.
Look services up by `rel`. Absent `eoepca:auth`, means unauthenticated access
is possible.

!!! note
The develop deployment does not serve `/.well-known/api-catalog` yet;
[schema/example.json](schema/example.json) is the reference document until it does.

## Selecting among multiple targets

A `rel` may list several targets (e.g. `data` carries both an open resource
catalogue and a transactional eoAPI STAC). Clients that need write access
SHOULD prefer the target whose `conformsTo` includes a STAC API core
conformance class and whose `eoepca:auth` is `oidc-write`, falling back to the
first STAC-conformant target otherwise.

## Known service behaviours

- eoAPI on develop only accepts tokens issued for the `eoapi` OIDC client
(`eoepca:default_client_id` above); tokens from other clients are rejected
with 401.
- eoAPI answers item `DELETE` with `200` and a JSON body rather than `204`.

## Versioning

`eoepca:schema_version` is SemVer. Changes within a MAJOR are additive only. On a
MAJOR bump the previous schema stays available at its versioned URL
(e.g. `/schemas/discovery/v1.json`) and the new one is published alongside it;
deployments state the version they implement in `eoepca:schema_version`.
6 changes: 0 additions & 6 deletions docs/api/endpoint-specification.md

This file was deleted.

182 changes: 182 additions & 0 deletions docs/api/schema/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
{
"$schema": "https://eoepca.org/schemas/discovery/v1.json",

"linkset": [
{
"anchor": "https://develop.eoepca.org/.well-known/api-catalog",
"profile": [
"https://www.rfc-editor.org/info/rfc9727",
"https://eoepca.org/profiles/discovery/v1"
],

"eoepca:schema_version": "1.0.0",
"eoepca:description": "EOEPCA+ reference deployment on CloudFerro.",
"eoepca:attribution": "ESA / EOEPCA+",
"eoepca:deployment": {
"name": "EOEPCA+ Develop",
"environment": "develop",
"git_revision": "a1b2c3d",
"generated_at": "2026-06-03T08:14:00Z"
},

"self": [
{
"href": "https://develop.eoepca.org/.well-known/api-catalog",
"type": "application/linkset+json",
"profile": "https://www.rfc-editor.org/info/rfc9727"
}
],
"service-desc": [
{
"href": "https://eoepca.org/schemas/discovery/v1.json",
"type": "application/schema+json"
}
],
"service-doc": [
{
"href": "https://eoepca.readthedocs.io/",
"type": "text/html"
}
],

"http://openid.net/specs/connect/1.0/issuer": [
{
"href": "https://iam-auth.develop.eoepca.org/realms/eoepca",
"title": "Keycloak",
"service-desc": "https://iam-auth.develop.eoepca.org/realms/eoepca/.well-known/openid-configuration",
"eoepca:realm": "eoepca",
"eoepca:default_client_id": "eoapi"
}
],

"https://eoepca.org/rel/workspace-api": [
{
"href": "https://workspace-api.develop.eoepca.org",
"type": "application/json",
"title": "Workspace API",
"eoepca:auth": "oidc",
"eoepca:api_version": "2.1",
"eoepca:naming": { "pattern": "ws-{username}", "prefix": "ws" }
}
],

"data": [
{
"href": "https://resource-catalogue.develop.eoepca.org",
"type": "application/json",
"title": "Resource catalogue (open)",
"conformsTo": [
"https://api.stacspec.org/v1.0.0/core",
"https://api.stacspec.org/v1.0.0/item-search",
"http://www.opengis.net/spec/ogcapi-records-1/1.0/conf/core"
],
"eoepca:auth": "none"
},
{
"href": "https://resource-catalogue-protected.develop.eoepca.org",
"type": "application/json",
"title": "Resource catalogue (protected)",
"eoepca:auth": "oidc-uma"
},
{
"href": "https://eoapi.develop.eoepca.org/stac",
"type": "application/json",
"title": "eoAPI STAC",
"conformsTo": [
"https://api.stacspec.org/v1.0.0/core",
"https://api.stacspec.org/v1.0.0/item-search"
],
"eoepca:auth": "oidc-write",
"eoepca:api_version": "1.0.0"
},
{
"href": "https://eoapi.develop.eoepca.org/vector",
"type": "application/json",
"title": "eoAPI vector (TiPg)",
"conformsTo": ["http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core"]
}
],

"https://eoepca.org/rel/harvester": [
{
"href": "https://registration-harvester-api.develop.eoepca.org/flowable-rest",
"type": "application/json",
"title": "Harvester (Flowable)",
"eoepca:engine": "flowable"
}
],

"http://www.opengis.net/def/rel/ogc/1.0/processes": [
{
"href": "https://zoostd.develop.eoepca.org/ogc-api",
"type": "application/json",
"title": "Processing (ZOO-DRU standard)",
"eoepca:flavor": "zoo-dru-std",
"eoepca:auth": "oidc-uma",
"eoepca:api_version": "OGC API Processes Part 1 / 1.0"
},
{
"href": "https://zookeda.develop.eoepca.org/ogc-api",
"type": "application/json",
"title": "Processing (ZOO-DRU KEDA)",
"eoepca:flavor": "zoo-dru-keda",
"eoepca:auth": "oidc-uma",
"eoepca:api_version": "OGC API Processes Part 1 / 1.0"
}
],

"https://eoepca.org/rel/openeo": [
{
"href": "https://eoapi.develop.eoepca.org/openeo",
"type": "application/json",
"title": "TiTiler-OpenEO",
"eoepca:backend_id": "titiler-openeo",
"eoepca:api_version": "1.2.0"
},
{
"href": "https://openeofed.develop.eoepca.org",
"type": "application/json",
"title": "OpenEO Federation",
"eoepca:backend_id": "federation",
"eoepca:role": "aggregator",
"eoepca:api_version": "1.2.0"
}
],

"https://eoepca.org/rel/datacube-access": [
{
"href": "https://datacube-access.develop.eoepca.org",
"type": "text/html",
"title": "Datacube Access"
}
],

"https://eoepca.org/rel/resource-health": [
{
"href": "https://resource-health.develop.eoepca.org",
"type": "text/html",
"title": "Resource Health",
"eoepca:apis": { "healthchecks": "/api/healthchecks/v1", "telemetry": "/api/telemetry/v1" }
}
],

"https://eoepca.org/rel/notifications": [
{
"href": "https://notifications.develop.eoepca.org",
"type": "application/json",
"title": "CloudEvents broker",
"eoepca:knative_subdomain": "na.develop.eoepca.org"
}
],

"https://eoepca.org/rel/s3": [
{
"href": "https://minio.develop.eoepca.org",
"title": "MinIO S3 endpoint",
"eoepca:region": "eoepca-demo",
"eoepca:virtual_hosting": false
}
]
}
]
}
106 changes: 106 additions & 0 deletions docs/api/schema/v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eoepca.org/schemas/discovery/v1.json",
"title": "EOEPCA+ API Catalog (RFC 9727)",
"description": "Schema for the document at `/.well-known/api-catalog`. RFC 9727 well-known URI, RFC 9264 Linkset format (`application/linkset+json`). Service URLs are link targets keyed by `rel`.",
"type": "object",
"required": ["linkset"],
"additionalProperties": true,
"properties": {
"$schema": { "type": "string", "format": "uri" },
"linkset": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/LinkContext" },
"contains": {
"type": "object",
"required": ["anchor"],
"properties": {
"anchor": { "type": "string", "pattern": "/\\.well-known/api-catalog$" }
}
}
}
},
"$defs": {
"LinkContext": {
"type": "object",
"required": ["anchor"],
"properties": {
"anchor": { "type": "string", "format": "uri" },
"profile": {
"type": ["string", "array"],
"items": { "type": "string", "format": "uri" }
},
"eoepca:schema_version": { "type": "string", "pattern": "^1\\.[0-9]+\\.[0-9]+$" },
"eoepca:description": { "type": "string" },
"eoepca:attribution": { "type": "string" },
"eoepca:deployment": { "$ref": "#/$defs/Deployment" }
},
"additionalProperties": { "$ref": "#/$defs/TargetArray" }
},
"TargetArray": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/Target" }
},
"Target": {
"type": "object",
"required": ["href"],
"additionalProperties": true,
"properties": {
"href": { "type": "string", "format": "uri-reference" },
"type": { "type": "string" },
"title": { "type": "string" },
"profile": {
"type": ["string", "array"],
"items": { "type": "string", "format": "uri" }
},
"service-desc": { "type": "string", "format": "uri" },
"conformsTo": {
"type": "array",
"items": { "type": "string", "format": "uri" }
},
"eoepca:auth": { "$ref": "#/$defs/AuthMode" },
"eoepca:api_version": { "type": "string" },
"eoepca:realm": { "type": "string" },
"eoepca:default_client_id": { "type": "string" },
"eoepca:naming": { "$ref": "#/$defs/NamingPattern" },
"eoepca:engine": { "type": "string", "enum": ["flowable", "operaton", "camunda"] },
"eoepca:flavor": { "type": "string", "enum": ["zoo-dru-std", "zoo-dru-keda", "zoo-dru-wes"] },
"eoepca:backend_id": { "type": "string" },
"eoepca:role": { "type": "string", "enum": ["backend", "aggregator"] },
"eoepca:region": { "type": "string" },
"eoepca:virtual_hosting": { "type": "boolean" },
"eoepca:knative_subdomain": { "type": "string" },
"eoepca:apis": {
"type": "object",
"additionalProperties": { "type": "string" }
}
}
},
"AuthMode": {
"type": "string",
"enum": ["none", "oidc", "oidc-write", "oidc-uma"],
"description": "none: open. oidc: bearer required. oidc-write: open for GET/HEAD/OPTIONS. oidc-uma: bearer + UMA ticket."
},
"NamingPattern": {
"type": "object",
"required": ["pattern"],
"additionalProperties": true,
"properties": {
"pattern": { "type": "string" },
"prefix": { "type": "string" }
}
},
"Deployment": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": { "type": "string" },
"environment": { "type": "string" },
"git_revision": { "type": "string" },
"generated_at": { "type": "string", "format": "date-time" }
}
}
}
}
Loading
Loading