diff --git a/.gitignore b/.gitignore index eba74f4..c2679e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -venv/ \ No newline at end of file +venv/ +site/ diff --git a/docs/api/api-catalog.md b/docs/api/api-catalog.md new file mode 100644 index 0000000..98cf731 --- /dev/null +++ b/docs/api/api-catalog.md @@ -0,0 +1,29 @@ +# 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. + +## Versioning + +`eoepca:schema_version` is SemVer. Changes within a MAJOR are additive only. On a +MAJOR bump the previous schema stays at diff --git a/docs/api/endpoint-specification.md b/docs/api/endpoint-specification.md deleted file mode 100644 index cab6c29..0000000 --- a/docs/api/endpoint-specification.md +++ /dev/null @@ -1,6 +0,0 @@ -# Specification - -Details of the API specification. - -!!! warning - Work in progress... :construction_worker: diff --git a/docs/api/schema/example.json b/docs/api/schema/example.json new file mode 100644 index 0000000..77dcca1 --- /dev/null +++ b/docs/api/schema/example.json @@ -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": "0.0.1", + "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": "demo" + } + ], + + "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 + } + ] + } + ] +} diff --git a/docs/api/schema/v1.json b/docs/api/schema/v1.json new file mode 100644 index 0000000..5f0ef44 --- /dev/null +++ b/docs/api/schema/v1.json @@ -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" } + } + } + } +} diff --git a/docs/design/overview.md b/docs/design/overview.md index 566790c..e96ad83 100644 --- a/docs/design/overview.md +++ b/docs/design/overview.md @@ -1,6 +1,45 @@ # Architecture -Subcomponent architecture and interfaces. +User clients are thin orchestration layers over EOEPCA+ platform services. The +platform advertises those services through a single discovery document; clients +never embed deployment-specific URLs. -!!! warning - Work in progress... :construction_worker: +## Discovery layer + +``` + User client EOEPCA+ deployment + ─────────── ────────────────── + + 1. GET /.well-known/api-catalog + ─────────────────────────────► Linkset JSON + (rel → href + metadata) + + 2. Pick rel (workspace-api, data, openeo, …) + Read eoepca:auth, eoepca:naming, conformsTo + + 3. Authenticate via OIDC issuer link + (eoepca:default_client_id from catalog) + + 4. Call target service API + ─────────────────────────────► Workspace, STAC, OpenEO, … +``` + +The catalog is specified in [API Catalog](../api/api-catalog.md) ([schema/v1.json](../api/schema/v1.json)). + +## Design principles + +- **Rel-based lookup** — clients select services by registered `rel` URIs, not + by position or informal key names. +- **Server decides auth** — `eoepca:auth` in the catalog is a hint; a 401 from the service means you need credentials. +- **Additive evolution** — new rels and properties are MINOR changes; removing + or renaming rels is MAJOR and follows the catalog versioning rules. +- **Cache-friendly** — deployments MUST emit a stable ETag tied to + `eoepca:deployment.git_revision` so clients can revalidate cheaply. + +## Interfaces + +| Interface | Role | +|---|---| +| `/.well-known/api-catalog` | Platform → client; full service directory. | +| OIDC issuer (`openid issuer` rel) | Client ↔ Keycloak; token acquisition. | +| Per-service APIs | Client ↔ individual building blocks; discovered via catalog. | diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 9080aa1..5536a3f 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -1,6 +1,23 @@ # Quick Start -Quick start instructions - including installation, e.g. of a local instance. +Point any user client at an EOEPCA+ deployment by its apex domain. The client +fetches the [API Catalog](../api/api-catalog.md) and resolves services from there. -!!! warning - Work in progress... :construction_worker: +## Discover a deployment + +```bash +DEPLOY=https://develop.eoepca.org + +curl -sS "$DEPLOY/.well-known/api-catalog" \ + | jq '.linkset[0] | { + schema: ."eoepca:schema_version", + deployment: ."eoepca:deployment".name, + workspace: ."https://eoepca.org/rel/workspace-api"[0].href, + issuer: ."http://openid.net/specs/connect/1.0/issuer"[0].href + }' +``` + +## What to read next + +- [API Catalog](../api/api-catalog.md) — schema and serving requirements. +- [Architecture](../design/overview.md) — how discovery fits into client design. diff --git a/docs/index.md b/docs/index.md index d870e4e..81967b3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,27 +1,37 @@ # Introduction -!!! warning - Work in progress... :construction_worker: +The **User Client** building block defines how tools, CLIs, and libraries +discover and interact with an EOEPCA+ deployment. Instead of baking in hostnames +or URL patterns, clients start from a single well-known entry point and follow +typed links to each service. -The documentation for the `` building block is organised as follows... +## About User Client -* **Introduction**
- Introduction to the BB - including summary of purpose and capabilities. -* **Getting Started**
- Quick start instructions - including installation, e.g. of a local instance. -* **Design**
- Description of the BB design - including its subcomponent architecture and interfaces. -* **Usage**
- Tutorials, How-tos, etc. to communicate usage of the BB. -* **Administration**
- Configuration and maintenance of the BB. -* **API**
- Details of APIs provided by the BB - including endpoints, usage descriptions and examples etc. +An EOEPCA+ deployment exposes many APIs (workspace, catalogue, processing, +OpenEO, object storage, identity, …) across different subdomains and auth modes. +User clients need a stable contract for: -## About `` +- finding the correct base URL for each capability, +- knowing which authentication flow applies, +- adapting to deployment-specific naming (e.g. workspace prefixes). -Description of the purpose of the BB. +That contract is the **[API Catalog](api/api-catalog.md)** at +`/.well-known/api-catalog` — a Linkset document keyed by standard and EOEPCA+ +relation types. ## Capabilities -Summary of the capabilities of the BB. +- **Service discovery** — resolve endpoints by `rel`; [schema](api/schema/v1.json) defines extension properties. +- **Auth hints** — `eoepca:auth` on each link; if missing, try unauthenticated first — a 401 from the service means auth is required. +- **Deployment metadata** — schema version, environment, and revision via + `eoepca:deployment` for cache invalidation and support diagnostics. + +## Documentation map + +| Section | Contents | +|---|---| +| [Getting Started](getting-started/quick-start.md) | Install a client and point it at a deployment. | +| [Design](design/overview.md) | How discovery fits into client architecture. | +| [Usage](usage/tutorials.md) | Tutorials and how-tos for common tasks. | +| [Administration](admin/configuration.md) | Configuration for operators serving the catalog. | +| [API](api/api-catalog.md) | API Catalog specification and schema. | diff --git a/mkdocs.yml b/mkdocs.yml index c9c0d02..dcb78f6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,11 +1,11 @@ -site_name: EOEPCA Document Template -site_url: https://eoepca.readthedocs.io/projects/template/ -repo_url: https://github.com/EOEPCA/document-template/ +site_name: EOEPCA User Client +site_url: https://eoepca.readthedocs.io/projects/user-client/ +repo_url: https://github.com/EOEPCA/user-client/ edit_uri: "edit/main/docs/" nav: - EOEPCA Documentation: https://eoepca.readthedocs.io/ - - Building-block Name: + - User Client: - index.md - Getting Started: - getting-started/quick-start.md @@ -20,7 +20,7 @@ nav: - admin/configuration.md - admin/maintenance.md - API: - - api/endpoint-specification.md + - api/api-catalog.md - api/usage.md # Footer links