## Summary

- Adds `apps/api/scripts/migrate-mttx.mjs`, an opt-in operator tool that copies the legacy `mattrax/mttx` MySQL schema into a freshly migrated `mattraxe` database.
  - Source/target configured with `MTTX_DATABASE_URL` / `TARGET_DATABASE_URL` (plus `MTTX_DATABASE_*` and `DATABASE_*` host/port/user/password/name fallbacks).
  - Idempotent upserts, `--dry-run`, and a hard requirement for `--yes` on real runs.
  - Preserves IDs for tenants/accounts, devices, groups, policies and enrollments; derives unique organisation slugs; maps tenant ownership (`tenant.id = account.id`) to an `owner` member.
  - Creates `auth_identifiers`, `auth_credentials` and `auth_emailCredentials` rows so email-code sign-in works after verification. It writes **no** `auth_passwords` rows; migrated users must reset or use email codes. Legacy sessions are not migrated.
  - Normalises binary fields: `cert_hash`/push tokens to hex, unlock/bootstrap tokens to base64, APNs/SCEP DER to PEM.
  - Recomputes configuration hashes with the new `SHA-256(JSON.stringify(data))` definition.
  - Refuses to silently drop APNs keys or the SCEP CA: both are skipped with loud warnings by default. `--resell-apns` (needs `MTTX_SECRET` + `AUTH_SECRET`) re-seals legacy keys; `--import-scep-ca` imports the legacy CA.
  - Reports inserted/updated/unchanged/skipped counts, per-organisation device mismatches and skipped-row samples.
- Adds `apps/api/scripts/README.md` with prerequisites, usage, validation queries, APNs/SCEP caveats and rollback guidance.
- Adds `docs/enterprise/mttx-data-migration.md` with the full table mapping, auth/device/policy notes, cutover procedure, security guidance and open decisions; links it in the Enterprise docs sidebar.
- Not wired into CI or any deployment path.

Design issue: #5.

## Test plan

- `pnpm typecheck`
- `pnpm test` — 33 files, 280 tests passed
- `pnpm doc:build`
- `node --check apps/api/scripts/migrate-mttx.mjs` and `--help`
- Parsed every generated target `INSERT`/`INSERT IGNORE` statement against the local `mattraxe` schema (columns, unique keys and SQL syntax).
- Verified the legacy ChaCha20-Poly1305 → new AES-256-GCM APNs re-seal round-trip against the repo's `openSecret`, and PKCS#8 DER → JWK import via `importPrivateKeyJwk`.
- Ran the script's preflight/failure path against the local database (confirmed clean refusal when legacy tables are absent).
- A full end-to-end dry run needs a scratch legacy `mttx` database, which is not available in this environment; the runbook makes the staged dry run the first cutover step.

Closes #5

<sub>Generated on _MrBeast_ using _opencode-go/deepseek-v4.1-flash_ in _ses_e3fe30b56ffdLHOi1nbsDAq8jw_</sub>
