> ## 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 Lerian SISBAJUD executor ejecuta órdenes

> Cómo Lerian SISBAJUD executor recibe avisos de ejecución, ejecuta bloqueos, desbloqueos y solicitudes de información en Midaz, e informa cada resultado a la Mensageria.

El **executor** ejecuta las órdenes judiciales de la Mensageria en el ledger Midaz de la institución. Esta página describe cómo el executor recibe una orden, qué escribe cada operación y cómo el executor informa el resultado. [Operar Lerian SISBAJUD executor](/es/rails/sisbajud/sisbajud-executor-operations) describe la configuración.

<h2 id="order-lifecycle">
  Ciclo de vida de la orden
</h2>

***

1. **Aviso.** El Streaming Hub envía un aviso de ejecución al listener de webhook del executor. El aviso lleva el ID de la orden y la revisión de la orden, no la orden.
2. **Verificación.** El executor verifica la firma HMAC de la entrega. Guarda cada aviso firmado antes de responder.
3. **Obtención.** El executor 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 executor verifica que es dueño de la institución de la orden.
5. **Ejecución.** En su siguiente ciclo, el executor ejecuta la operación en Midaz.
6. **Resultado.** El executor 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 executor no guarda nada. |
| Ninguna firma es válida. | `401`. El executor no guarda nada. |
| La firma es válida, pero el cuerpo no es un aviso utilizable. | `200`. El executor estaciona la entrega y dispara una alarma. |
| La Mensageria o una base de datos falla. | `503`. El Streaming Hub reintenta la entrega. |
| El executor acepta el aviso. | `200`. El executor ejecuta la orden en su siguiente ciclo. |

El executor 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 executor |
| - | - |
| `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. |

### Verificación del dueño

El executor 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 executor no escribe nada y dispara una alarma.
* Si la institución no tiene configuración en este executor, la orden pasa a una decisión humana.

### Ciclo de ejecución

El executor ejecuta un ciclo cada `EXECUTOR_TICK_EVERY`. El valor predeterminado es `30s`. Cada ciclo ejecuta cuatro 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 executor no escribió.
3. **Monitoreo.** Envía un heartbeat por cada escritura que no tiene un resultado conocido.
4. **Drenaje.** Envía los resultados que esperan en el outbox.

Un paso con falla no detiene los otros pasos.

### Resultados

El executor 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 executor envía el mismo resultado de nuevo en un ciclo posterior.

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

<h2 id="operations">
  Operaciones
</h2>

***

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

<h3 id="block">
  Bloqueo (BLOQUEIO)
</h3>

1. El executor 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.
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` |

<h3 id="unblock">
  Desbloqueo (DESBLOQUEIO)
</h3>

El desbloqueo libera fondos de una orden de bloqueo padre, identificada por `parentOrderId`.

* Sin una orden padre, el resultado es `NONE` con `PARENT_UNRESOLVED`, y el executor no escribe nada.
* Cuando la orden padre todavía no tiene un efecto conocido, el executor espera. En el plazo de la orden, entrega la orden a una decisión humana.
* El executor 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`.
* El executor devuelve los fondos a cada cuenta de origen del bloqueo padre.
* Cuando una cuenta del sujeto es una cuenta salario, la orden pasa a una decisión humana.

<h3 id="information-request">
  Solicitud de información (REQUISICAO\_INFORMACAO)
</h3>

El executor lee los saldos del sujeto y no escribe nada en el ledger. Responde dos totales: el total bloqueable y el total bloqueable de las cuentas salario.

* 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.
* Una orden que indica una cuenta que el sujeto no tiene pasa a una decisión humana.

<h2 id="ledger-semantics">
  Semántica del ledger
</h2>

***

### Cuenta de bloqueo

Cada orden de bloqueo tiene su propia cuenta de bloqueo en Midaz. 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.
* Un desbloqueo disminuye la cuenta de bloqueo. Su escritura tiene una pierna de origen: la cuenta de bloqueo.

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`. Una reentrega de la misma revisión de la orden envía la misma clave.

<h2 id="uncertain-writes">
  Escrituras inciertas
</h2>

***

Cuando Midaz responde a una escritura sin prueba de su efecto, el resultado es `INDETERMINATE`. El executor lee el ledger de nuevo antes de cada heartbeat. Envía un resultado de heartbeat a la Mensageria cada `EXECUTOR_HEARTBEAT_EVERY`.

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 executor entonces registra una decisión humana. En la lista de decisiones humanas, tiene `humanDisposition` `HELD_MONEY_MOVED`, y el executor no envía ninguna respuesta final. Los heartbeats continúan, con `executionState` y `effect` ambos `INDETERMINATE`.

### Operaciones que el executor 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 executor informa una operación como huérfana cuando su transacción no tiene `metadata.code`, o tiene un código que el executor no registró. Este paso solo detecta. No cambia nada en el ledger.

<h2 id="accounting-routes">
  Rutas contables
</h2>

***

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

Cuando una escritura no puede salir por su configuración, el executor 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 executor 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.

<h2 id="midaz-calls">
  Llamadas a Midaz
</h2>

***

El executor 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` |
| 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 executor 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.