Operadores del admin — contratos privados
Autorización, evidencia y paginación entre el backoffice, rails y el libro.
Ámbito: Plataforma, superficie interna. Propuesta del 10-sep-2026 pendiente de promoción. Estas rutas pertenecen a los servicios privados, no al API de tenants. La especificación está en
openapi/admin-internal.yaml, referenciada desdeopenapi/tikin.yaml.
Un canal autenticado y un operador autorizado
El secreto compartido autentica al backoffice. El sub estable identifica al
operador: x-admin-actor en rails, x-ledger-actor en ledger. Rails consulta
POST /v1/admin/authorize antes de cada mutación; el ledger resuelve el actor y
sus grants vigentes en cada petición, incluso si RBAC general está en off o
log. Un lector no recibe permisos de decisión ni edición de catálogo.
| Recurso | Permiso | Alcance verificado |
|---|---|---|
| Decisión de payout | payouts.decide | Tenant obtenido del hold persistido |
| Detalle de payout | payouts.view | Hold real; devuelve tenant y ledgerHoldId |
| Catálogo de rieles | platform.rails.manage | Plataforma |
| Asignación de riel | platform.rails.assign | Tenant existente de la ruta |
| Comprobante | payouts.documents.read | Hold y UUID del documento |
| Certificado KYC | compliance.documents.read | Tenant de Identity y UUID del documento |
| Export KYC | compliance.documents.export | Tenant activo autorizado |
La respuesta ALLOW contiene actorSub, permission, tenant y resourceId;
los consumidores cotejan todos los campos aplicables. Error o timeout de la
fuente niega la acción. El ledger persiste ALLOW/DENY antes de responder a la
comprobación de permisos; una falla de auditoría nunca entrega ALLOW. La auditoría
documental incluye UUID y propósito. Las descargas leen bytes después de
comprobar pertenencia y autorización, con Cache-Control: private, no-store.
GET /v1/admin/whoami?tenant=beu incluye permisos efectivos del tenant solicitado
sin exigir un grant individual a raíz. Consultar permisos no reemplaza el guard.
Evidencia antes de captura manual
El admin persiste archivo, hash SHA-256, tamaño y autor. Comprueba la metadata
retornada antes de firmar una prueba HMAC compacta ligada a operación, referencia
bancaria y operador. evidenceToken viaja en el body de
POST /admin/retiros/{id}/aceptar.
Rails decide si requiere evidencia a partir del riel persistido. Para manual,
valida firma, propósito, pertenencia, UUID de comprobante, tamaño, hash y vigencia
(máximo 300 segundos). Registra evidencia_verificada de forma durable antes
de llamar a captura. Evidencia inválida responde 422 evidencia_requerida; falla
de persistencia no captura. La repetición de una aceptación ya aplicada no vuelve
a mover dinero.
El payload tiene purpose=manual-payout-evidence, operacionId, providerRef,
actorSub, receiptId, sha256, bytes, iat y exp. La clave se deriva del
secreto del canal con HMAC-SHA256 y dominio tikin:manual-payout-evidence:v1.
El token es base64url(JSON).base64url(HMAC(payloadBase64url)).
Páginas completas de retiros
GET /admin/retiros?limit=100 habilita el contrato nuevo. cursor es opaco;
status, q, bank, from, to, inbox=1 y aml=1 se aplican antes de
paginar. Orden: fecha descendente, UUID ascendente. Las fechas son días inclusivos
de Bogotá. Los montos siguen como texto exacto y las cuentas bancarias,
enmascaradas.
La respuesta entrega retiros, total filtrado, nextCursor o null, pending,
amlHeld y metricsScope: all. Las dos métricas cuentan todo el motor. El
contrato antiguo con limite se conserva para consumidores anteriores.
Promoción y configuración
- Promover ledger-service desde
qa, con el contrato de autorización y catálogo de permisos. ProvisionarLEDGER_ADMIN_TOKENen rails, distinto al token de tenant. - Promover rails desde
main, con autorización, evidencia y páginas; coordinar la firma de evidencia del admin antes de habilitar aceptación manual. - Promover admin con los consumidores correspondientes. La lectura documental
requiere
IDENTITY_READ_DATABASE_URLcon rol solo lectura sobre Identity; no hay fallback a tablas legacy de validación.
Los flags de acciones y las promociones pertenecen al orquestador. Publicar estos
PRs no habilita acciones ni cambia ambientes. Identity mantiene su promoción
escalonada por qa; este cambio no modifica su contrato de escritura.