> ## Documentation Index
> Fetch the complete documentation index at: https://jephalabs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Movement Authorization Model

> Which decisions authorize a movement, when they take effect, and what they do not prove

# Movement Authorization Model

Authorization in QTG is a sequence of different decisions, not one boolean or one dashboard click. A later decision never makes an earlier control unnecessary.

<Note>
  **Current** describes behavior in this release.
</Note>

## The authorization chain

| Decision                        | Current owner and effect                                                                                                                                                                                                                                                                                                                                                                                            | What it does **not** authorize                                                                                                                                                                       |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. Allowlist registration       | An active `allowed_addresses` row makes an address eligible for the relevant QTG address gate. A newly added or reactivated row can be in a cooling period, so it is not yet usable by a fund-moving dispatch.                                                                                                                                                                                                      | It does not create a movement, approve a transfer, prove an exchange has saved the address, or bypass a later recheck.                                                                               |
| 2. Trusted-target status        | An active, usable trusted EVM target is an exact chain, destination, and token tuple in the policy-target registry. It is a subset of the QTG allowlist and can contribute `auto_eligible` evidence.                                                                                                                                                                                                                | It does not make a non-allowlisted address allowed, approve a movement by itself, or apply to CEX-only routes.                                                                                       |
| 3. Route-template registration  | Registering a template validates and persists a new immutable graph version. Reusing the same template/version is rejected; changing route shape requires another version.                                                                                                                                                                                                                                          | It does not select a recipient or amount for a particular transfer, create a movement, or grant execution authority.                                                                                 |
| 4. Movement creation            | Creation resolves the selected template version and bindings, validates the graph and applicable on-chain intent addresses, compiles the request, pins a `compiled_plan_hash`, and persists canonical authorization facts for new movements before normally parking it in `PENDING_APPROVAL`.                                                                                                                       | It does not prove a CEX destination is currently accepted by the exchange, reserve funds, or submit anything.                                                                                        |
| 5. Manual or automatic approval | The Dashboard first obtains a DB-only, digest-bound Approval Brief. Manual approval locks the pending movement, rebuilds that brief, and verifies the client-echoed plan hash and, in enforce mode, the captured brief digest. Existing auto-approve hooks can approve a bounded eligible movement during creation; their result is separately recorded. Approval then performs its reservation and binding checks. | It does not replace the dispatch-time hash, authorization-facts, QTG allowlist, recipient, or provider checks. A policy trace or pending guard is evidence, not final approval authority on its own. |
| 6. Dispatch revalidation        | Before a side-effecting executor runs, the dispatcher recomputes the compiled-plan hash, optionally enforces the persisted authorization-facts digest, and runs the applicable QTG address guard, including cooling-period enforcement. Executors then perform their route-specific preflight and submit checks.                                                                                                    | It cannot turn a failed or unknown provider operation into a safe retry, or recall a transfer that an external provider has already accepted.                                                        |

The operational path is therefore:

```mermaid theme={null}
flowchart LR
    A["Register allowed address"] --> T["Optionally mark exact EVM target trusted"]
    T --> R["Register immutable template version"]
    R --> C["Create and compile movement"]
    C --> P["Manual or existing auto approval"]
    P --> D["Dispatch-time revalidation"]
    D --> S["Provider submit"]

    A -. "cooling or inactive" .-> X["not dispatchable"]
    C -. "CEX-only: no provider whitelist read" .-> P
    D -. "hash or local guard drift" .-> X
```

## 1. Allowlist registration is configuration, not approval

**Current.** QTG records local destination policy in its allowlist. Address matching is normalized by chain family; relevant fund-moving guards require the row to be active and past any configured cooling period. Removing or revoking a row is a forward-looking policy change: it can stop a later recheck, but it is not an emergency stop for an operation that already passed its pre-submit check.

For on-chain action types, creation performs the applicable local source/destination check, and dispatch repeats it. The exact posture depends on the action: some signer-bound-source lanes check only the destination, while strict lanes check both endpoints.

For CEX withdrawals, do not infer the timing from the on-chain path. The current CEX-specific local address check runs in the dispatcher, after approval, not at movement creation. The detailed three-gate behavior, chain-family trap, cooling semantics, and exchange address-book limitations are in [Allowlist Operator QA](/reference/allowlist-operator-qa).

## 2. A trusted target narrows automation; it does not broaden destination authority

**Current.** The policy plane evaluates trusted targets only for EVM receiver actions. A trusted target must match the exact normalized chain ID, destination address, and token contract/native identifier, be active, and be past its own usable-after time. It is meaningful only after the destination has passed the QTG allowlist layer.

The resulting policy trace can say that a movement is `auto_eligible`, but the existing Free or Pro auto-approve hook still makes the actual automatic-approval decision. A target that is merely allowed normally remains a manual-approval candidate. CEX-only movements do not become denied or trusted through this EVM target policy.

Use the [Approval/Risk Policy Guide](/guide/approval-risk-policy) to configure bounded automation. The [Approval/Risk Policy Plane](/concepts/approval-risk-policy-plane) explains the trace vocabulary and why it cannot override dispatch guards.

## 3. A route template is an immutable route definition, not a transfer

**Current.** A template version fixes the validated graph, nodes, edges, completion policy, and risk controls from which a movement is compiled. Registering an existing `(template_key, version)` fails rather than modifying that version. The template record still has limited administrative fields such as namespace and auto-approve caps; those are not a mutation of a persisted plan-version graph.

Template registration has no transfer amount, live destination, approval, signing, or provider call. The internal Template Registration Guide covers the exact graph, executor, and signer-selector contracts; it links back to this model for the authority boundary.

**Current — configuration maker/checker.** Allowlist and template writes are configuration proposals. The direct remote routes (`POST /v3/plan-templates`, the dashboard allowed-address mutations, and the template `auto_approve_enabled` / `daily_cap_*` fields) always return `409 CONFIG_PROPOSAL_REQUIRED`. With `MG_CONFIG_REMOTE_MUTATION_MODE=proposal_only`, an admin or operator creates an `allowlist.*` or `route_template.register` proposal and a different admin applies it against its proposal digest; the maker credential and principal cannot apply their own proposal. Agent-authority, auto-approve-policy, and template auto-approve cap (`route_template.auto_approve`) proposals additionally require an HMAC admin maker. The only non-proposal writer is the audited host-maintenance CLI path (`--direct-maintenance`, gated by `MG_CONFIG_DIRECT_MAINTENANCE_ENABLED=true` and `MG_CLI_AUTH_REQUIRED=true`).

## 4. Movement creation compiles an instance and collects evidence

**Current.** Creation resolves one template version and its bindings using the supplied request inputs, validates the graph and template constraints, creates request nodes, and pins the resulting `compiled_plan_hash`. The movement begins pending approval unless an existing eligible auto-approve hook successfully approves it in the creation transaction. Agent-originated movements stay manual even when an auto-approve hook is enabled.

The creation path also persists a policy-trace result and, for newly created movements, canonical authorization facts plus their digest. The facts projection reconciles route-specific values that the executor will consume; conflicting CCIP or CEX withdrawal authority tuples fail before movement persistence. The policy trace is useful evidence about allowed/trusted EVM targets and other preview layers, but it is neither a signed authorization fact nor a replacement for approval and dispatch guards.

Creation-time address validation is deliberately action-specific:

* On-chain actions covered by the central guard validate their applicable intent addresses before the movement is persisted.
* A CEX-only template does not run the CEX local-address or exchange address-book check at creation. A created movement can still fail its first CEX dispatch gate.

## 5. Approval permits the compiled movement to become runnable

**Current — manual.** The approve route locks a `PENDING_APPROVAL` movement, requires the reviewed `compiled_plan_hash` echoed by the client, and rejects a mismatch. When maker-checker is enabled and both authenticated key identities are available, the creator and approver keys must differ. Approval then verifies binding availability, applies reservation and cap controls, stamps signer metadata where needed, makes frontier nodes ready, and records the approval state.

**Current — automatic.** Existing auto-approve hooks are evaluated during creation for eligible non-agent movements. They still run the approval/reservation path; a hook decision is not a bypass. The trusted-target policy trace can inform eligibility, but does not alone approve a transfer.

### The current dashboard review boundary

**Current.** Opening Dashboard approval requests a stateless, DB-only Approval Brief for the visible options. It displays the source, destination, asset/token identity, amount semantics, network, debit/fee posture, completion assurance, policy posture, every phase-labelled guard verdict, the compiled-plan hash, authorization-facts digest, and brief digest. A late response is discarded if the dialog, movement, or options have changed; digest-bound controls are disabled while a brief is loading.

Confirmation submits the exact digest captured for the reviewed options. Approval rebuilds the brief while holding the movement lock. `MG_AUTHORIZATION_PROJECTION_MODE=shadow` is the rollout default: the Dashboard still captures and echoes the digest, but external/manual API callers are not rejected solely for omitting it until operators explicitly enable `enforce`. In enforce mode, a missing or stale digest and legacy rows without bound authorization facts fail closed.

The brief deliberately labels policy `unknown` and dispatch-phase guards `pending` instead of turning them green. Server `confirmation_allowed` decides whether the current brief may be confirmed; dispatch remains the authoritative point for the checks labelled pending. A reviewed brief therefore proves which DB-derived facts and caveats the operator confirmed, not that the provider will accept the transfer or that later state cannot drift.

## 6. Dispatch revalidates before the executor can move funds

**Current.** The dispatcher recomputes the compiled-plan hash from persisted plan rows before it invokes a side-effecting executor. Drift fails the node before executor preflight, signing, or submission. When authorization projection is in `enforce`, it also rebuilds the canonical facts and requires their persisted digest to match. It then repeats the applicable local QTG allowlist check with cooling-period enforcement.

For a `cex_withdrawal`, the sequence is especially important:

1. The dispatcher requires a usable local QTG allowlist match for the approval-pinned destination.
2. The CEX executor checks that its literal configured destination remains pinned to the movement intent before submission.
3. If the adapter supports a saved-address-book listing, executor preflight reads it and rejects a mismatch. Some venues expose no usable listing API; QTG logs that absent pre-read and the venue may still enforce verified addresses when the withdrawal is submitted.

No provider whitelist lookup occurs at movement creation or manual approval. A CEX movement can therefore be created and approved but fail later at dispatch because the local allowlist cooled/revoked, the literal pin diverged, the exchange address book disagreed, or the venue rejects the withdrawal at submit time.

After a submission is ambiguous, observe and recovery reconcile provider state; they do not create a new approval or make an ambiguous side effect safe to rebroadcast. See [Movement Lifecycle](/concepts/movement-lifecycle) for the request and node-state flow.

## Current consuming services

These are the current source owners of the authorization boundaries above:

| Boundary                                                                               | Current consuming service                                                                                                                                                                       |
| -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Template graph/version validation and persistence                                      | `qtg.application.services.templates.create_plan_template`                                                                                                                                       |
| Movement creation, compilation, and on-chain creation-time address validation          | `qtg.application.services.movements.create_movement_uncommitted` and `_validate_onchain_intent_addresses`                                                                                       |
| Allowed/trusted EVM preview evidence                                                   | `qtg.application.services.policy_plane.evaluate_policy_preview`                                                                                                                                 |
| Canonical authorization facts and Approval Brief                                       | `qtg.application.services.authorization_facts` and `qtg.application.services.approval_brief`                                                                                                    |
| Manual plan-hash/brief-digest approval and reservation transition                      | `qtg.application.services.movements.approve_movement` and `apply_movement_approval_uncommitted`                                                                                                 |
| Pre-side-effect compiled-hash, authorization-facts, and local QTG address revalidation | `qtg.application.services.dispatch.dispatch_ready_nodes`, `_assert_compiled_plan_hash_unchanged`, `assert_authorization_facts_current`, `validate_movement_addresses`, and `is_address_allowed` |
| CEX literal-pin and exchange address-book preflight                                    | `qtg.infrastructure.executors.cex.withdrawal_action.CexWithdrawalActionExecutor.preflight`                                                                                                      |

## Operator checklist

Before approving or automating a route, establish each of these separately:

1. The local QTG allowlist row matches the action's required endpoint and is usable now.
2. A trusted target, if used, matches the exact EVM chain/address/token tuple and is only an automation input.
3. The selected template version is the intended immutable route shape, registered through an applied configuration proposal.
4. The Approval Brief shows the intended route, destination, asset/token, amount semantics, policy posture, and pending guard phases.
5. The movement's compiled-plan hash and the brief digest are the values captured for the reviewed options.
6. The approval mode, reservation, and caps permit this instance.
7. The dispatch-time checks can still reject the movement; for CEX routes, provider-side whitelist evidence may be unavailable until dispatch or submit.

Treat a failure at any step as a reason to correct or reject the relevant layer, not as a reason to bypass it with a broader auto-approve policy.
