> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Operar Plugin SISBAJUD

> Configura y opera Plugin SISBAJUD: instituciones y su conector de Midaz, el canal directo, enrutamiento del ledger, órdenes que necesitan atención, rotación de la clave de credenciales, roles, listeners y restricciones de despliegue.

Esta página describe cómo configurar y operar el **Plugin SISBAJUD**. [Operar Lerian SISBAJUD](https://docs.lerian.studio/es/rails/sisbajud/sisbajud-operations.md) describe la Mensageria. [Cómo Plugin SISBAJUD ejecuta órdenes](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-how-it-works.md) describe qué hace el plugin con cada orden.

## Configuración de la institución

***

Registra cada institución en la Mensageria y en el plugin, con el mismo `institutionId`. [Operar Lerian SISBAJUD](https://docs.lerian.studio/es/rails/sisbajud/sisbajud-operations.md#institutions) describe la solicitud de la Mensageria.

`POST /v1/institutions` registra una institución en el plugin. El cuerpo tiene estos campos:

| Campo | Significado |
| - | - |
| `institutionId` | El UUID de la institución. Usa el mismo valor que en la Mensageria. |
| `connectorType` | El conector del ledger. Configúralo como `midaz`. |
| `institutionCode` | La raíz del CNPJ de la institución, de 8 dígitos. |
| `enabled` | Si la institución está activa. Envía `true`. |
| `connectorMetadata` | La configuración de Midaz de la institución. Las tablas siguientes la describen. |
| `retryPolicyConfig` | Opcional. La política de reintentos, en JSON. |
| `branchFormat` | Opcional. Una expresión regular Go RE2, de 64 caracteres como máximo, para el número de sucursal que un tribunal puede indicar en una restricción de bloqueo. |
| `accountFormat` | Opcional. Una expresión regular Go RE2, de 64 caracteres como máximo, para el número de cuenta que un tribunal puede indicar en una restricción de bloqueo. El plugin compara ese número con `bankingDetails.account` de los instrumentos del CRM, así que la restricción exige `crmMode` `embedded`. |

La solicitud también crea el keyset de tokenización y el keyset de auditoría de la institución. Una segunda solicitud con el mismo `institutionId` devuelve `409`.

El plugin se registra como dueño de la institución, a partir de su propia identidad M2M (`EXECUTOR_M2M_SUBJECT`). Ningún campo de la solicitud define el dueño, y un `PATCH` no lo cambia.

### Metadatos del conector

| Clave | Obligatorio | Significado |
| - | - | - |
| `organizations` | Sí | Una lista de entradas `{organizationId, ledgers}`: las organizaciones de Midaz en las que el plugin busca las cuentas de un sujeto. Sin `ledgers`, el plugin busca en todos los ledgers de la organización. |
| `baseUrl` | Sí | La URL base del ledger Midaz de la institución. |
| `authAddress` | Cuando hay credenciales guardadas | La dirección del Access Manager que emite el token de Midaz de la institución. |
| `blockableBalances` | Sí | Las claves de saldo de Midaz que un bloqueo puede usar, por ejemplo `default`. Son claves de saldo, no los montos `available` u `onHold`. |
| `blockableAccountTypes` | Sí | Los tipos de cuenta que un bloqueo puede usar. |
| `salaryAccountTypes` | Sí | Los tipos de cuenta que son cuentas salario. Envía `["NONE"]` cuando la institución no tiene un tipo de cuenta salario. |
| `crmMode` | No | `legacy` o `embedded`. Sin valor, la institución usa `MIDAZ_CRM_MODE`. |
| `crmBaseUrl` | No | La URL base del CRM independiente de Midaz, para `legacy`. Con `embedded`, déjala vacía: el plugin lee el CRM por `baseUrl`. |
| `permanentProducts` | Para escribir resultados de bloqueo permanente | El catálogo de productos de la institución: `bankCode` y, en `types`, la clase y el código del producto de cada tipo de cuenta. Sin él, el plugin retiene el resultado de un bloqueo posterior y dispara una alarma. |
| `executorLedger` | Para ejecutar órdenes | El ledger en el que escribe el plugin. La siguiente tabla lo describe. |

### Ledger del plugin

| Clave | Significado |
| - | - |
| `organizationId` | La organización de Midaz de las escrituras. |
| `ledgerId` | El ledger de Midaz de las escrituras. |
| `asset` | Configúralo como `BRL`, exactamente. |
| `judicialDepositAccountAlias` | El alias de la cuenta de depósito judicial. Debe seguir la regla de alias de Midaz. |

El plugin rechaza una solicitud de institución cuyo `executorLedger` está presente y no es válido, con `400`. Al iniciar, el plugin deja fuera de su enrutamiento del ledger una institución que no tiene un `executorLedger` válido.

### Credenciales del conector

`PUT /v1/institutions/{institutionId}/connector-credentials` escribe las credenciales de Midaz de la institución:

* `ledger_client_id` y `ledger_client_secret` son siempre obligatorios.
* `crm_client_id` y `crm_client_secret` son obligatorios con `crmMode` `legacy`. Con `embedded`, no los envíes.

El plugin cifra las credenciales antes de guardarlas. `PATCH /v1/institutions/{institutionId}` rechaza un cuerpo con credenciales. Una credencial nueva no revoca la anterior en el Access Manager, así que revócala allí.

El plugin obtiene el token de Midaz de la institución en `{authAddress}/v1/login/oauth/access_token`. Cuando la institución no tiene credenciales guardadas, el plugin no envía el header `Authorization` a Midaz.

### Cambiar la configuración

* `PATCH /v1/institutions/{institutionId}` cambia los campos de la institución. Un `connectorMetadata` en el cuerpo reemplaza el paquete completo, excepto las credenciales guardadas.
* `PUT /v1/institutions/{institutionId}/connector-config` reemplaza `connectorType` y `connectorMetadata`. Mantiene las credenciales guardadas y rechaza un cuerpo con credenciales.
* `GET /v1/institutions/{institutionId}` devuelve la configuración sin las credenciales.

El plugin lee la configuración de sus instituciones al iniciar. Después de crear una institución o cambiar su configuración, reinicia el plugin.

## Canal directo

***

[Cómo Plugin SISBAJUD ejecuta órdenes](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-how-it-works.md#direct-channel) describe el canal. Para poner una institución en él, envía `PUT /v1/institutions/{institutionId}/channel` con `DIRECT`. Envía `MENSAGERIA` para devolverla. La llamada responde `200` con `changed` `false` cuando la institución ya está en ese canal.

El canal exige `PLUGIN_AUTH_ENABLED` activado, un tenant y el modo executor. El cambio exige una persona con el rol `platform-admin`. El plugin rechaza un token de aplicación y un token con alcance de tenant con `403`.

El cambio rechaza con estos códigos:

* `SBJ-0040` / **422**: el despliegue es multi-tenant.
* `SBJ-0041` / **422**: `PLUGIN_AUTH_ENABLED` está desactivado.
* `SBJ-0042` / **422**: el código de la institución guardado no es la raíz de 8 caracteres del CNPJ de la agrupación responsable.
* `SBJ-0043` / **409**: la institución tiene una orden abierta, o un bloqueo que todavía retiene dinero.
* `SBJ-0046` / **409**: otro cambio ganó. Nada se movió. Envía la solicitud de nuevo.
* `SBJ-0060` / **409**: otra instalación del Plugin SISBAJUD es dueña de la institución.

### Borrar una orden del canal directo

Un administrador de la plataforma llama a dos rutas para borrar órdenes del canal directo. [Cómo Plugin SISBAJUD ejecuta órdenes](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-how-it-works.md#direct-channel) describe qué elimina un borrado y qué conserva.

* `POST /v1/admin/direct/orders/{orderId}/erase` borra una orden. El cuerpo lleva `reason`, `ticket` y un `note` opcional. `reason` es `lgpd-subject-request` o `retention-purge`. `ticket` tiene hasta 64 caracteres, y `note` hasta 256. Ninguno puede contener datos personales. La respuesta es `200` con `outcome` `erased`, o `noop` cuando la orden ya está borrada, y el número de filas borradas.
* `POST /v1/admin/direct/purge` lista las órdenes que ya se pueden borrar y no cambia nada. El cuerpo lleva `reason`, `ticket`, `limit` (de 1 a 100, y 100 cuando falta) y `dryRun`, que debe ser `true`. La respuesta trae `orderIds`, de la más antigua a la más nueva, `asOf` y `truncated`. `truncated` es `true` cuando la lista se detuvo antes de que el plugin leyera todos los candidatos.

El llamador necesita el token de una persona, sin tenant. El plugin rechaza un token de aplicación con `403` `SBJ-0044`, y un token con alcance de tenant con `403` `SBJ-0045`. Las rutas solo existen cuando el plugin corre en modo executor con `PLUGIN_AUTH_ENABLED` activado. Un despliegue multi-tenant recibe `422` `SBJ-0059`. Una orden desconocida recibe `404` `SBJ-0015`. La [lista de errores del Plugin SISBAJUD](https://docs.lerian.studio/es/reference/interfaces/plugin-sisbajud/plugin-sisbajud-error-list.md) enumera `SBJ-0056` a `SBJ-0059`.

El gauge `sisbajud_executor_direct_intake_purge_eligible` cuenta las órdenes que ya se pueden borrar. La cuenta es un límite inferior. `EXECUTOR_DIRECT_PURGE_REFRESH_EVERY` define cada cuánto cuenta el plugin.

## Enrutamiento del ledger

***

Con `SYSTEMPLANE_ENABLED` activo, el plugin sirve los documentos de tenant de sus rutas contables en `/tenant-system`. El plugin lee dos de ellos: `routing.organizations` activa las rutas contables de cada organización, y `routing.ledger_bindings` guarda las rutas. Con `SYSTEMPLANE_ENABLED` inactivo, el plugin escribe sin rutas.

`routing.organizations` acepta `schemaVersion` 1 o 2. Con `schemaVersion` 2, cada entrada de organización tiene sus propias `routes` para cada flujo y sus `ledgers`, los ledgers que registran con esas rutas. El plugin entonces no lee `routing.ledger_bindings`, y una escritura en un ledger fuera de `ledgers` sale sin rutas.

`GET /v1/admin/ledger-routing/preflight` verifica la configuración de enrutamiento frente al ledger de la institución. No escribe nada. Un plugin single-tenant necesita el parámetro de consulta `institutionId`. El informe cubre estas verificaciones:

* Las rutas de transacción y las rutas de operación existen y coinciden con las escrituras del plugin.
* Un ledger que valida tipos de cuenta tiene `sisbajud_block` registrado.
* La cuenta de depósito judicial en `executorLedger` existe en el ledger y no está bloqueada.
* Con `schemaVersion` 2, el ledger de cada escritura está en los `ledgers` de su organización. Un ledger fuera de la lista recibe el problema `ledger_not_listed`, y el documento de bindings recibe el estado `ignored`.

El campo `ready` indica si la configuración está lista. El informe muestra el `executorLedger` guardado. El plugin en ejecución usa la configuración que leyó al iniciar.

## Órdenes que necesitan atención

***

| Operación | Qué devuelve |
| - | - |
| `GET /v1/institutions/{institutionId}/executor/failed-orders` | Las revisiones de orden que el plugin falló o abandonó. Cada elemento tiene el ID de la orden, la revisión, un token de motivo y el ID de su entrada en el journal. No lista las revisiones cuyo resultado todavía no se conoce. |
| `GET /v1/institutions/{institutionId}/executor/human-decisions` | Las revisiones de orden que el plugin detuvo en una decisión humana. |

Cada decisión humana tiene un `humanDisposition`:

* `GAVE_UP`: el plugin no intentó ninguna escritura en el ledger y respondió `EXECUTOR_GAVE_UP`.
* `HELD_MONEY_MOVED`: el plugin intentó una escritura. El dinero puede haberse movido, y el plugin no envió respuesta.

El plugin también registra una decisión humana cuando estaciona un resultado después de `EXECUTOR_RESULT_MAX_ATTEMPTS` envíos fallidos, y cuando el ledger está caído en el corte de una orden. [Cómo Plugin SISBAJUD ejecuta órdenes](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-how-it-works.md#ledger-down-at-the-cut) describe el corte.

### Resolver una decisión humana

`POST /v1/admin/executor/orders/{orderId}/revisions/{revision}/human-decision/resolution` cierra la decisión humana abierta de una revisión de orden. El cuerpo trae el `decisionId` de la decisión, un `reason` y una `resolution`:

* `proven-no-effect`: el ledger muestra que las escrituras de la revisión no llegaron.
* `effect-acknowledged`: aceptas el efecto tal como es. Para una liberación cuyo bloqueo padre llegó sin sus piernas de origen, envía `movedAmount` y una transacción como `ledgerEvidence`.

`ledgerEvidence` es obligatorio cuando la revisión es incierta. El `reason` tiene como máximo 200 caracteres y ningún dato personal.

El plugin registra la resolución y su entrada de auditoría en una transacción. No envía nada al tribunal: la institución responde al tribunal. La ruta exige `PLUGIN_AUTH_ENABLED` activado y una persona con el rol `platform-admin`, y el plugin rechaza un token de aplicación y un token con alcance de tenant con `403`. Un despliegue multi-tenant responde `422` `SBJ-0053`.

La ruta puede devolver estos errores:

* `SBJ-0051` / **409**: la revisión no tiene una decisión humana abierta para resolver aquí.
* `SBJ-0052` / **422**: la resolución, el motivo o la evidencia no es válido.
* `SBJ-0054` / **409**: el journal muestra que el dinero se movió, así que `proven-no-effect` se rechaza. Un reconocimiento también se rechaza mientras la escritura está indeterminada.
* `SBJ-0055` / **409**: el journal no muestra un efecto concretado, así que no hay nada que reconocer.
* `SBJ-0064` / **409**: la evidencia es una transacción que el propio plugin registró para la revisión.

### Rearmar un resultado estacionado

`POST /v1/admin/executor/orders/{orderId}/revisions/{revision}/results/{executionVersion}/rearm` toma un resultado que el plugin estacionó en `EXECUTOR_RESULT_MAX_ATTEMPTS`. Vuelve los intentos a 0, y el plugin envía el resultado de nuevo en el acto. Las versiones posteriores de la misma orden entonces siguen. Envía un `reason` de como máximo 200 caracteres, sin datos personales.

Un resultado que está pendiente pero no estacionado responde `200` con el resultado `NOOP`. La ruta exige `PLUGIN_AUTH_ENABLED` activado y una persona con el rol `platform-admin`, y funciona solo en un despliegue single-tenant.

* `SBJ-0048` / **409**: el resultado es terminal. No hay nada que rearmar.
* `SBJ-0049` / **422**: el motivo falta, está en blanco, es demasiado largo o tiene datos personales.
* `SBJ-0050` / **422**: el despliegue es multi-tenant.

### Resolver un intento permanente estacionado

`POST /v1/admin/executor/orders/{orderId}/permanent-attempts/{attemptId}/resolution` resuelve un intento estacionado de un bloqueo permanente en el canal directo. Sigue las reglas de la resolución de decisión humana y exige el mismo rol y `PLUGIN_AUTH_ENABLED` activado. Con `proven-no-effect`, los nuevos créditos del bloqueo se vuelven a tomar. Con `effect-acknowledged`, el plugin cuenta `movedAmount` en el monto de la orden. Agrega estos errores:

* `SBJ-0061` / **409**: el intento no está estacionado, o la orden está ocupada.
* `SBJ-0062` / **422**: el monto reconocido es mayor que lo que el bloqueo permanente abierto aún retiene, o mayor que la escritura que el plugin registró para un bloqueo cerrado.

La Mensageria también lista las órdenes en las que el plugin desistió. [Operar Lerian SISBAJUD](https://docs.lerian.studio/es/rails/sisbajud/sisbajud-operations.md#orders-that-need-attention) describe esa lista.

## Rotación de la clave de credenciales

***

`POST /v1/institutions/{institutionId}/security/credential-kek:rotate` rota la clave que envuelve las credenciales de Midaz guardadas de la institución. Esta clave no es la clave de datos de la institución que rota la Mensageria.

* La rotación mueve las credenciales guardadas a la nueva versión de la clave. Los valores de las credenciales no cambian. Para reemplazar una credencial, usa `PUT /v1/institutions/{institutionId}/connector-credentials`.
* La respuesta muestra la versión anterior y la nueva versión de la clave.
* Una institución sin credenciales guardadas devuelve `404`.
* Con `STREAMING_ENABLED` activo, la rotación publica un evento `kek.rotated` con `keyPurpose` `CREDENTIALS`.
* Con AWS KMS en el modo `provided`, el plugin no rota tu clave, y la operación devuelve `422`.

La rotación puede devolver estos errores:

* `SBJ-0007` / **409**: otra rotación de la misma institución está en curso. Envíala de nuevo cuando esa rotación termine.
* `SBJ-0012` / **409**: nada rotó, y la misma solicitud falla de nuevo.
* **503**: el gestor de claves falló antes de la rotación. Envíala de nuevo más tarde.
* `SBJ-0013` / **500**: el resultado de la rotación no se conoce. No envíes la rotación de nuevo.
* `SBJ-0014` / **500**: la clave rotó, pero un paso posterior falló. No envíes la rotación de nuevo. Contacta al soporte de Lerian.

Con `PLUGIN_AUTH_ENABLED` inactivo, el plugin no sirve esta operación.

## Verificación de auditoría

***

`GET /v1/admin/audit/verify` verifica un rango del log de auditoría de la institución, de `fromIndex` a `toIndex`. No descifra ningún payload. Informa alteraciones y entradas borradas.

## Roles

***

Cada operación necesita un permiso:

| Operación | Permiso |
| - | - |
| Crear o actualizar una institución, su configuración de conector o sus credenciales | `institution_config:write` |
| Leer una institución, las órdenes fallidas, las decisiones humanas o la verificación de auditoría | `admin:read` |
| Rotación de la clave de credenciales | `credential_kek:rotate` |
| Preflight del enrutamiento del ledger, y lecturas en `/tenant-system` | `tenant_policy:read` |
| Escrituras en `/tenant-system` | `tenant_policy:write` |
| Cambiar el canal de una institución | `institution_channel:write` |
| Rearmar un resultado estacionado | `executor_result:rearm` |
| Resolver una decisión humana o un intento permanente estacionado | `executor_human_decision:resolve` |
| Borrar una orden del canal directo | `direct_order_erasure:erase` |
| Previsualizar la depuración de órdenes del canal directo | `direct_order_erasure:purge_preview` |
| Enviar una orden directa | `order:submit` |
| Leer órdenes y resultados directos | `result:read` |

El plugin declara los roles `viewer`, `operator`, `investigator`, `cross-org-reader`, `admin`, `platform-admin`, `order-submitter` y `result-reader`. Cada uno de los seis primeros roles vincula el grupo `plugin-br-sisbajud-<role>-group`, y `admin` también vincula `admin-group`. Los roles `order-submitter` y `result-reader` no vinculan ningún grupo. Tu aplicación M2M tiene `admin`, `order-submitter` y `result-reader`.

El rol `admin` tiene los permisos de las cinco primeras filas de la tabla. Los roles `viewer`, `operator`, `investigator` y `cross-org-reader` tienen `admin:read`. El rol `platform-admin` tiene `institution_channel:write`, `executor_result:rearm`, `executor_human_decision:resolve`, `direct_order_erasure:erase`, `direct_order_erasure:purge_preview` y los permisos `systemplane` de `/system`. Ningún otro rol los tiene. El plugin rechaza un token de aplicación y un token con alcance de tenant en las cinco operaciones de plataforma con `403`.

El rol `result-reader` tiene solo `result:read`. El rol `order-submitter` tiene `order:submit`, `result:read` y `metadata:read`. Solo un llamador con `metadata:read` lee el `metadata` de la orden en las lecturas directas.

### El plugin en la Mensageria

El plugin llama a la API de ejecución de la Mensageria con su propio cliente M2M. Configura el cliente en `MENSAGERIA_CLIENT_ID` y `MENSAGERIA_CLIENT_SECRET`. El plugin obtiene su token del Access Manager en `PLUGIN_AUTH_HOST`.

## Listeners

***

El plugin tiene dos listeners:

* **API principal**, en `SERVER_ADDRESS`. Configúrala como `:4029`, el puerto que expone la imagen. Sirve las operaciones de la referencia de la API. También sirve `/health`, `/readyz` y `/version`. Con `SYSTEMPLANE_ENABLED` activo, sirve `/system` y `/tenant-system`. Con `SWAGGER_ENABLED` activo, sirve `/swagger`.
* **Listener de webhook**, en `EXECUTOR_HUB_WEBHOOK_ADDRESS`. El valor predeterminado es `:9082`. Tiene una ruta, `POST` en `EXECUTOR_HUB_WEBHOOK_PATH`, cuyo valor predeterminado es `/v1/webhooks/hub`. Expón este puerto al Streaming Hub y usa la dirección de tu ingress más esta ruta como URL de la suscripción.

El listener de webhook no tiene autenticación de aplicación. Acepta una entrega solo cuando la firma HMAC es válida con el secret de la suscripción o con el secret anterior. Fuera de `DEPLOYMENT_MODE=local`, el listener necesita su propio certificado TLS. Como alternativa, termina el TLS delante de él y configura `EXECUTOR_HUB_WEBHOOK_UPSTREAM_TLS_VALIDATED=true`.

`/readyz` incluye dos verificaciones del plugin:

* `hub_webhook`: el listener de webhook.
* `executor_institutions`: el número de instituciones de las que el plugin es dueño y cuántas de ellas tienen enrutamiento del ledger. Esta verificación no hace fallar la disponibilidad.

## Restricciones de despliegue

***

* **Un tenant por proceso.** El plugin no inicia cuando su lista de tenants tiene más de un tenant.
* **Su propia base de datos.** El plugin se ejecuta en su propia base de datos PostgreSQL vacía. Sus migraciones rechazan una base de datos que ya tiene otro historial de migraciones.
* **Reinicio después de cambios de configuración.** El plugin lee sus instituciones al iniciar.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.