> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/cross-chain-the-distributed-register/authorization-before-execution.md).

# Authorization before execution

The principle that keeps satellites honest is that they never decide compliance. A satellite executes a transfer only against an authorization that the reference chain has already issued for that exact transfer. Compliance is a precondition, established where the complete distribution of the asset is known. It is not a reconciliation performed afterward.

The authorization is an object called a compliance validation. This page describes what it contains, how it is requested, how its amount is decided and what issuing it writes on the register.

## Three steps

```mermaid
sequenceDiagram
    participant R as Sender identity, or an agent
    participant MC as ModularCompliance
    participant T as Token
    participant G as ERC-7786 gateway
    participant L as T-REX Lite

    R->>MC: requestTransferValidation(from, to, min, max, spender)
    MC->>MC: route, caller, deadlines, amount, spender
    MC->>MC: record the validation, reserve its amount
    MC->>T: dispatch, one message per satellite involved
    T->>G: compliance validation
    G->>L: deliver
    Note over L: the transfer executes against the validation
    L->>G: settlement notification
    G->>T: deliver
    T->>MC: handleSettlement
    MC->>MC: record the change of ownership
```

1. **Authorize.** The transfer is requested on the reference chain. The compliance evaluates it against the global state of the asset and, if it passes, issues a validation for exactly this transfer.
2. **Execute.** The validation travels to the satellite. T-REX Lite executes the transfer against it and consumes it.
3. **Settle.** T-REX Lite notifies the reference chain, which records the change of ownership.

A transfer that would breach the rules of the asset never executes anywhere. It is refused at step 1.

## The validation

| Field                    | Meaning                                                                                                                       |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `validationId`           | A number, unique for the asset and increasing by one. It identifies the validation on both sides and is used once.            |
| `from`                   | The sender's wallet, on a satellite, as an interoperable address.                                                             |
| `to`                     | The recipient's address, as an interoperable address: on the same satellite, on another satellite, or on the reference chain. |
| `spender`                | The party allowed to execute the transfer for the sender. Empty means the sender alone.                                       |
| `amountMin`, `amountMax` | The inclusive range in which the executed amount must fall.                                                                   |
| `token`                  | The address of the asset on the reference chain.                                                                              |
| `expiry`                 | The time before which the satellite must execute.                                                                             |
| `reconciliationWindow`   | How long the reference chain keeps the reservation after the expiry, waiting for the settlement.                              |

The compliance keeps a record of every validation it has issued, permanently. Any settlement that arrives, at any time, can be classified against what was issued.

## Requesting a validation

`ModularCompliance.requestTransferValidation(from, to, requestedMin, requestedMax, spender)` returns the identifier of the validation it issues.

The compliance answers five questions, in order.

| Question                 | What is checked                                                                                                                    | Refused with                                                                     |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| **Where is this going?** | Both addresses are well-formed. The sender is on a satellite chain.                                                                | `NonCanonicalInteroperableAddress`, `SenderNotOnSatellite`                       |
| **May the caller ask?**  | The sending wallet resolves to an identity. The caller is that identity, or holds the `AGENT` role.                                | `UnverifiedWallet`, `NotAuthorizedForWallet`                                     |
| **By when?**             | The validity window is set. Each satellite involved has a reconciliation window and is not paused for issuance.                    | `ValidityWindowNotSet`, `ReconciliationWindowNotSet`, `ValidationIssuancePaused` |
| **How much?**            | The recipient is eligible. The range is narrowed to what the wallet can send and to what the rules allow. Something is left of it. | `UnverifiedWallet`, `EmptyValidationRange`, `ZeroValue`                          |
| **Who executes?**        | If a spender is named, every `SPENDER` module accepts it.                                                                          | `ValidationSpenderRefused`                                                       |

When the validation is sent, the token requires every satellite involved to be open for the asset. Otherwise the whole request reverts with `ChainNotOpen` and nothing is recorded.

### Who asks

A wallet on a satellite does not request a validation for itself. Its identity does, on the reference chain, because the identity is where authority over the holder's positions lives. An agent holding the `AGENT` role can also request a validation on behalf of a holder.

### The sender is on a satellite

A validation always moves tokens out of a satellite wallet. The reason is structural: the T-REX Lite that executes a validation has to hold the position it moves. A balance on the reference chain stays free to leave between the issuance and the settlement, so nothing would guarantee that it is still there.

Tokens on the reference chain reach a satellite by movements that start on the reference chain, not through a validation: a delegation-out for one's own position, a direct transfer or a direct mint to someone else's wallet on a satellite. See [Movement types](/cross-chain-the-distributed-register/movement-types.md).

### The recipient

| The recipient is                    | Chains that receive the validation            | Settlement                                                          |
| ----------------------------------- | --------------------------------------------- | ------------------------------------------------------------------- |
| On the same satellite as the sender | That satellite                                | One notification                                                    |
| On another satellite                | Both satellites. The sending one consumes it. | Two notifications, one from each                                    |
| On the reference chain              | The sender's satellite                        | One notification. The recipient is credited on the reference chain. |

## A range, not an amount

The caller proposes a range, typically an amount and a tolerance around it. A transfer that settles a trade on a venue does not always execute for the amount first intended, and a fixed amount would fail whenever it differs by one unit.

The compliance narrows the range. It never widens it.

```mermaid
flowchart LR
    A["Requested range<br/>min to max"] --> B["Cap the maximum at what<br/>the sending wallet can still send"]
    B --> C["Cap the maximum at the smallest<br/>amount the rules allow"]
    C --> D{"Is the minimum still<br/>at or below the maximum?"}
    D -- "yes" --> E["Validation issued<br/>for the narrowed range"]
    D -- "no" --> F["Refused"]
```

1. **What the wallet can send.** The maximum is capped at the wallet's bridged position less what earlier validations already reserve from it. A wallet cannot obtain validations for more than it holds.
2. **What the rules allow.** Each `RULE` module answers the largest amount it allows. The maximum is capped at the smallest answer.
3. **What is left.** If the minimum the caller asked for is above the narrowed maximum, no validation is issued.

Because the satellite may execute any amount inside the range, the register treats the maximum as the amount that moves, for every rule, until the transfer settles.

### Between two wallets of one identity

When the sender and the recipient belong to the same identity, the movement changes no position. The rules about distribution are not asked and nothing is reserved against the identity. The wallet's own limit and the spender policy still apply: who executes is not a question about distribution.

## What issuing writes

Issuing a validation changes the state of the register, before anything has happened on the satellite.

| Written                       | Where               | Effect                                                                                                                                                 |
| ----------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| The record of the validation  | `ModularCompliance` | Its terms, its deadlines and its status, `Pending`. Kept permanently.                                                                                  |
| The pending amounts           | `ModularCompliance` | The maximum is added to what is promised out of the sender's identity and to what is promised to the recipient's identity. Rules count it from now on. |
| The reservation on the wallet | `Token`             | The maximum is reserved against the sending wallet's bridged position. It cannot be promised to another validation.                                    |
| The route                     | `Token`             | The gateway each message went out through is recorded for this validation. Its settlement is accepted from that gateway only.                          |

The event `TransferValidationIssued` carries the identifier, both addresses, the spender, the final range, the expiry and the reconciliation window.

The reservation is what makes concurrent requests safe. Two validations competing for the last room under a cap cannot both be issued: the first one takes the room when it is issued, and the second one finds none. What happens to the reservation afterward is described in [The dual-state lifecycle](/cross-chain-the-distributed-register/the-dual-state-lifecycle.md).

## The settings

| Setting               | Function                                      | Scope         | Effect when unset                           |
| --------------------- | --------------------------------------------- | ------------- | ------------------------------------------- |
| Validity window       | `setDefaultValidityWindow(duration)`          | The asset     | No validation can be issued.                |
| Reconciliation window | `setReconciliationWindow(chainKey, duration)` | One satellite | No validation can be issued for that chain. |
| Issuance pause        | `setIssuancePaused(chainKey, paused)`         | One satellite | Not paused.                                 |

All three require the `COMPLIANCE_MANAGER` role. The expiry of a validation is the time of issuance plus the validity window. The reconciliation window is fixed for a validation when it is issued, so a later change never moves a deadline that is already running. A transfer between two satellites takes the larger of the two chains' windows.

## Why a satellite cannot cheat the register

* **It cannot transfer without a validation.** T-REX Lite executes a transfer only against a stored validation, and mints only on an instruction from the reference chain or on a proof of burn from a peer.
* **It cannot reuse a validation.** A validation is consumed by its execution, and the register accepts one settlement per validation and per chain.
* **It cannot exceed the validation.** A settlement for an amount outside the issued range is refused.
* **It cannot substitute the parties.** A settlement must name the wallets and come from the chain and the gateway that were recorded at issuance.
* **It cannot invent tokens that then circulate.** A wallet obtains a validation only up to the position the register records for it.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/cross-chain-the-distributed-register/authorization-before-execution.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
