Order lifecycle
- Notice. The Streaming Hub posts an execution notice to the webhook listener of the plugin. The notice carries the order ID and the order revision, not the order.
- Verification. The plugin verifies the HMAC signature of the delivery. It stores each signed notice before it answers.
- Fetch. The plugin gets the order with
GET /v1/sisbajud/execution/orders/{orderId}on the execution API of the Mensageria. - Owner check. Before its first write, the plugin checks that it owns the institution of the order.
- Execution. On its next cycle, the plugin runs the operation on Midaz.
- Result. The plugin posts the result with
POST /v1/sisbajud/execution/orders/{orderId}/execution-results.
Webhook answers
The plugin accepts a delivery with a timestamp outside
EXECUTOR_HUB_WEBHOOK_MAX_SKEW_SEC, and logs a warning.
Fetch answers
Owner check
The plugin 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 plugin writes nothing and raises an alarm.
- If the institution has no configuration on this plugin, the order goes to a human decision.
Execution cycle
The plugin runs one cycle everyEXECUTOR_TICK_EVERY. The default is 30s. Each cycle runs three steps in this order:
- Ingest. Runs the accepted notices.
- Orphan check. Looks for operations on the block accounts that the plugin did not write.
- Monitor. Sends a heartbeat for each write that has no known outcome.
Results
The plugin stores each result in an outbox before it posts it. Each post carries theX-Idempotency header. When a post fails with a transient error, the plugin posts the same result again after a wait, up to EXECUTOR_RESULT_MAX_ATTEMPTS attempts. The default is 12.
After the last attempt, the plugin parks the result, records a human decision, and raises an alarm. It does not post a parked result again, and the subsequent versions of the same order wait behind it. A platform administrator re-arms the result. Operating Plugin SISBAJUD describes the route.
The
reasonCode of each operation is in the sections below.
Operations
The block and the unblock write on Midaz. The information request only reads.
Block (BLOQUEIO)
- The plugin reads the active accounts of the subject. A subject with no active account gets
NONEwithNO_CLIENT. - It applies the branch and account restriction of the order. Branch and account restriction gives the rules.
- It blocks a salary account only when the order allows salary accounts.
- It blocks own funds only. An account in overdraft counts as 0.
- 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.
A block order can carry a minimum amount. When the total that the plugin can block is below that minimum, it writes nothing and hands the order to a human decision.
Branch and account restriction
The plugin reads the branch and the account number of each account from the CRM instruments of the subject. WithcrmMode embedded, the branch is bankingDetails.branch and the account number is bankingDetails.account. With crmMode legacy, the CRM gives neither.
- An order that names a branch goes to a human decision when an account that can be the named one has an unknown or ambiguous branch.
- An order that names an account number blocks the accounts whose number matches. It also blocks an account whose number is unknown or ambiguous, up to the order amount, because that account can be the one that the court named. The accounts whose number matches come first. With
crmModelegacy, no number is known, so every account that passes the branch rule can be blocked. - An order with an account number and no branch goes to a human decision when two or more accounts match.
- With an account number, the result is
NONEwhen every account number is known and none matches.
Unblock (DESBLOQUEIO)
The unblock releases funds of a parent block order, identified byparentOrderId. The plugin uses the parent block’s recorded origin account as the release destination. If it cannot safely determine one destination, it requires a human decision rather than guessing.
- Without a parent, the result is
NONEwithPARENT_UNRESOLVED, and the plugin writes nothing. - When the parent has no known effect yet, the plugin waits. At the order deadline minus
RESPONSE_DEADLINE_MARGIN, the order goes to a human decision. If the order has no deadline, it goes to a human decision at once. - The plugin 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. - When a subject account is a salary account, the order goes to a human decision.
Information request (REQUISICAO_INFORMACAO)
The plugin reads the balances of the subject and writes nothing on the ledger. If the subject is a client but does not own the specified account, the plugin requires a human decision rather than reporting that the subject is not a client.- A subject with at least one active account gets
FULLwithINFO_FULFILLED. - A subject with no active account gets
NONEwithINFO_NON_CLIENT. - An order that names a branch goes to a human decision.
searchBalance), the result carries two totals: the blockable total and the blockable total of salary accounts. A subject with no active account gets 0.00 in both.
Direct channel
On the direct channel, the institution’s own system sends judicial orders to the plugin, and the Mensageria is not involved. The plugin stores each order, runs it on Midaz, and keeps the results. The institution reads the results and answers the court itself. The plugin serves the direct channel only when it runs in executor mode, with one tenant, and
PLUGIN_AUTH_ENABLED on. Otherwise the five direct routes answer 501.
A platform administrator switches an institution to the direct channel with PUT /v1/institutions/{institutionId}/channel. The switch needs all of these:
- The plugin owns the institution.
- The stored institution code is the 8-character CNPJ root of the responsible grouping.
- The institution has no open order, and no block of the institution still holds money.
422 SBJ-0025 on a direct order.
The results feed delivers each result at least once. Deduplicate by
orderId, orderRevision, and executionVersion. Submit an unblock or a transfer only after the 202 of its parent block.
The direct channel takes BLOCK, UNBLOCK, TRANSFER, INFO, and INTERRUPT. A transfer moves funds from the block account of its parent to the judicial deposit account of the institution. An interruption stops a permanent block and keeps what the block already holds. DIRECT_PERMANENT_BLOCK_ENABLED decides whether the channel takes a new permanent block. With the default, it refuses one with 422 SBJ-0027.
A permanent block keeps blocking new credits of the subject, up to the order amount. The plugin reads those credits from the Midaz ledger events. It lasts one year from receipt, or until the court date when the order gives one, and never more than one year. When the term ends, the block stops taking new credits and keeps what it already holds. An interruption, a transfer or an unblock of the remainder, or a cancellation closes it. When a later block of a permanent block keeps failing, the plugin parks the attempt, raises an alarm, and stops taking new credits for that block until a platform administrator resolves the attempt. A direct order that fails on every attempt, or reaches its cut while the ledger fails, is parked too. Its read shows parked true.
The machine roles order-submitter and result-reader call these routes. Operating Plugin SISBAJUD describes them.
Erase a direct-channel order
A platform administrator erases one concluded direct-channel order withPOST /v1/admin/direct/orders/{orderId}/erase, for an LGPD request from the data subject or at the end of retention. POST /v1/admin/direct/purge lists the orders that can be erased now and changes nothing. Both operations need a user token with no tenant, and they answer only on a single-tenant installation.
After the erase, nobody can read the content submitted with the order again: the order body and the document number of the person or company that the order targets. The erase cannot be undone. Your clientOrderId and externalReference become tokens. A lookup by the original externalReference still finds the erased order, with its content hidden.
The erase does not remove:
- the court protocol and the sequence numbers of the order;
- the plugin’s ledger journal, with its amounts, and the Midaz transactions;
- the results already in the results feed, and what your system already read from it;
- the audit entry of the erase;
- backups taken before the erase. After you restore one, erase the order again.
EXECUTOR_DIRECT_PURGE_ELIGIBLE_ALARM_AFTER (default 168h), the plugin logs an error so that an administrator reviews it.
Ledger semantics
Block account
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.
- A transfer decreases the block account of its parent and increases the judicial deposit account.
- An unblock decreases the block account. Its write has one source leg: the block account. It releases funds to the recorded origin account, or requires a human decision when one safe destination cannot be determined.
Idempotency
Each write carries theX-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, so 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 plugin reads the ledger again before each heartbeat. It sends a heartbeat result to the Mensageria every EXECUTOR_HEARTBEAT_EVERY, until the Mensageria answers that the order revision is superseded.
The order goes to a human decision at the first of two limits:
EXECUTOR_HUMAN_DECISION_AFTER_BEATSheartbeats without a change. The default is 3.- The order deadline minus
RESPONSE_DEADLINE_MARGIN.
humanDisposition HELD_MONEY_MOVED. The heartbeats continue, with executionState and effect both INDETERMINATE.
Ledger down at the cut
The cut of an order is its deadline minusRESPONSE_DEADLINE_MARGIN. When Midaz fails for an order of the Mensageria at or after the cut, and no court result of that revision waits in the outbox, the plugin stops its retries. It records a human decision and sends no result. Check the ledger and answer the court yourself before the deadline. Otherwise the Mensageria records a non-response.
After a person answers
Take a revision that was handed to a person at its cut, or that a person resolved as effect-acknowledged or proven-no-effect. When its write lands on Midaz afterwards, the plugin sends noFULL or PARTIAL result for it. It records the effect and raises an alarm. The court gets only the answer of the person, so reconcile a late effect on the ledger yourself.
Operations that the plugin did not write
The orphan check reads the operations of each block account overEXECUTOR_ORPHAN_RECONCILE_WINDOW. The default is 48h. The plugin reports an operation as an orphan when its transaction has no metadata.code, or has a code that the plugin did not record. This step only detects. It changes nothing on the ledger.
Accounting routes
Accounting routes are optional, per organization. The plugin reads them from the tenant documents
routing.organizations and routing.ledger_bindings in the Systemplane. With SYSTEMPLANE_ENABLED off, the plugin writes without routes.
With routing.organizations at schemaVersion 2, each organization carries its own routes for each flow and the list of ledgers that post with them. The plugin then does not read routing.ledger_bindings. A write to a ledger that is not on the list of its organization goes out without routes.
When a write cannot go out because of its configuration, the plugin 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 plugin cannot resolve the accounting routes of the write.
- Midaz refuses the accounting routes of the write:
422with code0113,0114,0116,0117,0118,0119,0152, or0157, or404with code0105.
GET /v1/admin/ledger-routing/preflight checks the configuration before you turn on routes.
Midaz calls
The plugin 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 plugin 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.
