Identidad de styx: login OIDC ligado al navegador con sesión por cookie (vía el BFF), refresh de clientes nativos, logout con CSRF, revocación de sesiones y resolución del principal de un access token. Publica las claves de firma (JWKS) con las que los servicios verifican los tokens en local. ## 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.
JWKS (RFC 7517) con las claves con las que identity-svc firma los access tokens. Cacheable 5 min; por el bus el mismo contenido es qry.identity.jwks.
application/json
curl -X GET "https://example.com/.well-known/jwks.json"{ "keys": [ { "alg": "string", "crv": "string", "kid": "string", "kty": "string", "use": "string", "x": "string" } ]}Revoca todas las sesiones del actor indicado. Exige rol admin y un login reciente (401 reauth-required si no).
Acceso: Bearer de identity con policy role:admin, con login reciente.
bearerAuth 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
1 <= length <= 128application/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/auth/admin/actors/string/revoke"{ "revoked": 0}Revoca la sesión indicada de cualquier actor. Exige rol admin y un login reciente (401 reauth-required si no).
Acceso: Bearer de identity con policy role:admin, con login reciente.
bearerAuth 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
uuidapplication/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/auth/admin/sessions/497f6eca-6276-4993-bfeb-53cbbbba6f08/revoke"Autenticado. Los scopes finales son lo pedido ∩ lo que el aprobador puede; un dispositivo nunca recibe más que quien lo aprueba. El CSRF lo exige el BFF de la web (la ruta sólo acepta Bearer, sin credencial ambiente).
Acceso: Bearer de identity con policy authenticated.
bearerAuth 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
TypeScript Definitions
Use the request body type in TypeScript.
items <= 644 <= length <= 16application/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/auth/device/approve" \ -H "Content-Type: application/json" \ -d '{ "userCode": "string" }'{ "decision": "approved"}Anónimo, con límite por IP y tope global de pendientes. Devuelve device_code (secreto del dispositivo), user_code de 8 dígitos y la página de verificación de la web. Acepta application/x-www-form-urlencoded y JSON. Errores en formato OAuth.
TypeScript Definitions
Use the request body type in TypeScript.
1 <= length <= 64Value in
^[^\u0000-\u001f\u007f-\u009f]+$1 <= length <= 64length <= 1024application/json
application/json
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
curl -X POST "https://example.com/auth/device/code" \ -H "Content-Type: application/json" \ -d '{ "client_id": "string", "device_name": "string" }'{ "device_code": "string", "expires_in": 1, "interval": 1, "user_code": "string", "verification_uri": "string", "verification_uri_complete": "string"}Acceso: Bearer de identity con policy authenticated.
bearerAuth 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
TypeScript Definitions
Use the request body type in TypeScript.
4 <= length <= 16application/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/auth/device/deny" \ -H "Content-Type: application/json" \ -d '{ "userCode": "string" }'{ "decision": "approved"}Autenticado. Cuenta como intento contra la sesión y la cuenta (5/min, 20/h por defecto). Una credencial pat no puede.
Acceso: Bearer de identity con policy authenticated.
bearerAuth 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
4 <= length <= 16application/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 GET "https://example.com/auth/device/lookup?user_code=string"{ "clientId": "string", "deviceKind": "string", "deviceName": "string", "expiresAt": 0, "requestIp": "string", "requestedAt": 0, "requestedScopes": [ "string" ], "userCode": "string"}Sondea con el device_code. authorization_pending / slow_down / access_denied / expired_token como errores OAuth (400). Aprobado: access JWT (cred=device) + refresh opaco de dec-0113, una sola vez.
TypeScript Definitions
Use the request body type in TypeScript.
1 <= length <= 641 <= length <= 128application/json
application/json
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
curl -X POST "https://example.com/auth/device/token" \ -H "Content-Type: application/json" \ -d '{ "client_id": "string", "device_code": "string", "grant_type": "urn:ietf:params:oauth:grant-type:device_code" }'{ "access_token": "string", "expires_in": 1, "refresh_token": "string", "scope": "string", "token_type": "Bearer"}Las más recientes primero, con su estado, usos y las cuentas creadas.
Acceso: Bearer de identity con policy resource:invitation:read.
bearerAuth 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
Value in
1 <= value <= 100application/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 GET "https://example.com/auth/invitations"{ "invitations": [ { "createdAt": 0, "createdBy": "string", "email": "string", "expiresAt": 0, "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "maxUses": 1, "note": "string", "redeemedBy": [ "string" ], "revokedAt": 0, "role": "restricted", "status": "active", "uses": 0 } ]}Caducidad obligatoria (tope IDENTITY_INVITE_MAX_TTL_S), rol restricted o member (admin y owner nunca por invitación) y, opcional, ligada a un email. El token sólo se devuelve aquí; identity guarda su hash.
Acceso: Bearer de identity con policy resource:invitation:create, con login reciente.
bearerAuth 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
Invitación de un solo uso con caducidad obligatoria.
TypeScript Definitions
Use the request body type in TypeScript.
Invitación de un solo uso con caducidad obligatoria.
Liga la invitación a un email: el id_token del login debe traerlo igual.
emaillength <= 25460 <= value <= 2592000length <= 200Value in
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/auth/invitations" \ -H "Content-Type: application/json" \ -d '{ "expiresInS": 60 }'{ "invitation": { "createdAt": 0, "createdBy": "string", "email": "string", "expiresAt": 0, "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "maxUses": 1, "note": "string", "redeemedBy": [ "string" ], "revokedAt": 0, "role": "restricted", "status": "active", "uses": 0 }, "token": "string"}Público y con el rate-limit por IP de /auth/*. Un token mal formado, inexistente o revocado da el mismo error (sin oráculo); sólo quien tiene un token válido ve que caducó o se agotó. No devuelve datos personales.
Token a inspeccionar sin consumirlo.
TypeScript Definitions
Use the request body type in TypeScript.
Token a inspeccionar sin consumirlo.
^styx_inv_[A-Za-z0-9_-]{43}$length <= 52application/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/auth/invitations/preview" \ -H "Content-Type: application/json" \ -d '{ "token": "string" }'{ "emailBound": true, "expiresAt": 0, "role": "restricted"}Acceso: Bearer de identity con policy resource:invitation:read.
bearerAuth 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
uuidapplication/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 GET "https://example.com/auth/invitations/497f6eca-6276-4993-bfeb-53cbbbba6f08"{ "createdAt": 0, "createdBy": "string", "email": "string", "expiresAt": 0, "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "maxUses": 1, "note": "string", "redeemedBy": [ "string" ], "revokedAt": 0, "role": "restricted", "status": "active", "uses": 0}Idempotente. No afecta a las cuentas ya creadas con ella; borrarlas es una operación aparte.
Acceso: Bearer de identity con policy resource:invitation:create, con login reciente.
bearerAuth 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
uuidapplication/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 DELETE "https://example.com/auth/invitations/497f6eca-6276-4993-bfeb-53cbbbba6f08"Acceso: Bearer de identity con policy resource:api-key:list.
bearerAuth 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
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
curl -X GET "https://example.com/auth/keys"{ "keys": [ { "createdAt": 0, "displayPrefix": "string", "expiresAt": 0, "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "lastUsedAt": 0, "name": "string", "revokedAt": 0, "scopes": [ "string" ] } ]}Scopes obligatorios y ⊆ permisos actuales del creador; caducidad obligatoria con tope. Una credencial pat no puede crear keys. Sólo se guarda el SHA-256.
Acceso: Bearer de identity con policy resource:api-key:create, con login reciente.
bearerAuth 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
TypeScript Definitions
Use the request body type in TypeScript.
60 <= value1 <= length <= 641 <= items <= 64application/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/auth/keys" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "scopes": [ "string" ] }'{ "key": { "createdAt": 0, "displayPrefix": "string", "expiresAt": 0, "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "lastUsedAt": 0, "name": "string", "revokedAt": 0, "scopes": [ "string" ] }, "token": "string"}Una key ajena o inexistente es 404 (sin oráculo).
Acceso: Bearer de identity con policy resource:api-key:revoke.
bearerAuth 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
uuidapplication/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 DELETE "https://example.com/auth/keys/497f6eca-6276-4993-bfeb-53cbbbba6f08"Cliente nativo: refresh token en el body. Navegador: cookie de sesión más CSRF de doble barrera (Sec-Fetch-Site u Origin exacto, y el token CSRF de la sesión); responde 204 con Clear-Site-Data.
sessionCookie Cookie de sesión del navegador. Sólo la acepta identity-svc en /auth/logout, con CSRF de doble barrera; llega a través del BFF.
In: cookie
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/auth/logout"Valida el callback contra el login sellado en la cookie de binding, crea la sesión de navegador y redirige a returnTo con la cookie __Host-styx_sess. Si falla, borra la cookie de binding.
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 GET "https://example.com/auth/oidc/callback"{ "category": "transient", "code": "IDENTITY_INVALID_INPUT", "detail": "string", "instance": "string", "retryable": true, "status": 400, "title": "string", "type": "string"}Prepara el login (PKCE, state y nonce sellados en la cookie de binding __Host-styx_login) y redirige al OP. returnTo tiene que pertenecer a un origen de la web. Con invite, la invitación se comprueba sin consumirla, viaja sellada con el login y se canjea en el callback (dec-0125 §7.3).
urllength <= 2048Token de invitación (dec-0125 §7.3): se valida sin consumirlo, viaja sellado en el login pendiente y se canjea de forma atómica en el callback.
^styx_inv_[A-Za-z0-9_-]{43}$length <= 52application/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 GET "https://example.com/auth/oidc/start?returnTo=string"{ "category": "transient", "code": "IDENTITY_INVALID_INPUT", "detail": "string", "instance": "string", "retryable": true, "status": 400, "title": "string", "type": "string"}Sólo clientes nativos: refresh token en el body JSON. Una petición con la cookie de sesión del navegador se rechaza (el navegador nunca recibe access tokens). Un refresh token ya rotado que vuelve a presentarse se rechaza (IDENTITY_REFRESH_TOKEN_REUSED) y queda en el audit.
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
curl -X POST "https://example.com/auth/refresh"{ "accessToken": "string", "expiresAt": 0, "refreshToken": "string", "tokenType": "Bearer"}Devuelve el principal del access token tras verificarlo en local y contra la sesión viva.
Acceso: Bearer de identity con policy authenticated.
bearerAuth 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
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
curl -X GET "https://example.com/auth/session"{ "actorId": "string", "authTime": 0, "cred": "browser", "displayName": "string", "expiresAt": 0, "role": "restricted", "scopes": [ "string" ], "sessionId": "string"}Revoca todas las sesiones del actor del token, también la actual.
Acceso: Bearer de identity con policy resource:actor:revoke-sessions.
bearerAuth 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
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
curl -X POST "https://example.com/auth/sessions/revoke-all"{ "revoked": 0}La key se presenta en subject_token (nunca en la URL). Rechaza con IDENTITY_KEY_IN_BROWSER_CONTEXT cualquier canje con Cookie, Origin o Sec-Fetch-*. El JWT lleva cred=pat y scp; caduca en ≤ 5 min y el principal se resuelve contra la key viva (revocarla corta el acceso en la siguiente resolución).
TypeScript Definitions
Use the request body type in TypeScript.
1 <= length <= 128application/json
application/json
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
curl -X POST "https://example.com/auth/token" \ -H "Content-Type: application/json" \ -d '{ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "subject_token": "string", "subject_token_type": "urn:styx:token-type:api-key" }'{ "access_token": "string", "expires_in": 1, "scope": "string", "token_type": "Bearer"}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).
application/json
curl -X GET "https://example.com/health"{ "status": "ok", "timestamp": 0, "uptime": 0, "version": "string"}Prueba cada dependencia registrada con un plazo de 3 s. 503 si falla alguna crítica; las no críticas sólo se informan.
application/json
application/json
curl -X GET "https://example.com/ready"{ "checks": [ { "critical": true, "error": "string", "name": "string", "ok": true } ], "status": "ready"}curl -X GET "https://example.com/version"{ "commit": "string", "component": "string", "train": "string", "version": "string"}Hijos de un work (serie → episodio, disco → pista…) GET
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.
Claves públicas (JWKS) para verificar los access tokens de identity GET
JWKS (RFC 7517) con las claves con las que identity-svc firma los access tokens. Cacheable 5 min; por el bus el mismo contenido es qry.identity.jwks.