> ## 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.

# Cómo Plugin SISBAJUD ejecuta órdenes

> Cómo Plugin SISBAJUD recibe órdenes judiciales, ejecuta bloqueos, desbloqueos, transferencias y solicitudes de información en Midaz, e informa cada resultado.

El **Plugin SISBAJUD** ejecuta órdenes judiciales en el ledger Midaz de la institución. Las órdenes vienen de la Mensageria o, en el canal directo, del sistema de la propia institución. Esta página describe cómo el plugin recibe una orden, qué escribe cada operación y cómo el plugin informa el resultado. [Operar Plugin SISBAJUD](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-operations.md) describe la configuración. [Cómo funciona Lerian SISBAJUD](https://docs.lerian.studio/es/rails/sisbajud/how-sisbajud-works.md) muestra cómo una orden pasa de la Mensageria al Plugin SISBAJUD.

## Ciclo de vida de la orden

***

1. **Aviso.** El Streaming Hub envía un aviso de ejecución al listener de webhook del plugin. El aviso lleva el ID de la orden y la revisión de la orden, no la orden.
2. **Verificación.** El plugin verifica la firma HMAC de la entrega. Guarda cada aviso firmado antes de responder.
3. **Obtención.** El plugin obtiene la orden con `GET /v1/sisbajud/execution/orders/{orderId}` en la API de ejecución de la Mensageria.
4. **Verificación del dueño.** Antes de su primera escritura, el plugin verifica que es dueño de la institución de la orden.
5. **Ejecución.** En su siguiente ciclo, el plugin ejecuta la operación en Midaz.
6. **Resultado.** El plugin envía el resultado con `POST /v1/sisbajud/execution/orders/{orderId}/execution-results`.

### Respuestas del webhook

| Entrega | Respuesta |
| - | - |
| El cuerpo es mayor que 1 MiB. | `413`. El plugin no guarda nada. |
| La firma HMAC falta o no es válida. | `401`. El plugin no guarda la entrega. |
| La firma es válida, pero el cuerpo no es un aviso utilizable ni un ping de verificación. | `200`. El plugin estaciona la entrega y dispara una alarma. |
| La Mensageria responde a la obtención con un estado `4xx` distinto de `401`, `404`, `410` o `429`. | `200`. El plugin estaciona la entrega y dispara una alarma. |
| La Mensageria o una base de datos falla. | `503`. El Streaming Hub reintenta la entrega. |
| El plugin acepta el aviso. | `200`. El plugin ejecuta la orden en su siguiente ciclo. |

El plugin acepta una entrega con un timestamp fuera de `EXECUTOR_HUB_WEBHOOK_MAX_SKEW_SEC` y registra una advertencia en el log.

### Respuestas de la obtención

| Respuesta de la Mensageria | Qué hace el plugin |
| - | - |
| `200` | Ejecuta la orden. |
| `404` o `410` | Trata la orden como retirada. No escribe nada en el ledger. |
| `401`, `429`, un estado `5xx` o un error de red | Reintenta la solicitud. |
| Cualquier otro estado `4xx` | Estaciona la entrega y dispara una alarma. |
| `200`, con una orden de bloqueo cuyo monto mínimo es mayor que su monto | No escribe nada en el ledger y dispara una alarma. |

### Verificación del dueño

El plugin escribe en el ledger solo para las instituciones de las que es dueño. Cuando crea una institución, registra su propio subject M2M (`EXECUTOR_M2M_SUBJECT`) como dueño.

* Si otra identidad es dueña de la institución, el plugin no escribe nada y dispara una alarma.
* Si la institución no tiene configuración en este plugin, la orden pasa a una decisión humana.

### Ciclo de ejecución

El plugin ejecuta un ciclo cada `EXECUTOR_TICK_EVERY`. El valor predeterminado es `30s`. Cada ciclo ejecuta tres pasos en este orden:

1. **Ingesta.** Ejecuta los avisos aceptados.
2. **Verificación de huérfanas.** Busca operaciones en las cuentas de bloqueo que el plugin no escribió.
3. **Monitoreo.** Envía un heartbeat por cada escritura que no tiene un resultado conocido.

Un paso con falla no detiene los otros pasos. El plugin drena los resultados que esperan en el outbox en un loop separado por cada canal, así que un canal lento no retiene el ciclo ni otro canal.

### Resultados

El plugin guarda cada resultado en un outbox antes de enviarlo. Cada envío lleva el header `X-Idempotency`. Cuando un envío falla con un error transitorio, el plugin envía el mismo resultado de nuevo después de una espera, hasta `EXECUTOR_RESULT_MAX_ATTEMPTS` intentos. El valor predeterminado es 12.

Después del último intento, el plugin estaciona el resultado, registra una decisión humana y dispara una alarma. No envía de nuevo un resultado estacionado, y las versiones posteriores de la misma orden esperan detrás de él. Un administrador de la plataforma rearma el resultado. [Operar Plugin SISBAJUD](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-operations.md#orders-that-need-attention) describe la ruta.

| Campo | Valores |
| - | - |
| `executionState` | `ACCEPTED`, `EXECUTING`, `MONITORING`, `RESOLVED`, `INDETERMINATE`, `AWAITING_RECONCILIATION` |
| `effect` | `NONE`, `FULL`, `PARTIAL`, `INDETERMINATE` |

El `reasonCode` de cada operación está en las secciones siguientes.

## Operaciones

***

El bloqueo y el desbloqueo escriben en Midaz. La solicitud de información solo lee.

### Bloqueo (BLOQUEIO)

1. El plugin lee las cuentas activas del sujeto. Un sujeto sin cuenta activa recibe `NONE` con `NO_CLIENT`.
2. Aplica la restricción de sucursal y cuenta de la orden. [Restricción de sucursal y cuenta](#branch-account-restriction) da las reglas.
3. Bloquea una cuenta salario solo cuando la orden permite cuentas salario.
4. Bloquea solo fondos propios. Una cuenta en sobregiro cuenta como 0.
5. Envía una escritura a Midaz. La escritura tiene una pierna por cada cuenta de origen, y todas las piernas van a la cuenta de bloqueo de la orden.

| Resultado | `effect` | `reasonCode` |
| - | - | - |
| El bloqueo cubre el monto todavía abierto en la orden. | `FULL` | `BLOCKED_TOTAL` |
| El bloqueo cubre menos que ese monto. | `PARTIAL` | `BLOCKED_PARTIAL` |
| No hay fondos disponibles. | `NONE` | `NO_BALANCE` |

Una orden de bloqueo puede traer un monto mínimo. Cuando el total que el plugin puede bloquear queda por debajo de ese mínimo, no escribe nada y pasa la orden a una decisión humana.

#### Restricción de sucursal y cuenta

El plugin lee la sucursal y el número de cada cuenta en los instrumentos del CRM del sujeto. Con `crmMode` `embedded`, la sucursal es `bankingDetails.branch` y el número de cuenta es `bankingDetails.account`. Con `crmMode` `legacy`, el CRM no trae ninguno de los dos.

* Una orden que indica una sucursal pasa a una decisión humana cuando una cuenta que puede ser la indicada tiene una sucursal desconocida o ambigua.
* Una orden que indica un número de cuenta bloquea las cuentas cuyo número coincide. También bloquea una cuenta de número desconocido o ambiguo, hasta el monto de la orden, porque esa cuenta puede ser la que indicó el tribunal. Las cuentas cuyo número coincide van primero. Con `crmMode` `legacy`, no se conoce ningún número, así que toda cuenta que pasa la regla de sucursal puede bloquearse.
* Una orden con número de cuenta y sin sucursal pasa a una decisión humana cuando dos o más cuentas coinciden.
* Con un número de cuenta, el resultado es `NONE` cuando todos los números de cuenta son conocidos y ninguno coincide.

### Desbloqueo (DESBLOQUEIO)

El desbloqueo libera fondos de una orden de bloqueo padre, identificada por `parentOrderId`. El plugin usa la cuenta de origen registrada del bloqueo padre como destino de la liberación. Si no puede determinar un único destino con seguridad, requiere una decisión humana en lugar de adivinar.

* Sin una orden padre, el resultado es `NONE` con `PARENT_UNRESOLVED`, y el plugin no escribe nada.
* Cuando la orden padre todavía no tiene un efecto conocido, el plugin espera. En el plazo de la orden menos `RESPONSE_DEADLINE_MARGIN`, la orden pasa a una decisión humana. Si la orden no tiene plazo, pasa a una decisión humana de inmediato.
* El plugin lee la cuenta de bloqueo de la orden padre cuando ejecuta la orden. Libera el menor de tres montos: el monto que pide la orden, el saldo restante de la orden padre y el saldo de la cuenta de bloqueo.
* Cuando el monto a liberar es 0, el resultado es `NOTHING_TO_RELEASE`.
* Cuando una cuenta del sujeto es una cuenta salario, la orden pasa a una decisión humana.

### Solicitud de información (REQUISICAO\_INFORMACAO)

El plugin lee los saldos del sujeto y no escribe nada en el ledger. Si el sujeto es cliente, pero no es titular de la cuenta especificada, el plugin requiere una decisión humana en lugar de informar que el sujeto no es cliente.

* Un sujeto con al menos una cuenta activa recibe `FULL` con `INFO_FULFILLED`.
* Un sujeto sin cuenta activa recibe `NONE` con `INFO_NON_CLIENT`.
* Una orden que indica una sucursal pasa a una decisión humana.

Cuando la orden pide el saldo (`searchBalance`), el resultado lleva dos totales: el total bloqueable y el total bloqueable de las cuentas salario. Un sujeto sin cuenta activa recibe 0.00 en ambos.

## Canal directo

***

En el canal directo, el sistema de la propia institución envía órdenes judiciales al plugin, y la Mensageria no participa. El plugin guarda cada orden, la ejecuta en Midaz y guarda los resultados. La institución lee los resultados y responde ella misma al tribunal.

El plugin sirve el canal directo solo cuando corre en modo executor, con un tenant, y con `PLUGIN_AUTH_ENABLED` activado. De lo contrario, las cinco rutas directas responden `501`.

Un administrador de la plataforma pasa una institución al canal directo con `PUT /v1/institutions/{institutionId}/channel`. El cambio exige todo esto:

* El plugin es el dueño de la institución.
* El código de la institución guardado es la raíz de 8 caracteres del CNPJ de la agrupación responsable.
* La institución no tiene orden abierta, y ningún bloqueo de la institución retiene todavía dinero.

La misma ruta devuelve la institución a la Mensageria. Una institución que no está en el canal directo recibe `422` `SBJ-0025` en una orden directa.

| Ruta | Finalidad |
| - | - |
| `POST /v1/institutions/{institutionId}/executor/orders` | Envía una orden o una revisión. Responde `202`. |
| `GET /v1/institutions/{institutionId}/executor/orders` | Busca las órdenes por `externalReference`. |
| `GET /v1/institutions/{institutionId}/executor/orders/{orderId}` | Lee una orden. |
| `GET /v1/institutions/{institutionId}/executor/orders/{orderId}/results` | Lista las versiones de resultado de una orden. |
| `GET /v1/institutions/{institutionId}/executor/results` | Lee los resultados de la institución como un feed por cursor. |

El feed de resultados entrega cada resultado al menos una vez. Elimina duplicados por `orderId`, `orderRevision` y `executionVersion`. Envía un desbloqueo o una transferencia solo después del `202` de su bloqueo padre.

El canal directo acepta `BLOCK`, `UNBLOCK`, `TRANSFER`, `INFO` e `INTERRUPT`. Una transferencia mueve fondos de la cuenta de bloqueo de la orden padre a la cuenta de depósito judicial de la institución. Una interrupción detiene un bloqueo permanente y conserva lo que el bloqueo ya retiene. `DIRECT_PERMANENT_BLOCK_ENABLED` decide si el canal acepta un nuevo bloqueo permanente. Con el valor predeterminado, rechaza uno con `422` `SBJ-0027`.

Un bloqueo permanente sigue bloqueando nuevos créditos del sujeto, hasta el monto de la orden. El plugin lee esos créditos de los eventos del ledger de Midaz. Dura un año desde la recepción, o hasta la fecha del tribunal cuando la orden indica una, y nunca más de un año. Cuando el plazo termina, el bloqueo deja de tomar nuevos créditos y conserva lo que ya retiene. Una interrupción, una transferencia o un desbloqueo del resto, o una cancelación lo cierra. Cuando un bloque posterior de un bloqueo permanente sigue fallando, el plugin estaciona el intento, levanta una alarma y deja de tomar nuevos créditos de ese bloqueo hasta que un administrador de la plataforma resuelva el intento. Una orden directa que falla en todos los intentos, o que llega a su corte mientras el ledger falla, también se estaciona. Su lectura muestra `parked` `true`.

Los roles de máquina `order-submitter` y `result-reader` llaman a estas rutas. [Operar Plugin SISBAJUD](https://docs.lerian.studio/es/interfaces/plugin-sisbajud/plugin-sisbajud-operations.md#roles) describe los roles.

### Borrar una orden del canal directo

Un administrador de la plataforma borra una orden concluida del canal directo con `POST /v1/admin/direct/orders/{orderId}/erase`, por una solicitud del titular de los datos bajo la LGPD o al final de la retención. `POST /v1/admin/direct/purge` lista las órdenes que ya se pueden borrar y no cambia nada. Las dos operaciones exigen un token de usuario sin tenant y solo responden en una instalación de un solo tenant.

Después del borrado, nadie vuelve a leer el contenido enviado con la orden: el cuerpo de la orden y el número de documento de la persona o empresa a la que apunta la orden. El borrado no se puede deshacer. Tu `clientOrderId` y tu `externalReference` pasan a ser tokens. Una búsqueda por el `externalReference` original todavía encuentra la orden borrada, con el contenido oculto.

El borrado no elimina:

* el protocolo del tribunal y los números de secuencia de la orden;
* el diario de asientos del plugin, con sus importes, ni las transacciones en Midaz;
* los resultados que ya están en el feed de resultados, ni lo que tu sistema ya leyó de él;
* el registro de auditoría del borrado;
* los backups hechos antes del borrado. Después de restaurar un backup, borra la orden otra vez.

El plugin nunca borra una orden por sí solo. El borrado rechaza una orden todavía abierta, que todavía retiene dinero o que tiene una orden hija abierta. También rechaza una orden de bloqueo con menos de un año desde su primer asiento en el ledger, y un bloqueo permanente antes de su fecha de fin. Cuando una orden sigue apta para el borrado más tiempo que `EXECUTOR_DIRECT_PURGE_ELIGIBLE_ALARM_AFTER` (por defecto `168h`), el plugin registra un error en el log para que un administrador lo revise.

## Semántica del ledger

***

### Cuenta de bloqueo

El alias de la cuenta de bloqueo tiene el prefijo `@block_sisbajud_` y luego los 32 dígitos hexadecimales en minúsculas del ID de la orden de bloqueo. Un desbloqueo encuentra la cuenta por su `parentOrderId`.

El tipo de cuenta de una cuenta de bloqueo es `sisbajud_block`. Si tu ledger valida tipos de cuenta, registra `sisbajud_block` como tipo de cuenta.

### Direcciones

* Un bloqueo disminuye las cuentas del sujeto y aumenta la cuenta de bloqueo.
* Una transferencia disminuye la cuenta de bloqueo de la orden padre y aumenta la cuenta de depósito judicial.
* Un desbloqueo disminuye la cuenta de bloqueo. Su escritura tiene una pierna de origen: la cuenta de bloqueo. Libera los fondos a la cuenta de origen registrada o requiere una decisión humana cuando no se puede determinar un único destino seguro.

Un bloqueo mueve el monto del saldo disponible de cada cuenta del sujeto al saldo disponible de la cuenta de bloqueo.

### Idempotencia

Cada escritura lleva el header `X-Idempotency` y `X-TTL: 604800`, que son siete días. Midaz guarda la clave de idempotencia de una escritura durante ese tiempo. La clave es `orderId:orderRevision`, así que una reentrega de la misma revisión de la orden envía la misma clave.

## Escrituras inciertas

***

Cuando Midaz responde a una escritura sin prueba de su efecto, el resultado es `INDETERMINATE`. El plugin lee el ledger de nuevo antes de cada heartbeat. Envía un resultado de heartbeat a la Mensageria cada `EXECUTOR_HEARTBEAT_EVERY`, hasta que la Mensageria responda que la revisión de la orden fue reemplazada.

La orden pasa a una decisión humana en el primero de dos límites:

* `EXECUTOR_HUMAN_DECISION_AFTER_BEATS` heartbeats sin cambio. El valor predeterminado es 3.
* El plazo de la orden menos `RESPONSE_DEADLINE_MARGIN`.

El plugin entonces registra una decisión humana. En la lista de decisiones humanas, tiene `humanDisposition` `HELD_MONEY_MOVED`. Los heartbeats continúan, con `executionState` y `effect` ambos `INDETERMINATE`.

### Ledger caído en el corte

El corte de una orden es su plazo menos `RESPONSE_DEADLINE_MARGIN`. Cuando Midaz falla para una orden de la Mensageria en el corte o después de él, y ningún resultado judicial de esa revisión espera en el outbox, el plugin detiene sus reintentos. Registra una decisión humana y no envía resultado. Revisa el ledger y responde tú al tribunal antes del plazo. De lo contrario, la Mensageria registra una no respuesta.

### Después de que una persona responde

Toma una revisión que se pasó a una persona en su corte, o que una persona resolvió como efecto reconocido o sin efecto comprobado. Cuando su escritura llega a Midaz más tarde, el plugin no envía un resultado `FULL` ni `PARTIAL` para ella. Registra el efecto y dispara una alarma. El tribunal recibe solo la respuesta de la persona, así que concilia tú un efecto tardío en el ledger.

### Operaciones que el plugin no escribió

La verificación de huérfanas lee las operaciones de cada cuenta de bloqueo durante `EXECUTOR_ORPHAN_RECONCILE_WINDOW`. El valor predeterminado es `48h`. El plugin informa una operación como huérfana cuando su transacción no tiene `metadata.code`, o tiene un código que el plugin no registró. Este paso solo detecta. No cambia nada en el ledger.

## Rutas contables

***

Las rutas contables son opcionales, por organización. El plugin las lee de los documentos de tenant `routing.organizations` y `routing.ledger_bindings` en Systemplane. Con `SYSTEMPLANE_ENABLED` inactivo, el plugin escribe sin rutas.

Con `routing.organizations` en `schemaVersion` 2, cada organización tiene sus propias rutas para cada flujo y la lista de ledgers que registran con ellas. El plugin entonces no lee `routing.ledger_bindings`. Una escritura en un ledger que no está en la lista de su organización sale sin rutas.

Cuando una escritura no puede salir por su configuración, el plugin la aplaza. Midaz no aplicó nada, así que la orden espera, y una entrega posterior envía la misma escritura con la misma clave de idempotencia. Estas condiciones aplazan una escritura:

* El plugin no puede resolver las rutas contables de la escritura.
* Midaz rechaza las rutas contables de la escritura: `422` con código `0113`, `0114`, `0116`, `0117`, `0118`, `0119`, `0152` o `0157`, o `404` con código `0105`.

Corrige la configuración antes del plazo de la orden. `GET /v1/admin/ledger-routing/preflight` verifica la configuración antes de que actives las rutas.

## Llamadas a Midaz

***

El plugin llama al ledger Midaz en el `baseUrl` de cada institución, con el token de esa institución. Da a las credenciales de la institución acceso a estas operaciones:

| Finalidad | Operación de Midaz |
| - | - |
| Bloqueo | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/block` |
| Desbloqueo | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/unblock` |
| Transferencia a la cuenta de depósito judicial | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/json` |
| Crear una cuenta de bloqueo | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts` |
| Encontrar una cuenta por alias | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts?alias=` |
| Leer una cuenta | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts/{accountId}` |
| Leer los saldos de un alias | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts/alias/{alias}/balances` |
| Leer las operaciones de una cuenta de bloqueo | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts/{accountId}/operations` |
| Leer una transacción | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/{transactionId}` |
| Encontrar las transacciones de una escritura | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions?metadata.code=` |

El plugin encuentra las cuentas de un sujeto por el CRM de Midaz. Con `crmMode` `legacy`, llama a `GET /v1/aliases?document=` en `crmBaseUrl`. Con `crmMode` `embedded`, llama a `GET /v2/organizations/{organizationId}/instruments?document=` en `baseUrl`.


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