API

Método Ruta Propósito
GET /health Estado del backend
GET /api/v1/readiness Estado de readiness por dependencia/adapter; 503 si alguna no está lista
GET /api/v1/metrics Métricas agregadas de requests y operaciones de adapters, sin PII ni secretos
GET /api/v1/engines Capacidades, limitaciones, versión de contrato, modo y tipo de recurso
GET /api/v1/operations Catálogo versionado de operaciones, campos requeridos y capability asociada
POST /api/v1/analyses Ejecutar análisis preventivo
GET /api/v1/analyses Listado resumido heredado
GET /api/v1/analyses/history Historial filtrado, paginado y versionado
GET /api/v1/analyses/compare?first_id=&second_id= Comparación versionada de reportes compatibles
GET /api/v1/analyses/{id} Reporte completo
GET /api/v1/engines/{engine}/resources Recursos visibles para el actor
POST /api/v1/connections Registrar referencia de conexión de prueba
GET /api/v1/audit Consultar eventos de auditoría como administrador
GET /api/v1/analyses/{id}/export?format=json\|csv Exportar reporte sin secretos

El contrato se publica automáticamente en /docs y /openapi.json. El análisis recibe JSON con engine, project_id, resource y proposal. Toda ruta protegida exige Authorization: Bearer <token>. El token firmado declara sujeto, rol, proyectos, recursos, emisor, audiencia y expiración; los headers X-Actor-* no forman parte de la autenticación.

/api/v1/operations enumera las 15 operaciones del MVP. Cada entrada declara required_fields, optional_fields y la capability que el adapter debe exponer cuando la operación depende de una capacidad del motor. UI-02 consume este catálogo en vez de mantener un payload fijo; solo hace validación previa y muestra los errores de la API junto al campo. POST /api/v1/analyses devuelve 422 con la ubicación y el motivo cuando faltan campos, hay rutas inválidas o los tipos no son compatibles. Para una operación engine_specific cuyo motor no declara la capability, devuelve 400 con code: CAPABILITY_UNSUPPORTED; en ambos casos no se inspecciona el recurso.

La respuesta de /api/v1/engines incluye contract_version, limitations_version, resource_kind (document, table o unknown), mode y las listas de capacidades/limitaciones. Los snapshots internos añaden evidence_status, total_count y provenance; una evidencia incompleta no se presenta como aprobada.

/api/v1/engines/{engine}/resources devuelve databases y collections para motores documentales; Cassandra conserva su semántica de tabla mediante el campo adicional tables, indexado por keyspace. Los resultados de discovery no contienen endpoints, credenciales ni excepciones del driver.

GET /api/v1/analyses/{id}/export?format=json|csv requiere el rol reader o admin y un claim compatible con el proyecto/recurso del reporte. Devuelve 400 con EXPORT_FORMAT_UNSUPPORTED para otro formato, 403 para un rol o scope sin permiso y 404 para un identificador inexistente. JSON entrega { "export_version": "1.0", "report": ... }; CSV usa una fila por reporte, con objetos como propuesta y hallazgos serializados en columnas JSON. Ambas respuestas incluyen Content-Disposition de descarga y una redacción defensiva de claves sensibles (uri, password, token, secret, etc.).

GET /api/v1/analyses/history entrega un sobre con contract_version, items, total, limit, offset y has_more. Acepta los filtros opcionales engine, resource, actor_id, risk y outcome, además de limit (1 a 100) y offset. El endpoint anterior /api/v1/analyses permanece como lista sin paginar para no romper clientes del bootstrap; la ruta nueva es el contrato recomendado para interfaces nuevas.

GET /api/v1/analyses/compare comprueba primero la versión de contrato, motor, recurso, propuesta, modo y exactitud de la evidencia. Si falta un reporte responde 404. Si una fuente usa evidencia de muestra o incompleta, devuelve comparable: false, razones explícitas y deltas nulos; no presenta métricas no comparables como una remediación confirmada.

GET /api/v1/audit requiere el rol admin. Devuelve una página con actor_id, action, resource, outcome, correlation_id y created_at; acepta actor_id, created_from, created_to, limit y offset. Una fecha inicial posterior a la final responde 422, y un actor sin privilegio recibe 403. Los tokens ausentes, inválidos o expirados y las denegaciones autorizadas se registran sin incluir secretos. AUDIT_RETENTION_DAYS define cuántos días conserva la auditoría y REPORT_RETENTION_DAYS define cuántos días conserva el historial (predeterminado: 90 para ambos). DATABASE_URL_REF selecciona el repositorio PostgreSQL desplegable; vacío mantiene SQLite local.

La API no conoce el proveedor de persistencia: ambos implementan ReportStore. PostgreSQL aplica la migración versionada 001, índices y transacciones por operación; SQLite conserva la migración compatible para demo. El backup/restore de infraestructura y sus evidencias quedan fuera de este contrato y se documentan en OPS-03.

Ejemplos de uso local:

curl -H "Authorization: Bearer $SCHEMASAFE_TOKEN" \
  'http://localhost:8000/api/v1/analyses/<id>/export?format=json' \
  --output reporte.json

curl -H "Authorization: Bearer $SCHEMASAFE_TOKEN" \
  'http://localhost:8000/api/v1/analyses/<id>/export?format=csv' \
  --output reporte.csv

curl -H "Authorization: Bearer $SCHEMASAFE_TOKEN" \
  'http://localhost:8000/api/v1/analyses/history?engine=mongodb&limit=20&offset=0'

curl -H "Authorization: Bearer $SCHEMASAFE_TOKEN" \
  'http://localhost:8000/api/v1/analyses/compare?first_id=<id-antes>&second_id=<id-despues>'

curl -H "Authorization: Bearer $SCHEMASAFE_ADMIN_TOKEN" \
  'http://localhost:8000/api/v1/audit?actor_id=ana&limit=20'

Las interfaces UI-01 a UI-03 consumen los contratos de motores, conexión, discovery, propuesta, historial, comparación y exportación. UI-03 presenta filtros y páginas del historial, obtiene el detalle bajo demanda y muestra las razones de una comparación incompatible sin inventar deltas. Para exportar usa un token de lector autorizado y conserva el nombre seguro que entrega el servidor. Los contratos deben incluir códigos 400/401/403/404/409/422/429/5xx, correlación de solicitud, paginación y una política explícita para evidencia incompleta.

/health es liveness y no consulta motores externos. /api/v1/readiness consulta check_connection() de cada adapter, devuelve ready cuando todos responden connected o fixture-ready, y devuelve 503 con estado y detalle sanitizados cuando alguno falla. /api/v1/metrics expone solo agregados en memoria: total/errores por ruta y conteo, duración, modo y errores por operación/adapter. Los eventos de aplicación se emiten como JSON con event, correlation ID, estado, duración y conteo; no incluyen cuerpos, headers, actores, recursos ni mensajes de excepción. La guía ejecutable para operadores, troubleshooting y soporte está en DOC-02.