Skip to main content
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 describes the setup.

Order lifecycle


  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

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

Fetch answers

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. The reasonCode of each operation is in the sections below.

Operations


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

Block (BLOQUEIO)

  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.

Unblock (DESBLOQUEIO)

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.

Information request (REQUISICAO_INFORMACAO)

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.

Ledger semantics


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.

Uncertain writes


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.

Accounting routes


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.

Midaz calls


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