Skip to main content

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.
Current describes behavior in this release.

The authorization chain

The operational path is therefore:

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.

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 to configure bounded automation. The 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 for the request and node-state flow.

Current consuming services

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

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.