Add FederationHubAPI spec, hub registration schema, FastAPI hub with SQLite persistence, reuse-surface hub CLI client, Dockerfile, and hub tests. Activate workplan; T05 deploy and T06 ops docs remain open pending railiance01 cutover.
6.4 KiB
Federation Hub API
Repository: reuse-surface
Artifact: specs/FederationHubAPI.md
Status: Draft 0.1 (REUSE-WP-0011-T01)
Schema: schemas/hub-registration.schema.yaml
1. Purpose
The federation hub is a hosted coordination service that records which repositories publish capability indexes and serves a composed federated index for agent discovery. It does not store capability entry Markdown bodies.
Companion deployment workplan: railiance-apps RAILIANCE-WP-0007.
2. Base URL and formats
| Item | Value |
|---|---|
| Default production URL | https://reuse-hub.whywhynot.de (confirm at deploy) |
| API prefix | /v1 |
| Read formats | JSON (default), YAML via Accept: application/yaml or ?format=yaml |
| Write content type | application/json |
Environment variables for clients:
| Variable | Purpose |
|---|---|
REUSE_SURFACE_HUB_URL |
Hub base URL (no trailing slash) |
REUSE_SURFACE_HUB_TOKEN |
Bearer token for write operations |
3. Authentication
| Endpoint class | Auth |
|---|---|
GET /health, GET /v1/repos, GET /v1/repos/{repo}, GET /v1/federated |
Public (read) |
POST /v1/repos, PATCH /v1/repos/{repo}, DELETE /v1/repos/{repo}, POST /v1/federated/compose |
Bearer token required |
Write requests must include:
Authorization: Bearer <REUSE_SURFACE_HUB_TOKEN>
Missing or invalid token → 401 Unauthorized.
4. Registration model
A registration mirrors federation url sources from
schemas/federation.schema.yaml, plus hub metadata:
| Field | Required | Notes |
|---|---|---|
repo |
yes | Slug [a-z][a-z0-9-]*; primary key |
url |
yes | HTTP(S) URL to capabilities.yaml |
enabled |
yes | Include in federated compose when true |
domain |
yes | e.g. helix_forge |
required |
no | Fail compose if fetch fails and no cache |
description |
no | Human-readable note |
cache_ttl_seconds |
no | Default 86400 |
auth_env |
no | Hub container env var for fetch auth (never returned in GET) |
auth_header |
no | Default Authorization |
registered_at |
hub | ISO-8601 UTC |
updated_at |
hub | ISO-8601 UTC |
registered_by |
no | Optional client-supplied actor label |
Local filesystem index paths are not accepted — registrations must use
published raw URLs.
5. Endpoints
5.1 GET /health
Liveness/readiness probe.
Response 200:
{
"status": "ok",
"service": "reuse-surface-hub",
"version": "0.1.0"
}
5.2 GET /v1/repos
List all registrations (including disabled).
Response 200:
{
"count": 2,
"repos": [
{
"repo": "reuse-surface",
"url": "https://gitea.coulomb.social/coulomb/reuse-surface/raw/main/registry/indexes/capabilities.yaml",
"enabled": true,
"required": true,
"domain": "helix_forge",
"description": "Primary registry",
"cache_ttl_seconds": 86400,
"registered_at": "2026-06-15T12:00:00Z",
"updated_at": "2026-06-15T12:00:00Z"
}
]
}
auth_env is omitted from responses.
5.3 POST /v1/repos
Register a new repository. Auth required.
Request body: registration_request from schema.
Response 201: Full registration object.
Errors:
| Code | Condition |
|---|---|
400 |
Schema validation failure |
401 |
Missing/invalid token |
409 |
repo already registered |
5.4 GET /v1/repos/{repo}
Fetch one registration.
Response 200: Registration object.
Response 404: Unknown repo.
5.5 PATCH /v1/repos/{repo}
Update fields on an existing registration. Auth required.
Request body: registration_update from schema (at least one field).
Response 200: Updated registration.
Errors: 400, 401, 404.
5.6 DELETE /v1/repos/{repo}
Remove a registration. Auth required.
Response 204: No content.
Response 404: Unknown repo.
5.7 GET /v1/federated
Return the composed federated index from all enabled registrations.
Reuses WP-0010 remote fetch/cache logic server-side. Output shape matches
registry/indexes/federated.yaml:
version: 1
updated: "2026-06-15"
domain: helix_forge
collision_policy: warn
sources:
- repo: reuse-surface
url: https://...
count: 12
capabilities:
- id: capability.registry.register
source_repo: reuse-surface
source_url: https://...
# ... index fields ...
Query parameters:
| Param | Default | Meaning |
|---|---|---|
format |
json |
json or yaml |
refresh |
false |
Bypass remote cache when true |
Warnings from compose (duplicate IDs, fetch fallbacks) are returned in response
header X-Federation-Warnings (semicolon-separated) for MVP; JSON envelope
extension is a future option.
Response 200: Federated index document.
Response 502: Required source unavailable with no cache.
5.8 POST /v1/federated/compose
Trigger federated index refresh (same as GET /v1/federated?refresh=true).
Auth required. Useful for operators after bulk registration changes.
Response 200: Federated index document.
6. Error envelope
Non-2xx responses use:
{
"error": "validation_error",
"message": "Human-readable summary",
"details": ["optional field-level messages"]
}
error code |
HTTP |
|---|---|
validation_error |
400 |
unauthorized |
401 |
not_found |
404 |
conflict |
409 |
compose_error |
502 |
7. Hub service configuration
| Env var | Required | Purpose |
|---|---|---|
REUSE_SURFACE_HUB_TOKEN |
yes | Write API bearer token |
REUSE_SURFACE_HUB_DB |
no | SQLite path (default /data/hub.db) |
REUSE_SURFACE_HUB_CACHE_DIR |
no | Remote index cache (default /data/cache) |
REUSE_SURFACE_HUB_DOMAIN |
no | Default federated domain (default helix_forge) |
8. CLI mapping
| CLI command | API call |
|---|---|
reuse-surface hub status |
GET /health |
reuse-surface hub list |
GET /v1/repos |
reuse-surface hub show --repo X |
GET /v1/repos/X |
reuse-surface hub register ... |
POST /v1/repos |
reuse-surface hub update ... |
PATCH /v1/repos/{repo} |
Global flags: --hub-url, env REUSE_SURFACE_HUB_URL, REUSE_SURFACE_HUB_TOKEN.
9. Deployment reference
- Image:
gitea.coulomb.social/coulomb/reuse-surface-hub:<tag> - Probe path:
/health - Persistence: PVC at
/data(SQLite + fetch cache) - Helm release:
railiance-appsRAILIANCE-WP-0007