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

# Getting Started

> Single-page setup reference for QTG — auth, schema, and verification

# Getting Started

A single-page consolidated reference for getting QTG running, authenticated, and verified. If you want a guided multi-step walkthrough instead, use [`docs/quickstart/`](quickstart/) (4 documents, \~30 minutes end-to-end).

## Supported platforms

| OS                                | Status                             |
| --------------------------------- | ---------------------------------- |
| Linux (kernel ≥ 5.4 with systemd) | Primary deployment target          |
| macOS (≥ 13 Ventura)              | Dev workstation                    |
| Windows                           | Not supported — use WSL2 (= Linux) |

Toolchain:

* Python 3.14+
* [uv](https://docs.astral.sh/uv/) package manager
* PostgreSQL (Docker Compose provided)
* Exchange API keys (live mode only)
* AWS KMS key (EVM proving lanes) or 1Password CLI (dev quickstart)

## Quickstart

```bash theme={null}
git clone https://github.com/jephalabs/quant-transfer-guard
cd quant-transfer-guard
cp .env.example .env

uv venv
source .venv/bin/activate
uv sync --extra dev

uv run uvicorn qtg.main:app --reload --port 8100
```

Minimum environment variables:

* `MG_DATABASE_URL`
* `MG_CALLBACK_HMAC_SECRET`
* `MG_CALLBACK_ALLOWED_HOSTS_CSV`

| File           | Purpose                                                                         |
| -------------- | ------------------------------------------------------------------------------- |
| `.env.example` | Full configuration template (`MG_*` prefix). Start with `cp .env.example .env`. |
| `.env`         | Real local values. **Do not commit.**                                           |

### Docker

```bash theme={null}
docker volume create quant-transfer-guard_qtg-postgres-data   # first install only; the data volume is external
docker compose -f infra/docker-compose.yml up -d postgres qtg-mainnet qtg-dashboard
```

Name the services you want. Starting everything also starts `qtg-testnet` against the
same database, and whichever network bucket was not migrated fails its boot check.

The Postgres data volume is `external` so that `docker compose down -v` cannot delete
it. Compose therefore refuses to start when it is absent, which is the intended signal
— see `docs/quickstart/01-local-setup.md`.

### Dashboard

```bash theme={null}
cd frontend && npm install && npm run dev   # port 5173, proxy → localhost:8100
```

The dashboard provides Gateway balances, CCTP transfer tracking, movement management, and route lookup.

## Execution modes

| `MG_WORKERS_ENABLED` | Behavior                                                                                 |
| -------------------- | ---------------------------------------------------------------------------------------- |
| `false`              | Dev mode — API / DB / template registration only. No real exchange or chain calls.       |
| `true`               | Workers (dispatcher, observer, recovery, callback, etc.) run. Real integrations execute. |

## Signer backends

The default proving-lane signer is AWS KMS. For dev or for evaluating QTG without AWS, a local private-key signer provides two key sources:

* **1Password CLI** (recommended for local) — keys fetched on demand from your vault.
* **Plain env var** (`plain`) — development only; plaintext key held in process memory. **Do not use for fund movement volume.** No sign-without-expose guarantee.

Migrate to AWS KMS (or a future signer backend such as Vault Transit / GCP KMS) before scaling. See [`docs/reference/signers/local-private-key-signer.md`](/reference/signers/local-private-key-signer) and [`docs/reference/signers/signer-protocol.md`](/reference/signers/signer-protocol).

### Multi-signer bootstrap

For redundancy or rotation overlap, configure additional signers via `MG_EXTRA_SIGNERS_JSON`. Signer health checks run at bootstrap.

### CCTP local signer readiness

```bash theme={null}
uv run python -m qtg.interfaces.tools.cctp_live_preflight

QTG_CCTP_LIVE_E2E=1 uv run python -m qtg.interfaces.tools.cctp_live_e2e \
  --template-key cctp.single_lane_usdc \
  --template-version <approved-version> \
  --checkpoint-path <new-local-packet-path> \
  --i-understand-this-can-sign-and-broadcast
```

Activate the EVM / signer section in `.env` (copied from `.env.example`).
The retained one-shot command is TESTNET-only and can sign and broadcast through
AWS KMS. Its presence is not live approval: use it only with a fresh reviewed
operator approval for the exact run. Pytest has no CCTP broadcast authority.

## Binance master / sub-account model

Binance sub-account bindings are signed through the **master credentials** — QTG never holds sub-account trading keys. Declare sub bindings with `account_role: "sub"` and `sub_account_uid`, omitting `access_key` and `secret_key`.

For Binance, `sub_account_uid` is intentionally the **sub-account email** (Binance sub-account asset and transfer APIs use `email` / `fromEmail`); do not put the numeric `subUserId` / UID there.

Master bindings use `account_role: "master"` and carry credentials. The Binance master API key must have **Enable Sub-Account Management** so QTG can read sub balances through `/sapi/v3/sub-account/assets`. See `.env.example` for the full binding JSON shape.

### CEX logical venue alias

`MG_CEX_BINDINGS_JSON` maps an alias such as `binance_lab` to the existing Binance provider. If an alias exists, runtime proving and balance both resolve binding-first. Legacy `MG_BINANCE_*` settings remain as fallback.

## Auth model

### Inbound request HMAC

Required headers:

* `X-QTG-Key-Id`
* `X-QTG-Timestamp`
* `X-QTG-Nonce`
* `X-QTG-Signature`

Canonical string:

```text theme={null}
METHOD
PATH
QUERY
SHA256(raw_body_bytes)
TIMESTAMP
NONCE
```

* `PATH` is the routed, percent-decoded path the server dispatches on — no origin, no query string.
* `QUERY` is the query **exactly as sent**: no leading `?`, **no sorting**, empty string if absent.
  Sorting before signing transmits bytes you did not sign, and every such request 401s.

A working signed-sender example is provided in the repository's `examples/` directory.

### RBAC — 3 roles

Each API key is bound to exactly one role, enforced per route by the HMAC auth middleware:

| Role       | Use case                                                                                  | Sample routes                                                                                            |
| ---------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `admin`    | Privileged ops — template / registry / signer mutation                                    | `POST /v3/plan-templates`, `PATCH /v3/signers/{key}`                                                     |
| `operator` | Day-to-day movement ops — approve / reject, retry, capital transfers, balance reads       | `POST /v3/movements/{id}/approve`, `POST /v3/capital-transfers`, `GET /v3/signers`                       |
| `agent`    | Agent-namespace scoped — propose templates and bridge attempts via authority binding only | `POST /v3/agent-authorities/{key}/template-proposals`, `POST /v3/agent-authorities/{key}/bridge-attempt` |

All mutating routes are mirrored into an append-only `audit_events` table. Query via `GET /v3/audit/events` (canonical, admin + operator) or the legacy `GET /v3/registry/audit`. For agent-namespace tenant isolation, see [`docs/reference/api/v3-endpoints.md`](/reference/api/v3-endpoints).

### Outbound callback HMAC (v3)

Headers:

* `X-QTG-Callback-Timestamp`
* `X-QTG-Callback-Nonce`
* `X-QTG-Callback-Signature-Version: v3`
* `X-QTG-Callback-Signature`

v3 includes nonce-based replay defense. Receiver implementation requirements: [`docs/callback-verification-contract.md`](/callback-verification-contract). A working receiver example is provided in the repository's `examples/` directory.

## Schema bootstrap

PostgreSQL only since v0.1.0. Auto-creating tables at startup is no longer supported — a fresh DB is built from the 3-bucket alembic chain (global / mainnet / testnet):

```bash theme={null}
uv run alembic -c alembic_v3.ini -x network=global  upgrade global_chain@head
uv run alembic -c alembic_v3.ini -x network=mainnet upgrade network_chain@head
uv run alembic -c alembic_v3.ini -x network=testnet upgrade network_chain@head
```

`scripts/quickstart.sh` runs these for you. Schema changes ship as new migrations in the same chain.

* Heads are per-bucket — there is no single global "head" revision; upgrade each bucket to its own `@head`.
* Startup validation: on boot the server checks that the schema exists and the alembic head matches before accepting traffic — a drifted or unmigrated DB refuses to boot.
* Existing databases (schema drift, live deployment): managed by the same `alembic_v3/` migration chain.
* One-off data backfills: `scripts/` or explicit operational runbooks.
* Local and container dependency installation: all aligned on `uv`.
* Minimum Python: `3.14` (repo-local default + Docker baseline both aligned).

`MG_NETWORK_MODE` is **required and has no default** (`mainnet` | `testnet`). The server refuses to boot if it is unset; `.env.example` ships `MG_NETWORK_MODE=mainnet`.

## Runtime surfaces

QTG runs as a single FastAPI service with a few operator-facing surfaces:

* **REST API** — the `/v3/*` movement, template, registry, and signer endpoints, plus `/healthz`.
* **Dashboard** — a React SPA served against the `/dashboard/*` endpoints (Gateway balances, CCTP transfer tracking, movement management, route lookup).
* **Runtime workers** — when `MG_WORKERS_ENABLED=true`, 8 always-on workers (dispatcher, observer, recovery, callbacks, expiration, proposal expiry, executor health, audit promotion) run and execute real integrations, plus conditional sidecars behind their own flags.
* **CLI tools** — preflight, seed, and import utilities for setup and operations.

The repository also ships `examples/` (a callback receiver and a signed sender) and `docs/` (design, reference, and operational docs).

## Verification commands

```bash theme={null}
uv run pytest -q tests/qtg/
uv run ruff check src tests
uv run mypy src
```

Health check — once the server is up, `GET /healthz` returns:

```json theme={null}
{"ok": true, "service": "movement-guard", "api_prefix": "/v3"}
```

## Important runtime nuances

* **Auto-approve.** When `MG_AUTO_APPROVE_ENABLED=true` and `strategy_id` is provided, policy-matched requests become `APPROVED` immediately and manual approval is skipped.
* **Address allowlist.** On-chain executors apply the DB-level address guard at *dispatch* time, not at template registration.
* **Callback v3.** Nonce-based replay protection is implemented; receivers must store and reject seen nonces.
* **Signer health.** Bootstrap runs a health check on every configured signer.
* **EVM proving signer.** Defaults to the local AWS KMS signer bootstrapped via `MG_LOCAL_SIGNER_*`.
* **EVM RPC endpoints.** Default to PublicNode URLs for \~24 mainnet + testnet chains so the dev quickstart works out of the box. Per-chain overrides in `MG_EVM_RPC_ENDPOINTS_JSON` always win; set `MG_EVM_RPC_USE_DEFAULTS=false` to disable the table entirely. Live broadcast tools (`*_live_preflight`, Stage 3 harness) ignore defaults regardless — see [`reference/rpc-defaults.md`](/reference/rpc-defaults).

## Where to go next

* **First movement, dry-run:** [`docs/quickstart/02-first-movement.md`](/quickstart/02-first-movement)
* **Template patterns by lane:** [`docs/quickstart/03-template-cookbook.md`](/quickstart/03-template-cookbook)
* **Going live (auth, callbacks, workers, Docker, allowlist):** [`docs/quickstart/04-going-live.md`](/quickstart/04-going-live)
* **API reference:** [`docs/reference/api/v3-endpoints.md`](/reference/api/v3-endpoints)
* **Runbooks:** [`docs/runbooks/`](runbooks/)
