catalog-svc

catalog-svc

Catálogo federado de styx (Work → Edition → MediaAsset → SourceBinding): lectura de works y sus assets reproducibles, y alta de ficheros por escaneo con los facts del motor de medios del daemon. ## Errores Todo error es un Problem Details (RFC 9457) servido como `application/problem+json`, con `type`, `title`, `status` y un `code` estable. Los errores de dominio añaden `retryable` y `category` (`transient`, `permanent` o `recoverable`). Los de framework son `400 parse` (JSON roto), `404 not-found` (ruta inexistente) y `422 validation` (con `on`; `property` y `detail` sólo fuera de producción). Las denegaciones del Bearer son `401 unauthenticated` o `reauth-required`, `403 forbidden` y `429 rate-limited` (con `Retry-After`). Ningún problem repite el valor recibido y un recurso de otro actor responde 404, sin oráculo.

GET
/health

Responde 200 mientras el proceso atiende peticiones; no comprueba dependencias. La usan el HEALTHCHECK de la imagen y el compose (con GET: HEAD es opt-in en Elysia 2).

Response Body

application/json

curl -X GET "https://example.com/health"
{  "status": "ok",  "timestamp": 0,  "uptime": 0,  "version": "string"}
GET
/kinds

Kinds registrados (los 6 audiovisuales del core y los de los plugins content-type) con su descriptor de presentación. Un cliente trata un kind que no conoce con la presentación genérica (dec-0132 §4.2).

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/kinds"
{  "kinds": [    {      "actions": [        "string"      ],      "editionKinds": [        "string"      ],      "facets": [        "string"      ],      "family": "string",      "finite": true,      "id": "string",      "label": "string",      "layouts": [        "file"      ],      "pipelines": [        "string"      ],      "relations": [        "string"      ],      "requiredFacets": [        "string"      ]    }  ]}
POST
/scan

Pide los facts del fichero al motor de medios del daemon (qry.media.probe sobre una raíz de STYX_MEDIA_ROOTS, nunca una ruta absoluta), crea o actualiza el asset y su MediaIndex y publica evt.catalog.assetIndexed. Un fichero que el motor dice que no es un medio entra como asset unidentified (indexed=false, sin índice) en vez de rechazarse. Gasta un presupuesto propio por actor (5/s, ráfaga 20) además del del servicio.

Acceso: Bearer de identity con policy resource:asset:scan.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

editionId?string
path*string
Length1 <= length
workId?string

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/scan" \  -H "Content-Type: application/json" \  -d '{    "path": "string"  }'
{  "asset": {    "container": "string",    "createdAt": 0,    "editionId": "string",    "fastHash": "string",    "id": "string",    "identification": "identified",    "kind": "logical-composition",    "layout": "file",    "path": "string",    "sizeBytes": 0,    "updatedAt": 0  },  "index": {    "assetId": "string",    "bitrateBps": 0,    "capabilities": [      "string"    ],    "container": "string",    "createdAt": 0,    "durationMs": 0,    "id": "string",    "indexVersion": 0,    "keyframesMs": [      0    ],    "streams": [      {        "bitRateBps": 0,        "channels": 0,        "codec": "string",        "defaultFlag": true,        "frameRate": 0,        "height": 0,        "index": 0,        "language": "string",        "sampleRate": 0,        "type": "video",        "width": 0      }    ]  },  "indexed": true}
GET
/version

Response Body

application/json

curl -X GET "https://example.com/version"
{  "commit": "string",  "component": "string",  "train": "string",  "version": "string"}
GET
/works

Works del catálogo federado, paginados (page desde 1, pageSize por defecto 50, máximo 200), con el total. Lectura pública de laboratorio: aún no hay bibliotecas privadas.

Query Parameters

page?integer
Range1 <= value
pageSize?integer
Range1 <= value <= 200

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/works"
{  "total": 0,  "works": [    {      "createdAt": 0,      "id": "string",      "kind": "string",      "originalTitle": "string",      "title": "string",      "updatedAt": 0,      "year": 0    }  ]}

Obtener un work

GET
/works/{id}

Un work del catálogo. 404 CATALOG_WORK_NOT_FOUND si no existe.

Path Parameters

id*string
Length1 <= length <= 128

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/works/string"
{  "work": {    "createdAt": 0,    "id": "string",    "kind": "string",    "originalTitle": "string",    "title": "string",    "updatedAt": 0,    "year": 0  }}
GET
/works/{id}/assets

Assets de las editions del work, indexados primero y luego el más reciente. indexed=false significa que el catálogo no tiene su MediaIndex: POST /sessions de playback-svc respondería PLAYBACK_NO_CAPABILITIES.

Path Parameters

id*string
Length1 <= length <= 128

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/works/string/assets"
{  "assets": [    {      "assetId": "string",      "container": "string",      "durationMs": 0,      "editionId": "string",      "facets": [        "string"      ],      "identification": "identified",      "indexed": true,      "layout": "file",      "sizeBytes": 0    }  ]}
GET
/works/{id}/relations

Relaciones padre → hijo del work ordenadas por ordinal (ruta numérica: [1, 3] = temporada 1, episodio 3). 404 CATALOG_WORK_NOT_FOUND si el work no existe.

Path Parameters

id*string
Length1 <= length <= 128

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/works/string/relations"
{  "relations": [    {      "childWorkId": "string",      "createdAt": 0,      "ordinal": [        0      ],      "parentWorkId": "string",      "rel": "string"    }  ]}