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

# How the Lerian SISBAJUD executor runs orders

> How the Lerian SISBAJUD executor receives execution notices, runs blocks, unblocks, and information requests on Midaz, and reports each result to the Mensageria.

The **executor** runs the judicial orders of the Mensageria on the client's Midaz ledger. This page describes how the executor receives an order, what each operation writes, and how the executor reports the result. [Operating the Lerian SISBAJUD executor](/en/rails/sisbajud/sisbajud-executor-operations) describes the setup.

<h2 id="order-lifecycle">
  Order lifecycle
</h2>

***

1. **Notice.** The Streaming Hub posts an execution notice to the webhook listener of the executor. The notice carries the order ID and the order revision, not the order.
2. **Verification.** The executor verifies the HMAC signature of the delivery. It stores each signed notice before it answers.
3. **Fetch.** The executor gets the order with `GET /v1/sisbajud/execution/orders/{orderId}` on the execution API of the Mensageria.
4. **Owner check.** Before its first write, the executor checks that it owns the institution of the order.
5. **Execution.** On its next cycle, the executor runs the operation on Midaz.
6. **Result.** The executor posts the result with `POST /v1/sisbajud/execution/orders/{orderId}/execution-results`.

### Webhook answers

| Delivery | Answer |
| - | - |
| The body is larger than 1 MiB. | `413`. The executor stores nothing. |
| No signature verifies. | `401`. The executor stores nothing. |
| The signature verifies, but the body is not a usable notice. | `200`. The executor parks the delivery and raises an alarm. |
| The Mensageria or a database fails. | `503`. The Streaming Hub retries the delivery. |
| The executor accepts the notice. | `200`. The executor runs the order on its next cycle. |

The executor accepts a delivery with a timestamp outside `EXECUTOR_HUB_WEBHOOK_MAX_SKEW_SEC`, and logs a warning.

### Fetch answers

| Answer of the Mensageria | What the executor does |
| - | - |
| `200` | Runs the order. |
| `404` or `410` | Treats the order as withdrawn. It writes nothing on the ledger. |
| `401`, `429`, a `5xx` status, or a network error | Retries the request. |
| Any other `4xx` status | Parks the delivery and raises an alarm. |

### Owner check

The executor writes on the ledger only for the institutions that it owns. When it creates an institution, it records its own M2M subject (`EXECUTOR_M2M_SUBJECT`) as the owner.

* If another identity owns the institution, the executor writes nothing and raises an alarm.
* If the institution has no configuration on this executor, the order goes to a human decision.

### Execution cycle

The executor runs one cycle every `EXECUTOR_TICK_EVERY`. The default is `30s`. Each cycle runs four steps in this order:

1. **Ingest.** Runs the accepted notices.
2. **Orphan check.** Looks for operations on the block accounts that the executor did not write.
3. **Monitor.** Sends a heartbeat for each write that has no known outcome.
4. **Drain.** Posts the results that wait in the outbox.

A failed step does not stop the other steps.

### Results

The executor stores each result in an outbox before it posts it. Each post carries the `X-Idempotency` header. When a post fails with a transient error, the executor posts the same result again on a later cycle.

| Field | Values |
| - | - |
| `executionState` | `ACCEPTED`, `EXECUTING`, `MONITORING`, `RESOLVED`, `INDETERMINATE`, `AWAITING_RECONCILIATION` |
| `effect` | `NONE`, `FULL`, `PARTIAL`, `INDETERMINATE` |

The `reasonCode` of each operation is in the sections below.

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

***

The executor runs three operations. The block and the unblock write on Midaz. The information request only reads.

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

1. The executor reads the active accounts of the subject. A subject with no active account gets `NONE` with `NO_CLIENT`.
2. It applies the branch and account restriction of the order.
3. It blocks a salary account only when the order allows salary accounts.
4. It blocks own funds only. An account in overdraft counts as 0.
5. It sends one write to Midaz. The write has one leg for each source account, and all legs go into the block account of the order.

| Outcome | `effect` | `reasonCode` |
| - | - | - |
| The block covers the amount still open on the order. | `FULL` | `BLOCKED_TOTAL` |
| The block covers less than that amount. | `PARTIAL` | `BLOCKED_PARTIAL` |
| No funds are available. | `NONE` | `NO_BALANCE` |

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

The unblock releases funds of a parent block order, identified by `parentOrderId`.

* Without a parent, the result is `NONE` with `PARENT_UNRESOLVED`, and the executor writes nothing.
* When the parent has no known effect yet, the executor waits. At the deadline of the order, it hands the order to a human decision.
* The executor reads the block account of the parent when it runs the order. It releases the smallest of three amounts: the amount that the order asks, the remaining balance of the parent, and the balance of the block account.
* When the release amount is 0, the result is `NOTHING_TO_RELEASE`.
* The executor returns the funds to each origin account of the parent block.
* When a subject account is a salary account, the order goes to a human decision.

<h3 id="information-request">
  Information request (REQUISICAO\_INFORMACAO)
</h3>

The executor reads the balances of the subject and writes nothing on the ledger. It answers two totals: the blockable total and the blockable total of salary accounts.

* A subject with at least one active account gets `FULL` with `INFO_FULFILLED`.
* A subject with no active account gets `NONE` with `INFO_NON_CLIENT`.
* An order that names a branch goes to a human decision.
* An order that names an account the subject does not hold goes to a human decision.

<h2 id="ledger-semantics">
  Ledger semantics
</h2>

***

### Block account

Each block order has its own block account in Midaz. The alias of the block account has the prefix `@block_sisbajud_` and then the 32 lowercase hexadecimal digits of the block order ID. An unblock finds the account through its `parentOrderId`.

The account type of a block account is `sisbajud_block`. If your ledger validates account types, register `sisbajud_block` as an account type.

### Directions

* A block decreases the subject accounts and increases the block account.
* An unblock decreases the block account. Its write has one source leg: the block account.

A block moves the amount from the available balance of each subject account to the available balance of the block account.

### Idempotency

Each write carries the `X-Idempotency` header and `X-TTL: 604800`, which is seven days. Midaz keeps the idempotency key of a write for that time. The key is `orderId:orderRevision`. A redelivery of the same order revision sends the same key.

<h2 id="uncertain-writes">
  Uncertain writes
</h2>

***

When Midaz answers a write without proof of its effect, the outcome is `INDETERMINATE`. The executor reads the ledger again before each heartbeat. It sends a heartbeat result to the Mensageria every `EXECUTOR_HEARTBEAT_EVERY`.

The order goes to a human decision at the first of two limits:

* `EXECUTOR_HUMAN_DECISION_AFTER_BEATS` heartbeats without a change. The default is 3.
* The order deadline minus `RESPONSE_DEADLINE_MARGIN`.

The executor then records a human decision. In the human-decisions list it has `humanDisposition` `HELD_MONEY_MOVED`, and the executor posts no final answer. The heartbeats continue, with `executionState` and `effect` both `INDETERMINATE`.

### Operations that the executor did not write

The orphan check reads the operations of each block account over `EXECUTOR_ORPHAN_RECONCILE_WINDOW`. The default is `48h`. The executor reports an operation as an orphan when its transaction has no `metadata.code`, or has a code that the executor did not record. This step only detects. It changes nothing on the ledger.

<h2 id="accounting-routes">
  Accounting routes
</h2>

***

Accounting routes are optional, per organization. The executor reads them from the tenant documents `routing.organizations` and `routing.ledger_bindings` in the Systemplane. With `SYSTEMPLANE_ENABLED` off, the executor writes without routes.

When a write cannot go out because of its configuration, the executor defers it. Midaz has applied nothing, so the order waits, and a later delivery sends the same write with the same idempotency key. These conditions defer a write:

* The executor cannot resolve the accounting routes of the write.
* Midaz refuses the accounting routes of the write: `422` with code `0113`, `0114`, `0116`, `0117`, `0118`, `0119`, `0152`, or `0157`, or `404` with code `0105`.

Fix the configuration before the order deadline. `GET /v1/admin/ledger-routing/preflight` checks the configuration before you turn on routes.

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

***

The executor calls the Midaz ledger at the `baseUrl` of each institution, with the token of that institution. Give the credentials of the institution access to these operations:

| Purpose | Midaz operation |
| - | - |
| Block | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/block` |
| Unblock | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/unblock` |
| Create a block account | `POST /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts` |
| Find an account by alias | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts?alias=` |
| Read an account | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts/{accountId}` |
| Read the balances of an alias | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts/alias/{alias}/balances` |
| Read the operations of a block account | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/accounts/{accountId}/operations` |
| Read a transaction | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions/{transactionId}` |
| Find the transactions of a write | `GET /v1/organizations/{organizationId}/ledgers/{ledgerId}/transactions?metadata.code=` |

The executor finds the accounts of a subject through the Midaz CRM. With `crmMode` `legacy`, it calls `GET /v1/aliases?document=` at `crmBaseUrl`. With `crmMode` `embedded`, it calls `GET /v2/organizations/{organizationId}/instruments?document=` at `baseUrl`.


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