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

# TanStack Start And Rust Migration

> Migration contract for replacing apps/web with apps/tanstack-web plus the Rust backend

`apps/tanstack-web` is the replacement frontend for the legacy Next.js
`apps/web` runtime. It uses TanStack Start, TanStack Router, TanStack Query,
Vite, React 19, Tailwind 4, and the existing Tuturuuu shared packages.

`apps/backend` is the planned Rust API runtime. Do not create another backend
service for this migration; extend `apps/backend` route groups and keep API
contracts documented in `apps/backend/api/openapi.yaml`.

<Warning>
  `apps/backend` is not currently deployed and receives no production traffic.
  `apps/web` remains the live API runtime. A route marked `migrated` in this
  document means its future Rust source contract is implemented and tested; it
  does not mean that request routing has cut over.
</Warning>

The crate can run as a native container and keeps a Cloudflare Workers Rust
entrypoint in `apps/backend/wrangler.jsonc` for future, explicitly approved
preview deployment.

For exact local run commands and deployment steps across native local, Docker,
Cloudflare Workers, Vercel, and VPS/Cloudflare Tunnel paths, use
[TanStack/Rust Local And Deployment](/build/devops/tanstack-rust-local-deploy).

## Runtime Shape

| Runtime      | Local URL                             | Fallback port | Owner               |
| ------------ | ------------------------------------- | ------------: | ------------------- |
| Legacy web   | `https://tuturuuu.localhost`          |        `7803` | `apps/web`          |
| TanStack web | `https://tanstack.tuturuuu.localhost` |        `7824` | `apps/tanstack-web` |
| Rust backend | `http://localhost:7820`               |        `7820` | `apps/backend`      |

Use `bun dev:tanstack-web` for local TanStack work. Docker dev also exposes the
`tanstack-web` service on port `7824` and injects `BACKEND_PUBLIC_ORIGIN`,
`BACKEND_INTERNAL_URL`, and `BACKEND_INTERNAL_TOKEN` for Rust backend calls.
Cloudflare preview uses the `BACKEND` service binding first and keeps
`BACKEND_INTERNAL_URL` as an HTTP fallback for local, Docker, and emergency
non-binding runs.

## Rendering And Cache Policy

Every migrated TanStack route must declare its rendering/cache class before it
is marked terminal in `route-overrides.json`:

| Class                         | Use for                                                                                | Required implementation                                                                                                                                            |
| ----------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Static prerender              | Public routes whose HTML is fully local/static at build time.                          | Add the localized path to the `pages` and `prerender` options in `apps/tanstack-web/vite.config.ts`; keep `crawlLinks: true` plus the static-route filter enabled. |
| ISR-style CDN revalidation    | Public routes backed by slow-changing Rust/backend data, such as models and changelog. | Add route-level `headers()` with `Cache-Control` `s-maxage` plus `stale-while-revalidate`; add `CDN-Cache-Control` for Cloudflare.                                 |
| Dynamic no-store              | Authenticated, workspace-scoped, session-specific, or secret-backed routes.            | Do not prerender; use server functions/internal API calls with forwarded auth and no shared-cache headers.                                                         |
| Redirect/static compatibility | Redirect-only compatibility routes such as QR and docs handoffs.                       | Keep redirect behavior exact; only cache when the target contract is public and invariant.                                                                         |

This follows TanStack Start's current guidance: prerender public paths through
the Start Vite plugin, use standard HTTP cache headers for ISR-style pages, and
prefer CDN headers such as `CDN-Cache-Control` for Cloudflare-specific shared
cache control. Official references:
[Static Prerendering](https://tanstack.com/start/latest/docs/framework/react/guide/static-prerendering)
and
[Incremental Static Regeneration](https://tanstack.com/start/latest/docs/framework/react/guide/isr).

The initial prerender set intentionally includes only public, unauthenticated,
non-backend-backed pages. Backend-backed public pages are not prerendered at
build time because Docker, CI, and Cloudflare builds must not require a live
Rust backend just to emit static HTML. Instead, those pages use conservative
ISR-style CDN headers from `apps/tanstack-web/src/lib/platform/cache.ts`.

## Cloudflare Preview Deployment

Cloudflare preview deployments are supported before cutover so the team can
validate the Worker runtime, smoke endpoints, and benchmark numbers without
moving production traffic. The preview path uses:

* `apps/backend/wrangler.jsonc` for the Rust Worker bundle.
* `apps/tanstack-web/wrangler.jsonc` for the TanStack Start Worker.
* `@cloudflare/vite-plugin` in `apps/tanstack-web/vite.config.ts`, registered
  before `tanstackStart()`.
* root `wrangler` tooling plus `bun check:cloudflare` to validate both Worker
  configs without contacting Cloudflare.

Validate the checked Cloudflare contract locally:

```bash theme={null}
bun check:cloudflare
```

Current compatibility contract:

| Runtime                 | Cloudflare entrypoint              | Deploy command                                             | Compatibility status                                                                                                                |
| ----------------------- | ---------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Rust backend            | `apps/backend/wrangler.jsonc`      | `bun wrangler deploy --config apps/backend/wrangler.jsonc` | Source- and preview-ready, but not currently deployed. The command is reserved for an explicitly approved future preview.           |
| TanStack Start frontend | `apps/tanstack-web/wrangler.jsonc` | `bun --cwd apps/tanstack-web run deploy:cloudflare`        | Preview-ready for migrated public routes, redirects, the root migration shell, and Start server-function calls to the Rust backend. |

`apps/tanstack-web` deployment runs `bun run build` internally through the
app-local `deploy:cloudflare` script. Do not run it during docs-only or
inspection work unless the task explicitly allows build commands. For a
configuration-only preflight, use `bun check:cloudflare`.

Both Wrangler configs declare required secret names with the schema-supported
`secrets.required` property. The validator requires these names and rejects
secret-looking values under `vars`:

| Worker                             | Required preview secrets                                                                                                                                                                              |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apps/backend/wrangler.jsonc`      | `BACKEND_INTERNAL_TOKEN`, `TUTURUUU_APP_COORDINATION_SECRET`, `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, `CRON_SECRET`, `DISCORD_APP_DEPLOYMENT_URL`, `AURORA_EXTERNAL_URL`, `AURORA_EXTERNAL_WSID` |
| `apps/tanstack-web/wrangler.jsonc` | `BACKEND_PUBLIC_ORIGIN`, `BACKEND_INTERNAL_TOKEN`; `BACKEND` service binding to `tuturuuu-backend`                                                                                                    |

For local Worker previews, put secret values next to the owning Wrangler config
in ignored files:

* `apps/backend/.dev.vars`
* `apps/tanstack-web/.dev.vars`

Do not commit `.dev.vars*` or `.env.preview*` files. `bun check:cloudflare`
validates the ignore rules so preview tokens and account-specific Worker
origins do not enter Git.

The backend Worker uses `BACKEND_ENV=preview` in `wrangler.jsonc`. Do not set
Cloudflare preview traffic to `development`; development-only migration routes
remain limited to local development and the explicit local E2E bypass.

Use `wrangler secret put` for initial preview bootstrapping only: Cloudflare
creates and deploys a new active Worker version when that command changes a
secret. For rotations, canaries, or any deployed Worker that already receives
traffic, use `wrangler versions secret put`, then promote the resulting version
with `wrangler versions deploy`.

Deploy the Rust backend Worker first:

```bash theme={null}
rustup target add wasm32-unknown-unknown
cargo install worker-build --locked
bun wrangler secret put BACKEND_INTERNAL_TOKEN --config apps/backend/wrangler.jsonc
bun wrangler secret put TUTURUUU_APP_COORDINATION_SECRET --config apps/backend/wrangler.jsonc
bun wrangler secret put SUPABASE_URL --config apps/backend/wrangler.jsonc
bun wrangler secret put SUPABASE_SERVICE_ROLE_KEY --config apps/backend/wrangler.jsonc
bun wrangler secret put CRON_SECRET --config apps/backend/wrangler.jsonc
bun wrangler secret put DISCORD_APP_DEPLOYMENT_URL --config apps/backend/wrangler.jsonc
bun wrangler secret put AURORA_EXTERNAL_URL --config apps/backend/wrangler.jsonc
bun wrangler secret put AURORA_EXTERNAL_WSID --config apps/backend/wrangler.jsonc
bun wrangler deploy --config apps/backend/wrangler.jsonc
```

`BACKEND_INTERNAL_TOKEN` is required before backend preview deploys are useful:
`/readyz` reports not-ready when the token is missing.
`TUTURUUU_APP_COORDINATION_SECRET` is required before contact/profile preview
routes can verify Tuturuuu `ttr_app_` app-session tokens in production-like
Cloudflare environments. `CRON_SECRET` and `DISCORD_APP_DEPLOYMENT_URL` are
required before the Rust-owned Discord cron proxy routes can call the Discord
app. `AURORA_EXTERNAL_URL` is required before the Rust-owned Aurora health and
ingest routes can call the Aurora service, and `AURORA_EXTERNAL_WSID` is
required before Aurora ingest routes can write rows. Wrangler prompts for
values; do not place those values in `wrangler.jsonc`, `vars`, docs, or shell
history.

`SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY` are required backend Worker
secrets for the Rust-owned contact/profile APIs. They stay server-only: the
backend reads `users` and `user_private_details`, updates profile fields, and
inserts `support_inquiries` through Supabase REST with the service-role key.
`GET /api/migration/status` exposes only redacted readiness state and the
Supabase origin, never the credential.

Smoke-test the returned `workers.dev` URL before pointing the frontend at it:

```bash theme={null}
curl -fsS https://<backend-worker-origin>/healthz
curl -fsS https://<backend-worker-origin>/readyz
curl -fsS \
  -H "Authorization: Bearer ${BACKEND_INTERNAL_TOKEN:?set BACKEND_INTERNAL_TOKEN}" \
  https://<backend-worker-origin>/api/migration/status
```

Then configure the TanStack Worker. `apps/tanstack-web/wrangler.jsonc`
declares a `BACKEND` service binding to `tuturuuu-backend`, so the backend
Worker must be deployed first. Store only the browser-safe public backend
origin and the shared internal token as Cloudflare secrets for preview runs:

```bash theme={null}
bun wrangler secret put BACKEND_PUBLIC_ORIGIN --config apps/tanstack-web/wrangler.jsonc
bun wrangler secret put BACKEND_INTERNAL_TOKEN --config apps/tanstack-web/wrangler.jsonc
```

For gradual/canary secret rotation after the first preview deploy, use the
versions command family instead:

```bash theme={null}
bun wrangler versions secret put BACKEND_INTERNAL_TOKEN --config apps/backend/wrangler.jsonc
bun wrangler versions secret put TUTURUUU_APP_COORDINATION_SECRET --config apps/backend/wrangler.jsonc
bun wrangler versions secret put SUPABASE_URL --config apps/backend/wrangler.jsonc
bun wrangler versions secret put SUPABASE_SERVICE_ROLE_KEY --config apps/backend/wrangler.jsonc
bun wrangler versions secret put CRON_SECRET --config apps/backend/wrangler.jsonc
bun wrangler versions secret put DISCORD_APP_DEPLOYMENT_URL --config apps/backend/wrangler.jsonc
bun wrangler versions secret put AURORA_EXTERNAL_URL --config apps/backend/wrangler.jsonc
bun wrangler versions secret put AURORA_EXTERNAL_WSID --config apps/backend/wrangler.jsonc
bun wrangler versions deploy --config apps/backend/wrangler.jsonc

bun wrangler versions secret put BACKEND_PUBLIC_ORIGIN --config apps/tanstack-web/wrangler.jsonc
bun wrangler versions secret put BACKEND_INTERNAL_TOKEN --config apps/tanstack-web/wrangler.jsonc
bun wrangler versions deploy --config apps/tanstack-web/wrangler.jsonc
```

`BACKEND_PUBLIC_ORIGIN` should initially be the backend Worker origin, for
example the `https://<backend-worker>.<subdomain>.workers.dev` URL returned by
the backend deploy. It remains the browser-safe origin used for public probes
and non-protected traffic. Start server functions prefer the `BACKEND` service
binding for Worker-to-Worker backend calls and fall back to
`BACKEND_INTERNAL_URL` only outside Cloudflare or when the binding is absent.
Use `BACKEND_INTERNAL_URL` in local Docker, local Node preview, or emergency
HTTP fallback runs; do not make it a required TanStack Worker secret while the
service binding is declared. The TanStack Worker still needs the same
`BACKEND_INTERNAL_TOKEN` value so Start server functions can call protected Rust
migration inventory endpoints. Local `wrangler dev` can omit origin bindings
because `packages/internal-api` falls back to `http://localhost:7820`; local
migration dashboard calls will fall back to the checked manifest when the
backend token is not configured.

Deploy the TanStack Start Worker after the backend origin secrets are present:

```bash theme={null}
bun --cwd apps/tanstack-web run cf-typegen
bun --cwd apps/tanstack-web run deploy:cloudflare
```

For a local Worker-shape smoke before deployment, use Wrangler preview servers
in separate terminals and then point the smoke command at those origins:

```bash theme={null}
bun wrangler dev --config apps/backend/wrangler.jsonc
bun --cwd apps/tanstack-web run preview:cloudflare
```

The checked Wrangler configs reserve distinct local preview ports so both
Workers can run at the same time: `http://localhost:8780` for the Rust backend
and `http://localhost:8784` for TanStack Start. Keep those ports stable because
`bun check:cloudflare` validates them and the smoke examples below assume them.

Set the same env variable names that the deployed Workers use. Keep values in
the shell, local ignored env files, or Wrangler secret storage only:
`BACKEND_INTERNAL_TOKEN` and `BACKEND_PUBLIC_ORIGIN`. When the TanStack local
Worker cannot use the `BACKEND` service binding, set `BACKEND_INTERNAL_URL` to
the local backend Wrangler origin as an HTTP fallback.

Then run the preview smoke command against the returned Worker origins:

```bash theme={null}
BACKEND_INTERNAL_TOKEN="${BACKEND_INTERNAL_TOKEN:?set BACKEND_INTERNAL_TOKEN}" \
BACKEND_WORKER_ORIGIN=http://localhost:8780 \
TANSTACK_WEB_WORKER_ORIGIN=http://localhost:8784 \
bun smoke:cloudflare \
  --output tmp/benchmarks/web-migration/<timestamp>/cloudflare-smoke.json
```

For deployed previews, replace those local origins with the `workers.dev` or
custom preview origins returned by Wrangler. Set `BACKEND_INTERNAL_TOKEN` in the
shell before running the smoke command. The smoke command probes `/healthz`,
`/readyz`, authenticated `/api/migration/status`, missing/invalid-token
rejection for the protected migration status endpoint, and the TanStack root
shell. It fails on unexpected `4xx` and `5xx` responses, requires the TanStack
root shell to show `Backend reachable`, and redacts the bearer token from
output. That final check proves the deployed Start server function can reach
the Rust Worker through the service binding or configured HTTP fallback and
token, not just that the static shell rendered. Use `--output` to persist the
smoke report under
ignored `tmp/benchmarks/web-migration/<timestamp>/cloudflare-smoke.json` when
the run is part of a cutover rehearsal.
For deployed E2E smoke runs, set `TANSTACK_EXPECT_BACKEND_REACHABLE=1` and
`TANSTACK_EXPECT_BACKEND_TARGET=cloudflare-workers` so the migration shell must
prove the frontend can reach the Rust Worker.

For a non-terminal Cloudflare preview gate, attach that smoke report while
explicitly allowing the still-legacy route inventory:

```bash theme={null}
bun migration:tanstack:gates -- \
  --allow-legacy \
  --skip-benchmark \
  --skip-e2e \
  --cloudflare-smoke-report tmp/benchmarks/web-migration/<timestamp>/cloudflare-smoke.json
```

This command is only preview evidence. It proves the current Workers can talk
to each other, but it does not satisfy the final route parity, Docker E2E, or
benchmark cutover gates.

This is still a preview/canary path. Keep `apps/web` as the production source of
truth until the manifest, Docker E2E, benchmark, and cutover gates below pass.
Do not map production hostnames to the preview Worker while `workers_dev`
canary traffic and route parity are still in progress.

Rollback is currently DNS/routing only: remove or roll back any Cloudflare route
or custom-domain mapping that sends traffic to the preview Worker, and leave the
Docker blue/green `apps/web` production stack serving the canonical host. Do
not delete Wrangler secrets during rollback unless the secret itself is
compromised; keeping them bound makes redeploying the previous Worker version or
re-running smoke checks deterministic. Inspect and roll back preview Worker
deployments with Wrangler:

```bash theme={null}
bun wrangler deployments list --config apps/backend/wrangler.jsonc
bun wrangler deployments status --config apps/backend/wrangler.jsonc
bun wrangler rollback <VERSION_ID> --config apps/backend/wrangler.jsonc

bun wrangler deployments list --config apps/tanstack-web/wrangler.jsonc
bun wrangler deployments status --config apps/tanstack-web/wrangler.jsonc
bun wrangler rollback <VERSION_ID> --config apps/tanstack-web/wrangler.jsonc
```

Worker rollback does not revert external resources, bindings, routes, custom
domains, or secret values. If a preview deploy regresses, roll back the Worker
version or remove the preview route, then run `bun smoke:cloudflare` against the
remaining preview origins before resuming canary traffic.

Protected TanStack-to-backend traffic now has a Cloudflare service binding from
the TanStack Worker to the backend Worker: binding name `BACKEND`, service
`tuturuuu-backend`. The shared backend client prefers that binding in
server-only TanStack code and keeps `BACKEND_INTERNAL_URL` as a non-Cloudflare
HTTP fallback. Protected workspace and admin APIs still must not move to
production Worker traffic until each route has backend tests, OpenAPI coverage,
an internal-api facade, and migration gate evidence. Browser code must never
receive service tokens, and server-owned protected data must stay behind
server-owned calls.

Current Cloudflare limitations:

* Runtime service binding smoke is pending. The config and internal client use
  the `BACKEND` binding, but deployed smoke still needs to prove the binding
  path in Cloudflare preview before production host routing.
* Production host routing is pending full route manifest completion, Docker
  compare-mode E2E evidence, benchmark evidence, and
  `bun migration:tanstack:gates`.
* Preview Workers should not become the owner for private workspace/admin APIs
  until each route has backend tests, OpenAPI coverage, an internal-api facade,
  and migration gate evidence.

## Route Ownership Manifest

The current migration manifest is checked in at
`apps/tanstack-web/migration/route-manifest.json`. It records the current
`apps/web/src/app` route inventory, intended target owner for each route, and a
progress summary grouped by target owner and route kind. API and route-handler
entries also include a `methods` array derived from exported Next route methods;
`summary.methodCounts` tracks total exported `GET`, `POST`, `PUT`, `PATCH`,
`DELETE`, `HEAD`, and `OPTIONS` handlers. When only some methods on a legacy
`route.ts` are migrated, `route-overrides.json` can split that file into
method-level artifacts with `parentId` and `method`; the unmigrated paired
methods stay visible as `legacy-next`.

### Rust GET-handler migration wave

The backend port proceeds GET-first: a route's read path moves to a Rust handler
in `apps/backend/src/<module>.rs` while its mutation methods stay on the live
Next.js route. The Rust handler matches the legacy mount path exactly and returns
`None` (never `405`) for every method it does not own, so the worker falls through
to Next.js for `POST`/`PUT`/`PATCH`/`DELETE`. Because the route is still the source
of truth for writes, it correctly stays `legacy-next` in the manifest until the
remaining methods are ported and a cutover decision is recorded — GET-only ports
do not flip ownership status, so they add no manifest debt.

As of this wave the curated non-special fresh-GET surface is migrated: \~235 GET
routes now have Rust handlers. The only deliberately-skipped GET routes are
`/api/v1/workspaces/:wsId/mind/boards/:boardId` and
`/api/v1/workspaces/:wsId/whiteboards/:boardId`, whose CRDT/Yjs binary state lives
in a store the worker cannot reach; they stay on Next.js. Still pending as
separate phases: mutation methods for the GET-migrated routes, and special-auth
GET routes (`/api/cron/*` `CRON_SECRET`, `/api/trpc`, `/:locale` pages, OAuth
callbacks, and Hive routes backed by `HIVE_DATABASE_URL`).

Each batch is verified with `bun check:backend` (mirrors the CI Rust gate: `cargo
fmt --check`, `cargo clippy --locked --all-targets --features native -- -D
warnings`, `cargo test --locked`, and the `wasm32-unknown-unknown` worker check)
plus a runtime dual coverage probe that asserts every migrated `GET` is served by
the dispatcher (COVER) and every un-ported method still falls through (FRESH).

### Worker-incompatible routes (native-backend or Next.js only)

Some legacy routes cannot run on the **Cloudflare Worker** build of
`apps/backend` because the wasm sandbox has no arbitrary sockets, no filesystem,
and no Redis/Postgres drivers. They split into three buckets:

* **Native-backend portable (deferred, needs secrets wired):** the scheduler
  `/api/cron/*` jobs that just "call an external API + write Supabase" —
  `finance/exchange-rates`, `inventory/polar-product-sync`, `payment/{orders,products,subscriptions}`,
  `ai/sync-models`, `tasks/generate-embeddings`, `calendar/{provider-sync,smart-schedule}`,
  `process-{post-email-queue,topic-announcement-queue,notification-batches}`, and
  `hive/simulate`. These ARE portable to the **native Rust container** target
  (`--features native`, which can do outbound HTTP and reach external DBs) once
  each job's provider secret/connection is added to `BackendConfig` +
  `wrangler.jsonc` secrets. They are not portable to the wasm Worker build. Until
  the secrets are wired they stay on Next.js (`Bearer CRON_SECRET`).
* **Host/infra-coupled (stay where the runner lives):** the cron-runner
  *monitoring* surface — `monitoring/cron/{control,run,runner-recovery,executions}`,
  plus `cron/infrastructure/{docker-recovery-alerts,sample-resources}` — reads a
  filesystem archive / controls the deployment host (Docker control), and
  `cron/infrastructure/sync-trust-cache` needs Redis. These belong with whatever
  orchestrates the runner, not a stateless handler.
* **Transport that can't be a single handler:** `/api/trpc/[trpc]` is a catch-all
  that dispatches the entire tRPC procedure router (`appRouter`). The transport
  stays on Next.js; its data access migrates incrementally as individual
  procedures move behind `packages/internal-api` / the Rust backend.

Record the chosen disposition for each in
`apps/tanstack-web/migration/route-overrides.json` with an evidence note rather
than leaving them as untriaged `legacy-next` backlog.

Current inventory:

* `149` pages
* `57` layouts
* `571` route handler artifacts
* `8` cron handlers
* `780` total tracked route artifacts
* `214` migrated artifacts, `227` terminal artifacts, and `553` remaining
  legacy-owned artifacts in the checked manifest

Regenerate it after adding or removing legacy routes:

```bash theme={null}
bun migration:tanstack:manifest
```

Regenerate the TanStack Router route tree after adding or removing
`apps/tanstack-web/src/routes/**` files:

```bash theme={null}
bun migration:tanstack:routes
```

This command preserves the TanStack Start `Register` augmentation footer that
`bun check:cloudflare` validates for the Cloudflare-compatible Start runtime,
then formats the generated `routeTree.gen.ts` with the generator's isolated
Biome config so repeated route-tree generation does not leave persistent dirty
output. The Rust/TanStack Cloudflare workflow runs
`scripts/generate-tanstack-route-tree.test.js` whenever the generator changes.

Route ownership status is preserved through
`apps/tanstack-web/migration/route-overrides.json`. Add an override with a
non-empty evidence note when a route becomes `migrated` or receives an accepted
removal decision; do not edit the generated manifest by hand.

Check that the manifest still matches the legacy route tree while migration is
in progress:

```bash theme={null}
bun migration:tanstack:check
```

Cutover mode is intentionally stricter. It fails while any route remains marked
as `legacy-next`:

```bash theme={null}
bun migration:tanstack:cutover-check
```

The full cutover gate also requires explicit Docker E2E, benchmark, and
Cloudflare smoke evidence:

```bash theme={null}
bun migration:tanstack:gates -- \
  --e2e-report tmp/e2e/web-migration/compare-report.json \
  --benchmark-report tmp/benchmarks/web-migration/<timestamp>/report.json \
  --cloudflare-smoke-report tmp/benchmarks/web-migration/<timestamp>/cloudflare-smoke.json \
  --output tmp/benchmarks/web-migration/<timestamp>/cutover-gates.json
```

This command validates route parity, terminal migration statuses, backend-owned
route mapping, compare-mode Docker E2E evidence, and a full compare benchmark
report without committing generated artifacts. The output JSON is the
review/handoff artifact for cutover sign-off and stays under ignored `tmp/`
paths with the source reports. The benchmark report must be created with
`--setup compare --profile full` and include every required metric comparison;
smoke reports alone are useful for previews but are not sufficient cutover
evidence. The Cloudflare smoke report must come from
`bun smoke:cloudflare` against distinct live Rust backend and TanStack Worker
origins, and the cutover gate verifies that each required probe URL matches
that provenance.

The manifest also includes `progress.byOwner`, `progress.byKind`, and
`progress.topLegacyRoutes`. Use those fields when splitting the remaining port
work across frontend and backend owners. Use each route's `methods` list when
checking API parity so a `GET` port does not accidentally hide an unmigrated
`POST`, `OPTIONS`, or mutation handler on the same route artifact. The Rust
backend exposes the same derived progress at:

```text theme={null}
GET /api/migration/progress
```

`apps/tanstack-web` reads that endpoint through `packages/internal-api` and
falls back to the checked manifest when the backend is offline.

Method-level migration ownership is only valid when the deployment path can
route traffic by HTTP method or otherwise avoid sending still-legacy methods to
Rust. For example, the Rust backend can own `OPTIONS` preflight responses for an
auth route while the corresponding `POST` or `GET` artifact remains
`legacy-next`; a path-only proxy must keep that whole path on Next until the
auth method is migrated too.

First migrated ownership:

| Legacy route                                                                                                                                                                                                               | New owner                            | Evidence                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /.well-known/*` / `HEAD /.well-known/*`                                                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route handler `migrated`; Rust returns a cacheable empty `404` with `Cache-Control: public, max-age=300, must-revalidate`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `GET /~recover-browser-state` / `POST /~recover-browser-state`                                                                                                                                                             | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route handler `migrated`; Rust returns the no-store reset HTML, enforces same-origin POST confirmation, emits `Clear-Site-Data`, clears Supabase auth cookies, and redirects to `/login?browserStateReset=1`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `GET /serwist/:path`                                                                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route handler `migrated`; Rust serves a no-store decommissioning worker at `/serwist/sw.js` that unregisters stale Next/Serwist service workers during Cloudflare cutover and returns deterministic source-map metadata at `/serwist/sw.js.map`. This is cutover ownership, not offline-cache feature parity.                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `GET /api/health`                                                                                                                                                                                                          | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; `GET /api/health` returns the legacy ok status JSON with `Cache-Control: no-store` and JSON security headers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `GET /api/time-tracking/export`                                                                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the browser Supabase session or non-app-session Bearer token, requires a `@tuturuuu.com` root user and the root workspace, verifies workspace membership, preserves legacy query parsing and the 1000-row limit cap, forwards `get_grouped_sessions_paginated` through the caller Supabase token, and returns the legacy data/pagination envelope with an empty-result fallback when RPC and JS-style recovery cannot produce rows.                                                                                                                                                                                                                                                          |
| `GET /api/auth/me`                                                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the Supabase browser session cookie or non-app-session Bearer token with Supabase Auth, returns the raw legacy user payload, keeps no-store headers, and preserves the legacy Unauthorized message response for missing or invalid sessions.                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `GET /api/auth/mfa/totp/assurance-level`                                                                                                                                                                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the Supabase browser session cookie or non-app-session Bearer token with Supabase Auth, derives `currentLevel` from the JWT `aal` claim, derives `nextLevel` from verified Supabase Auth factors on the revalidated user JSON, returns `currentAuthenticationMethods` from the JWT `amr` claim, and keeps the legacy no-store/error response shape.                                                                                                                                                                                                                                                                                                                                          |
| `GET` / `POST` `/api/auth/mfa/totp/factors`                                                                                                                                                                                | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the Supabase browser session cookie or non-app-session Bearer token with Supabase Auth, mirrors Auth JS `listFactors()` from the revalidated user JSON, enrolls TOTP factors through Supabase Auth REST, normalizes TOTP QR codes, and preserves the legacy no-store/error response shape.                                                                                                                                                                                                                                                                                                                                                                                                   |
| `GET` / `DELETE` `/api/auth/mfa/totp/factors/:factorId`                                                                                                                                                                    | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the Supabase browser session cookie or non-app-session Bearer token with Supabase Auth, resolves factor detail from the verified TOTP subset returned by Auth JS-compatible `listFactors()`, unenrolls factors through Supabase Auth REST, and preserves the legacy `Factor not found` and success-wrapper responses.                                                                                                                                                                                                                                                                                                                                                                        |
| `GET /api/:wsId/crawlers/domains`                                                                                                                                                                                          | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy no-auth, workspace-agnostic behavior, reads `crawled_urls` and non-skipped `crawled_url_next_urls` through the server-owned Supabase REST adapter, extracts valid URL hostnames, deduplicates them, and returns the sorted domain list with `cached: false`.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `GET /api/:wsId/crawlers/list`                                                                                                                                                                                             | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the browser Supabase session, requires a `@tuturuuu.com` user email before server-owned admin reads, preserves the legacy raw `crawled_urls` row payload, domain/search filters, `created_at.desc` ordering, exact-count pagination, and data/count response shape. Unauthorized callers now receive an explicit `401` instead of the legacy catch-all `500`.                                                                                                                                                                                                                                                                                                                                |
| `GET /api/:wsId/crawlers/uncrawled`                                                                                                                                                                                        | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy no-auth, workspace-agnostic behavior, reads non-skipped `crawled_url_next_urls`, applies legacy URL filters and pagination, removes URLs already present in `crawled_urls`, groups the remaining rows by `origin_id`, and returns the legacy `uncrawledUrls`, `groupedUrls`, and `pagination` payload.                                                                                                                                                                                                                                                                                                                                                                              |
| `GET /api/v1/workspaces/:wsId/crawlers/status`                                                                                                                                                                             | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy workspace-agnostic URL status lookup, validates the required `url` query parameter, reads the exact `crawled_urls.url` row through the server-owned Supabase REST adapter, and returns raw `crawledUrl` plus raw `crawled_url_next_urls` rows ordered by `created_at.desc`; missing crawled URLs still return `crawledUrl: null` and `relatedUrls: []`.                                                                                                                                                                                                                                                                                                                             |
| `GET /api/v1/calendar/mock`                                                                                                                                                                                                | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust returns the deterministic legacy mock calendar event payload with JSON security headers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `GET /api/v1/devboxes/cache` and `POST /api/v1/devboxes/cache/prune`                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks both devbox cache routes `migrated`; Rust accepts CLI app-session Bearer tokens for the platform target with `cli:access` or browser/non-app-session Supabase credentials, requires root workspace `MEMBER` access, preserves the legacy empty caches list body, and returns the legacy prune acknowledgement without private devbox table mutations. Other devbox mutation routes remain legacy-owned.                                                                                                                                                                                                                                                                                                                             |
| `GET /api/admin/tasks/embeddings/stats`                                                                                                                                                                                    | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the admin statistics route `migrated`; Rust validates the browser Supabase auth cookie with Supabase Auth, requires a `tuturuuu.com` or `xwf.tuturuuu.com` user email, reads exact system-wide task counts through the server-owned Supabase REST adapter, and returns only the derived legacy embedding coverage payload. The SSE embedding generation route remains legacy-owned.                                                                                                                                                                                                                                                                                                                                                 |
| `GET /api/v1/ai/whitelist/me`                                                                                                                                                                                              | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy app-session-first auth behavior for satellite app-session targets, falls back to browser Supabase auth cookies only when no app-session token is present, reads only the `enabled` flag for the authenticated email from `private.ai_whitelisted_emails`, and returns the derived legacy email/enabled payload.                                                                                                                                                                                                                                                                                                                                                                     |
| `GET` / `POST` `/api/v1/infrastructure/ai/whitelist/domains` and `/emails`; `PUT` / `DELETE` `/api/v1/infrastructure/ai/whitelist/:email` / `/domain/:domain`                                                              | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the list/create collection methods plus detail `PUT` and `DELETE` method artifacts `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, requires a `@tuturuuu.com` operator email, reads, inserts, patches, and deletes private whitelist rows through the service-role private-schema REST adapter, preserves list pagination and create validation/defaults, applies legacy `Boolean(enabled)` truthiness for detail updates, and keeps the legacy success, validation, 403, JSON failure, and plain-text failure bodies.                                                                                                                                                            |
| `GET /api/v1/users/me/hive-access`                                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy app-session-first auth behavior for current-user app-session targets, falls back to browser Supabase auth cookies only when no app-session token is present, reads only `hive_members.enabled` and `platform_user_roles.enabled`/`allow_role_management` for the authenticated user through the server-owned Supabase REST adapter, returns the derived legacy access/admin/member payload, and keeps the legacy private cache directive on successful responses.                                                                                                                                                                                                                   |
| `GET /api/v1/cms/workspaces`                                                                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves app-session and browser Supabase auth, loads the caller's admin-visible workspaces through service-role Supabase REST, applies root-admin and per-workspace external-project permission checks, resolves active external-project bindings, and returns the raw legacy workspace array with subscription tier metadata.                                                                                                                                                                                                                                                                                                                                                                         |
| `GET /api/v1/notifications/unread-count`                                                                                                                                                                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves app-session and browser Supabase auth, validates the optional `wsId` query filter, verifies workspace membership before scoped counts, builds the legacy notification access filter, reads the exact unread count through the service-role Supabase REST adapter, and returns no-store JSON responses.                                                                                                                                                                                                                                                                                                                                                                                         |
| `GET /api/v1/mira/achievements`                                                                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the browser Supabase session or non-app-session Bearer token, reads the private Mira achievement catalog through the service-role private-schema Supabase REST adapter, reads the caller's unlocked achievements through the caller-token Supabase REST adapter, and preserves the legacy unlocked-status merge, grouping, XP/stat calculation, and empty-unlocked fallback when the user-achievement read fails.                                                                                                                                                                                                                                                                            |
| `GET /api/v1/storage/list`                                                                                                                                                                                                 | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust validates legacy `ttr_` workspace API keys, resolves role/default workspace permissions, requires `manage_drive` or `admin`, preserves query coercion and storage path sanitization, blocks mobile-deployment vault paths, lists Supabase Storage through the server-owned storage REST adapter, filters placeholder/reserved entries, recursively counts matching files, and returns the legacy data/pagination and error envelopes.                                                                                                                                                                                                                                                                    |
| `GET /api/v1/hive/ai/models`                                                                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves Hive-only app-session auth and browser Supabase cookie fallback, requires Hive member or admin access before private reads, reads only UI-safe model columns from `private.ai_gateway_models` through the server-owned private-schema REST adapter, preserves the legacy `enabled`/`type` filters and provider/name ordering, and returns the derived models UI payload.                                                                                                                                                                                                                                                                                                                       |
| `GET /api/v1/nova/me/team`                                                                                                                                                                                                 | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves Nova-only app-session auth and browser Supabase cookie fallback, reads only `team_id` for the authenticated user from `private.nova_team_members` through the server-owned private-schema REST adapter, and returns the derived legacy team ID payload.                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `GET /api/v1/task-board-status-templates`                                                                                                                                                                                  | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves authenticated Supabase browser-cookie and non-app-session Bearer access, rejects Tuturuuu app-session tokens without falling back to stale cookies, reads the global `task_board_status_templates` catalog through the server-owned Supabase REST adapter, preserves legacy `is_default.desc,name.asc` ordering, and returns the raw legacy templates payload.                                                                                                                                                                                                                                                                                                                                 |
| `GET` / `PUT` `/api/v1/infrastructure/mobile-versions`                                                                                                                                                                     | `apps/backend` Rust route dispatcher | `route-overrides.json` marks both method artifacts `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, requires root workspace `manage_workspace_roles` through the server-owned `has_workspace_permission` RPC, reads the fixed root workspace mobile policy config IDs for snapshots, validates and normalizes write payloads, upserts all nine root workspace policy config rows through the server-owned Supabase REST adapter, and preserves the legacy admin policy snapshot plus success/error write bodies.                                                                                                                                                                                                |
| `GET` / `POST` `/api/v1/infrastructure/timezones` and `PUT` / `DELETE` `/api/v1/infrastructure/timezones/:timezoneId`                                                                                                      | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the collection `GET`/`POST` and detail `PUT`/`DELETE` artifacts `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, requires root workspace `manage_workspace_roles`, reads and writes `private.timezones` through the server-owned private-schema Supabase REST adapter, preserves `value.asc` ordering for reads, normalizes legacy create/update payloads, omits missing/null create IDs so the database UUID default is used, and preserves the legacy success and method-specific failure bodies.                                                                                                                                                                                |
| `GET /api/v1/infrastructure/user-status-changes`                                                                                                                                                                           | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust requires a normal Supabase browser session or non-app-session Bearer token, forwards that caller token to Supabase REST so `workspace_user_status_changes` RLS remains active, preserves the legacy `ws_id` requirement, parseInt-style `limit`/`offset` range behavior, exact-count pagination, raw row list response, and legacy Supabase error body.                                                                                                                                                                                                                                                                                                                                                  |
| `GET /api/v1/infrastructure/users`                                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust uses the shared caller-token paginated export helper for `workspace_users`, preserving Supabase RLS, the legacy `ws_id` requirement, parseInt-style `limit`/`offset` range behavior, exact-count pagination, raw row list response, and legacy Supabase error body.                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `GET /api/v1/infrastructure/classes`, `/product-categories`, and `/score-names`                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these routes `migrated`; Rust uses the shared caller-token paginated export helper for `workspace_user_groups`, `product_categories`, and `user_group_metrics`, preserving Supabase RLS, the legacy `ws_id` requirement, parseInt-style `limit`/`offset` range behavior, exact-count pagination, raw row list responses, and legacy Supabase error bodies.                                                                                                                                                                                                                                                                                                                                                                          |
| `GET /api/v1/infrastructure/lessons` and `/packages`                                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these routes `migrated`; Rust preserves the legacy no-auth service-role private-schema export for `lessons`, while `packages` revalidates a normal Supabase browser session or non-app-session Bearer token, normalizes the workspace, requires `view_inventory`, reads `workspace_products` through the service-role Supabase REST adapter, and preserves the legacy `ws_id`, parseInt-style `limit`/`offset`, exact-count pagination, data/count body, and error responses.                                                                                                                                                                                                                                                       |
| `GET /api/v1/infrastructure/bills`, `/roles`, and `/transaction-categories`                                                                                                                                                | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these routes `migrated`; Rust uses the shared caller-token paginated export helper for `finance_invoices`, `workspace_user_groups`, and `transaction_categories`, preserving Supabase RLS, the legacy `ws_id` requirement, parseInt-style `limit`/`offset` range behavior, exact-count pagination, raw row list responses, and legacy Supabase error bodies.                                                                                                                                                                                                                                                                                                                                                                        |
| `GET /api/v1/infrastructure/abuse-intelligence`                                                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `GET` method artifact `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, requires root workspace `view_infrastructure` through the shared workspace permission helper, reads reputation subjects, activity signals, and step-up challenges with caller-token Supabase REST, reads active trust overrides with the service-role Supabase adapter, and preserves the legacy `limit`/`signalLimit` parsing, summary, `topRiskySubjects` sorting, and auth/error bodies. POST remains legacy-owned.                                                                                                                                                                             |
| `GET /api/v1/infrastructure/abuse-events`                                                                                                                                                                                  | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, preserves the root workspace membership gate through caller-token Supabase REST reads, queries `abuse_events` with the caller token, and preserves the legacy `ip`/`type`/`success` filters, `page`/`pageSize` parseInt-style range behavior, exact-count pagination, data/count/page/pageSize/totalPages body, and legacy auth/error responses.                                                                                                                                                                                                                                                                        |
| `GET /api/v1/infrastructure/blocked-ips`                                                                                                                                                                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `GET` method artifact `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, preserves the root workspace membership gate through caller-token Supabase REST reads, queries `blocked_ips` with the legacy `unblocked_by_user` embed, and preserves the legacy `status`/`ip` filters, `page`/`pageSize` parseInt-style range behavior, exact-count pagination, data/count/page/pageSize/totalPages body, and legacy auth/error responses. POST/DELETE remain legacy-owned.                                                                                                                                                                                                       |
| `GET /api/v1/infrastructure/suspensions`                                                                                                                                                                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `GET` method artifact `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, requires root workspace `manage_workspace_roles` through `has_workspace_permission` with the caller token, reads active `user_suspensions` rows through the service-role Supabase REST adapter ordered by `suspended_at.desc`, returns the legacy raw row array, and preserves the legacy `Unauthorized`, `Forbidden`, and `Failed to fetch suspensions` error bodies. POST and detail DELETE remain legacy-owned.                                                                                                                                                                                 |
| `GET` / `POST` `/api/v1/infrastructure/email-blacklist` and `GET` / `PUT` / `DELETE` `/api/v1/infrastructure/email-blacklist/:entryId`                                                                                     | `apps/backend` Rust route dispatcher | `route-overrides.json` marks all email blacklist collection and detail method artifacts `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, preserves root workspace membership gates and the detail GET non-root `401` quirk, reads, inserts, updates, and deletes through caller-token Supabase REST so RLS remains active, preserves Zod-style write validation bodies, maps duplicate creates to `409`, maps detail misses to the legacy `404` bodies, and preserves update/delete prefetch behavior.                                                                                                                                                                                                          |
| `GET /api/v1/infrastructure/bill-coupons`, `/bill-packages`, `/class-attendance`, `/class-members`, `/class-packages`, `/class-scores`, `/package-stock-changes`, and `/student-feedbacks`                                 | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these routes `migrated`; Rust extends the shared caller-token paginated export helper with route-specific embedded select strings and related-table workspace filters, preserving Supabase RLS, the legacy `ws_id` requirement, parseInt-style `limit`/`offset` range behavior, exact-count pagination, raw row list responses, and legacy Supabase error bodies.                                                                                                                                                                                                                                                                                                                                                                   |
| `GET /api/v1/infrastructure/coupons`, `/user-coupons`, `/user-monthly-reports`, and `/user-monthly-report-logs`                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these routes `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, normalizes the requested workspace, requires `manage_external_migrations` through the shared workspace permission resolver, reads `private.workspace_promotions`, `private.user_linked_promotions`, and the private monthly report views through the server-owned Supabase REST adapter with private-schema headers, preserves the user-coupons empty-promotion short-circuit and `workspace_promotions` relation object reconstruction, and preserves the legacy `ws_id` requirement, parseInt-style `limit`/`offset` range behavior, exact-count pagination, raw row list responses, and legacy auth/error bodies. |
| `GET /api/v1/infrastructure/payment-methods`, `/wallets`, and `/wallet-transactions`                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these routes `migrated`; Rust revalidates the normal Supabase browser session or non-app-session Bearer token, normalizes the requested workspace and requires `view_transactions` for wallet/payment method reads, reads `private.workspace_wallets` through the server-owned Supabase REST adapter with private-schema headers, forwards wallet transaction reads to `get_wallet_transactions_with_permissions` with the caller token, and preserves the legacy `ws_id` requirement, parseInt-style `limit`/`offset` behavior, pagination/count envelopes, raw row list responses, and legacy auth/error bodies.                                                                                                                  |
| `GET /api/v1/workspaces/limits`                                                                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust validates the browser Supabase auth cookie with Supabase Auth, treats `tuturuuu.com` and `xwf.tuturuuu.com` user emails as unlimited, otherwise reads only the exact count of non-deleted workspaces created by the authenticated user through the server-owned Supabase REST adapter, and returns the legacy `canCreate`, `currentCount`, `limit`, and `remaining` payload.                                                                                                                                                                                                                                                                                                                             |
| `GET /api/v1/workspaces/:wsId/posts/permissions`                                                                                                                                                                           | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase session when present, calls the server-owned `has_workspace_permission` RPC for workspace `approve_posts` and root workspace `manage_workspace_roles`, and preserves the legacy quiet-failure behavior where missing auth, inaccessible workspaces, RPC failures, and missing permissions all return `200` with both permission flags `false`.                                                                                                                                                                                                                                                                                                                             |
| `GET /api/v1/workspaces/:wsId/Mention`                                                                                                                                                                                     | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy path casing, revalidates a normal Supabase browser session or non-app-session Bearer token, rejects app-session tokens, requires exact `MEMBER` workspace membership, reads `workspace_users.email` with the caller token, and preserves the legacy email response, Unauthorized, Forbidden, membership lookup failure, and Supabase error bodies.                                                                                                                                                                                                                                                                                                                                  |
| `GET /api/v1/workspaces/:wsId/habits/access`                                                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token, rejects app-session tokens, resolves `internal`, `personal`, UUID, and handle workspace identifiers, requires exact `MEMBER` membership through the service-role `workspace_members` read, reads `ENABLE_HABITS` from `workspace_secrets` with exact `value === "true"` matching, and returns the legacy enabled access payload.                                                                                                                                                                                                                                                                                          |
| `GET /api/v1/workspaces/:wsId/mobile/module-flags`                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token, rejects app-session tokens, resolves the legacy `internal` workspace slug, requires workspace membership through a caller-token `workspace_members` read, reads `MOBILE_HIDE_EXPERIMENTAL_MODULES` and `MOBILE_HIDDEN_MODULES` from `workspace_secrets` through the server-owned Supabase REST adapter, preserves JSON-array and comma-separated hidden-module parsing, and returns sorted `hiddenModuleIds` with the legacy private cache directive.                                                                                                                                                                     |
| `GET /api/v1/workspaces/:wsId/education/access`                                                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token, mirrors getPermissions-style workspace permission resolution for `ai_lab`, reads `ENABLE_EDUCATION` from `workspace_secrets` through the server-owned Supabase REST adapter, and preserves the legacy access-probe behavior where workspace, feature-flag, permission, and lookup failures return `200` with `enabled: false`.                                                                                                                                                                                                                                                                                            |
| `GET /api/v1/workspaces/:wsId/finance/budgets/status`                                                                                                                                                                      | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts finance/platform app-session tokens and CLI app-session tokens before falling back to a normal Supabase browser session or non-app-session Bearer token, normalizes internal, personal, handle, and UUID workspace identifiers, requires `manage_finance` through `has_workspace_permission`, calls `get_budget_status` with the service-role credential, returns the raw legacy RPC payload, and preserves the legacy Unauthorized, Insufficient permissions, and Error fetching budget status bodies.                                                                                                                                                                                          |
| `GET /api/workspaces/:wsId/finance/charts/balance`                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts finance/platform app-session tokens and CLI app-session tokens before normal Supabase fallback, normalizes workspace identifiers, requires `view_finance_stats`, preserves the legacy required `date` query plus `includeConfidential` parsing, calls `get_wallet_balance_at_date`, and returns the legacy balance/date payload, Unauthorized, Forbidden, invalid-query, and balance lookup error bodies.                                                                                                                                                                                                                                                                                        |
| `GET /api/v1/workspaces/:wsId/finance/debts/summary`                                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts finance/platform app-session tokens and CLI app-session tokens before normal Supabase fallback, normalizes internal, personal, handle, and UUID workspace identifiers, requires `manage_finance`, calls private-schema `get_debt_loan_summary` with `_actor_id` and `_ws_id` using service-role auth, returns the first legacy RPC row or the zero summary, and preserves the legacy Unauthorized, Insufficient permissions, and Error fetching debt/loan summary bodies.                                                                                                                                                                                                                        |
| `GET /api/v1/workspaces/:wsId/finance/filter-users`                                                                                                                                                                        | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts finance/platform app-session tokens and CLI app-session tokens before normal Supabase fallback, normalizes workspace identifiers, requires `view_transactions`, preserves the legacy `type` branches, reads transaction and invoice creator filters through service-role Supabase REST with explicit `ws_id` filters, reads workspace users with the caller token for normal Supabase sessions and service-role auth for app sessions, and preserves the legacy users payload, Unauthorized, and branch-specific failure bodies.                                                                                                                                                                 |
| `GET /api/v1/workspaces/:wsId/finance/invoices/subscription/context`                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts finance/platform app-session tokens and CLI app-session tokens before normal Supabase fallback, normalizes workspace identifiers, requires `create_invoices`, preserves the legacy missing-query short-circuit, validates requested student groups inside the workspace, reads month-scoped attendance and completed invoice history through service-role Supabase REST, returns the legacy attendance and latest paid invoice context shape, and preserves the legacy Unauthorized and subscription-context error bodies.                                                                                                                                                                       |
| `GET /api/v1/workspaces/:wsId/finance/recurring-transactions/upcoming`                                                                                                                                                     | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the upcoming transactions route `migrated`; Rust accepts finance/platform app-session tokens and CLI app-session tokens before normal Supabase fallback, normalizes workspace identifiers, requires `view_transactions`, preserves JavaScript parseInt-style `daysAhead` parsing with a 30-day fallback, calls `get_upcoming_recurring_transactions` with caller-token auth for normal Supabase sessions and service-role auth for app sessions, and preserves the legacy upcomingTransactions payload, `403` Unauthorized, and fetch-failure bodies. Recurring transaction collection and detail routes remain legacy-owned.                                                                                                  |
| `GET /api/v1/workspaces/:wsId/settings/permissions`                                                                                                                                                                        | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token, rejects app-session tokens, resolves personal/workspace identifiers, mirrors `getPermissions` role/default/creator/admin behavior, and returns the legacy `manage_subscription`, `manage_workspace_settings`, and `manage_workspace_members` flags with the private 30-second success cache directive.                                                                                                                                                                                                                                                                                                                    |
| `GET /api/v1/workspaces/:wsId/settings/permissions/check`                                                                                                                                                                  | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token, ignores app-session tokens and the legacy `userId` query, resolves personal/workspace identifiers, requires workspace access, and mirrors `getPermissions` role/default/creator/admin behavior before returning the hasPermission payload.                                                                                                                                                                                                                                                                                                                                                                                |
| `GET /api/v1/workspaces/:wsId/course-modules` and `GET /api/v1/workspaces/:wsId/quiz-sets/:setId/linked-modules`                                                                                                           | `apps/backend` Rust route dispatcher | `route-overrides.json` marks both education read endpoints `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token, resolves `ai_lab` workspace permission, requires the `ENABLE_EDUCATION` secret, reads course modules through service-role Supabase REST with exact-count page/pageSize/q behavior, and verifies linked quiz sets belong to the resolved workspace before listing linked modules.                                                                                                                                                                                                                                                                                                                      |
| `GET` / `PATCH` `/api/v1/user/onboarding-progress`                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust validates the browser Supabase session with Supabase Auth, reads or upserts only the authenticated user's `onboarding_progress` row through the server-owned Supabase REST adapter, preserves the legacy allowed-field filter, null missing-row response, invalid/empty update errors, and method handling.                                                                                                                                                                                                                                                                                                                                                                                              |
| `PATCH /api/v1/user/profile`                                                                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust validates the browser Supabase session with Supabase Auth, validates `display_name`, `bio`, and `avatar_url` with the legacy limits, ignores unknown fields, updates only the authenticated user's `users` row through the server-owned Supabase REST adapter, and preserves the legacy success/error response messages.                                                                                                                                                                                                                                                                                                                                                                                 |
| `GET` / `PATCH` `/api/v1/users/me/default-workspace`                                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts current-user app-session tokens or revalidated browser Supabase sessions for reads, preserves the legacy `null` fallback when workspace data cannot be resolved, falls back from an inaccessible saved default to the caller's personal workspace, and updates `user_private_details.default_workspace_id` only after validating the `workspaceId` field as a UUID or `null` and verifying workspace membership with the caller token.                                                                                                                                                                                                                                                           |
| `GET` / `PATCH` `/api/v1/users/calendar-settings`                                                                                                                                                                          | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust accepts calendar app-session tokens or revalidated browser Supabase sessions, reads and updates the authenticated user's `timezone`, `first_day_of_week`, and `time_format` from `user_private_details`, defaults missing values to `auto`, strips unknown patch fields, validates the legacy enum/string limits, and preserves private read cache plus no-store mutation responses.                                                                                                                                                                                                                                                                                                                     |
| `GET /api/v1/users/me/identities`                                                                                                                                                                                          | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates a normal Supabase browser session or non-app-session Bearer token with Supabase Auth, rejects Tuturuuu app-session tokens, extracts the Auth JS-compatible `identities` array from the revalidated Supabase user JSON, returns the legacy identities/canUnlink payload, and keeps the legacy private cache directive plus auth, Supabase rejection, and internal error bodies.                                                                                                                                                                                                                                                                                                               |
| `PATCH /api/v1/users/me/full-name`                                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust revalidates the browser Supabase session cookie or non-app-session Bearer token with Supabase Auth, validates `full_name` as a required JSON string with trimmed length `1..100`, and upserts `user_private_details` with `user_id` fixed to the authenticated user through Supabase REST using the caller token and `on_conflict=user_id`.                                                                                                                                                                                                                                                                                                                                                              |
| `POST /api/v1/aurora/health`                                                                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust validates the browser Supabase session with Supabase Auth, preserves the exact `@tuturuuu.com` email-domain gate, calls `AURORA_EXTERNAL_URL/health`, and returns the legacy success, auth, forbidden, and upstream-failure JSON bodies.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `GET` / `POST` `/api/v1/aurora/forecast`, `GET` / `POST` `/api/v1/aurora/ml-metrics`, `GET` / `POST` `/api/v1/aurora/statistical-metrics`                                                                                  | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the Aurora forecast and metrics method artifacts `migrated`; Rust reads public Aurora forecast and metric tables through the server-owned Supabase REST adapter for GET. POST ingest routes preserve the legacy `AURORA_EXTERNAL_URL` and `AURORA_EXTERNAL_WSID` checks, Supabase session revalidation, exact `@tuturuuu.com` email-domain gate, external Aurora fetches, normalized Supabase inserts with the caller token, and legacy success/error JSON bodies.                                                                                                                                                                                                                                                                  |
| `GET` / `POST` `/api/v1/infrastructure/changelog`, `GET` / `PUT` / `DELETE` `/api/v1/infrastructure/changelog/:id`, `POST /api/v1/infrastructure/changelog/:id/publish`, `GET /api/v1/infrastructure/changelog/slug/:slug` | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the collection, detail, publish, and slug route artifacts `migrated`; Rust reads `changelog_entries` through the server-owned Supabase REST adapter, validates browser Supabase auth cookies with Supabase Auth before checking root workspace `manage_changelog`, falls back to published-only public reads for anonymous or unauthorized sessions, preserves exact-count list pagination, singular PostgREST detail/slug lookups, write authorization and validation, publish/unpublish timestamp behavior, and maps `PGRST116` to the legacy `404` body. Media upload remains legacy-owned.                                                                                                                                      |
| `GET /api/v1/inventory/storefronts/:slug`, `GET /api/v1/inventory/orders/:publicToken`                                                                                                                                     | `apps/backend` Rust route dispatcher | `route-overrides.json` marks both public inventory read endpoints `migrated`; Rust keeps storefront/order data behind private inventory RPCs and service-role private-schema metadata reads, preserves public storefront CDN cache headers, private storefront/order app-session and browser-session membership checks, simulated HMAC order tokens, private no-store cache headers, and legacy `401`/`403`/`404`/`500` JSON bodies. Storefront checkout creation, analytics events, Polar webhooks, and workspace inventory management remain legacy-owned.                                                                                                                                                                                                     |
| `GET /api/v1/topic-announcement-verifications/:token`                                                                                                                                                                      | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust decodes the token path segment, hashes it with SHA-256, reads and updates `private.topic_announcement_contact_verifications` through the server-owned Supabase REST adapter, and returns the legacy public HTML pages for verified, unavailable/already-used, expired, and failed links. Workspace Topic Announcements management APIs remain legacy-owned.                                                                                                                                                                                                                                                                                                                                              |
| `POST` / `DELETE` `/api/v1/infrastructure/languages`                                                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy locale validation bodies and `NEXT_LOCALE` set/delete cookie behavior.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `POST` / `DELETE` `/api/v1/infrastructure/sidebar`                                                                                                                                                                         | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy collapsed-sidebar validation body and `sidebar-collapsed` set/delete cookie behavior.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `POST` / `DELETE` `/api/v1/infrastructure/sidebar/sizes`                                                                                                                                                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy size validation body, two-cookie write behavior, and DELETE behavior that clears only `sidebar-size`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `GET /api/v1/infrastructure/users/fields/types`                                                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust returns the deterministic ordered legacy field type payload without opening a Supabase admin client for static metadata.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `GET /api/v1/infrastructure/ai/models`                                                                                                                                                                                     | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust reads `private.ai_gateway_models` through the server-owned Supabase REST adapter with private-schema headers, preserves the fixed public column list, default `type=language` filtering, provider/tag/enabled/search/ids filters, exact-count pagination, and caps ID filters at 100 so private model metadata stays behind the backend.                                                                                                                                                                                                                                                                                                                                                                 |
| `OPTIONS /api/v1/auth/password-login`, `/otp/send`, and `/otp/verify`; `GET` / `OPTIONS` `/api/v1/auth/otp/settings`                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the shared auth preflight method artifacts plus OTP settings `GET` migrated; Rust preserves wildcard CORS, public client/platform validation, `WEB_OTP_ENABLED` reads for web/tulearn, mobile OTP policy reads, non-mobile fail-open diagnostics, and mobile fail-closed errors while the paired OTP send/verify and password auth methods remain `legacy-next`.                                                                                                                                                                                                                                                                                                                                                                    |
| `OPTIONS /api/v1/auth/mobile/password-login`, `/send-otp`, and `/verify-otp`                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `OPTIONS` method artifacts `migrated`; Rust preserves the shared legacy wildcard CORS `204` response while the `POST` auth methods remain `legacy-next`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `GET` / `OPTIONS` `/api/v1/mobile/version-check`                                                                                                                                                                           | `apps/backend` Rust route dispatcher | `route-overrides.json` marks both method artifacts `migrated`; Rust preserves public strict query validation, root workspace mobile policy config reads through the server-owned Supabase REST adapter, legacy update-status evaluation, and the shared wildcard CORS response headers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `OPTIONS /api/v1/auth/qr-login/challenges`, `/:challengeId`, `/:challengeId/approve`                                                                                                                                       | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `OPTIONS` method artifacts `migrated`; Rust preserves the legacy bare empty `204` response while QR challenge creation, polling, and approval remain `legacy-next`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `OPTIONS /api/v1/auth/mfa/mobile/challenges` and `/approvals`                                                                                                                                                              | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `OPTIONS` method artifacts `migrated`, including dynamic challenge polling and approval paths; Rust preserves the legacy bare empty `204` response while challenge creation, polling, approval, and approval listing remain `legacy-next`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `OPTIONS /api/v1/workspaces/:wsId/external-projects/webgl-packages/upload`                                                                                                                                                 | `apps/backend` Rust route dispatcher | `route-overrides.json` marks only the `OPTIONS` method artifact `migrated`; Rust preserves the legacy origin-dependent CMS upload CORS `204` response while the protected `PUT` upload remains `legacy-next`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `POST /api/v1/workspaces/:wsId/user-groups/:groupId/group-checks/:postId/email`                                                                                                                                            | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy `410 Gone` response for removed direct post email sending.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `GET` / `POST` `/api/v1/workspaces/:wsId/slides`                                                                                                                                                                           | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the current `501 Not implemented` placeholder contract without adding protected workspace slide data access.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `PUT` / `DELETE` `/api/v1/workspaces/:wsId/slides/:slideId`                                                                                                                                                                | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the current `501 Not implemented` placeholder contract without adding protected workspace slide data access.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `PUT /api/v1/infrastructure/migrate/grouped-score-names`                                                                                                                                                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the route `migrated`; Rust preserves the legacy development-only guard and the disabled `410 MIGRATION_DISABLED` response for the removed `user_group_indicators` table.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `GET` / `PUT` / `PATCH` / `POST` `/api/v1/infrastructure/migrate/:migration`                                                                                                                                               | `apps/backend` Rust route dispatcher | `route-overrides.json` marks the legacy one-off batch migration helpers `accepted-removal`; Rust preserves the development/local-E2E guard and legacy method allow lists, but returns terminal `410 MIGRATION_DISABLED` instead of exposing broad admin batch reads or writes through the Cloudflare-compatible backend.                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `PUT /api/workspaces/:wsId/products/categories/migrate`, `/products/units/migrate`, `/transactions/categories/migrate`, `/users/indicators/migrate`, and `/wallets/transactions/migrate`                                   | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these obsolete workspace migration writes `accepted-removal`; Rust preserves the development-only guard and returns the terminal `410 MIGRATION_DISABLED` decommission body instead of preserving legacy Supabase data writes.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `GET` / `POST` `/api/v1/workspaces/:wsId/encryption/migrate`, `POST /api/v1/workspaces/:wsId/storage/migrate`, `GET /api/v2/workspaces/:wsId/migrate/:module`                                                              | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these production auth/API-key migration helpers `accepted-removal`; Rust preserves each legacy method allow list but returns terminal `410 MIGRATION_DISABLED` in every environment instead of preserving broad admin calendar encryption, storage migration, or migration export data paths.                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `GET /api/share/course/:courseId`, `GET /api/sync-logs`, `GET /api/users/search`, `GET /api/v1/proxy/tuturuuu`                                                                                                             | `apps/backend` Rust route dispatcher | `route-overrides.json` marks these retired legacy API aliases, broad maintenance/search routes, and the development-only Tuturuuu API proxy `accepted-removal`; Rust returns terminal `410 ENDPOINT_REMOVED` with legacy `Allow` headers while maintained replacements, workspace-scoped readers, phase-specific routes, or direct backend/internal API clients remain separate migration work. Payment paths are not claimed by this compatibility responder and therefore return the normal platform `404`.                                                                                                                                                                                                                                                    |

First TanStack Start migrated ownership:

| Legacy route                                                                                                                                                                                                                                                                    | New owner                                         | Evidence                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/:locale`                                                                                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start static route   | `route-overrides.json` marks the landing page, landing metadata layout, and shared marketing layout `migrated`; the Start route preserves the public English and Vietnamese landing content with local primitives and no framer-motion, Next.js APIs, auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                         |
| `/:locale/docs`                                                                                                                                                                                                                                                                 | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page `migrated`; `/:locale/docs` throws a TanStack Router `307` redirect to `https://docs.tuturuuu.com`.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `/:locale/calendar/meet-together/[[...slug]]`                                                                                                                                                                                                                                   | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page `migrated`; `/:locale/calendar/meet-together` and nested slug paths redirect to `/meet-together` while preserving trailing slug segments.                                                                                                                                                                                                                                                                                                                                                                                   |
| `/:locale/pricing`                                                                                                                                                                                                                                                              | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page `migrated`; `/pricing` and `/:locale/pricing` throw a TanStack Router `307` redirect to `/?hash-nav=1#pricing`.                                                                                                                                                                                                                                                                                                                                                                                                             |
| `/:locale/about`                                                                                                                                                                                                                                                                | `apps/tanstack-web` TanStack Start static route   | `route-overrides.json` marks the about page and metadata-only layout `migrated`; the Start route preserves the legacy English and Vietnamese `about.*` message namespace through TanStack-local message files and renders without framer-motion, Next.js APIs, auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                |
| `/:locale/contact`                                                                                                                                                                                                                                                              | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the page and metadata layout `migrated`; the Start route preserves the visible contact shell, hydrates the current-user contact profile through TanStack Query and Start server functions, and submits inquiries through `@tuturuuu/internal-api` Rust backend facades for `/api/v1/users/me/profile` and `/api/v1/inquiries`.                                                                                                                                                                                                       |
| `/:locale/users/:handle`                                                                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the auth-gated marketing profile page `migrated`; the Start route preserves fail-closed current-user auth, locale-aware login redirects with `nextUrl`, private no-store headers, caller-scoped reads of the legacy public `users` profile fields through the internal-api `users-server` facade, the profile background/avatar shell, and explicit no-auth Playwright coverage. A Rust-owned public profile reader remains the follow-up before removing the temporary request-scoped Supabase helper.                              |
| `/:locale/contributors`                                                                                                                                                                                                                                                         | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the page `migrated`; the Start route preserves the public contributors shell, GitHub repository/contributor data loading, loading and error states, stats, contributor list, CTA links, and analytics sections through TanStack Query. Dependency-free CSS/SVG equivalents are accepted for the legacy `framer-motion`, Recharts, and `react-confetti` visuals.                                                                                                                                                                      |
| `/:locale/women-in-tech`                                                                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the page and metadata layout `migrated`; the Start route preserves the localized legacy title, Open Graph/Twitter/head metadata, public Vietnamese Women's Day content, copied media, local language switcher, and section structure. Dependency-free native image and CSS animation replacements are accepted for the legacy Next/framer-motion runtime.                                                                                                                                                                            |
| `/:locale/acceptable-use`, `/community-guidelines`, `/privacy`, and `/terms`                                                                                                                                                                                                    | `apps/tanstack-web` TanStack Start static routes  | `route-overrides.json` marks each legal page and metadata-only layout `migrated`; the Start routes preserve the legacy static legal content, local legal primitives, and metadata without auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                                                                     |
| `/:locale/partners`                                                                                                                                                                                                                                                             | `apps/tanstack-web` TanStack Start static route   | `route-overrides.json` marks the partners page and metadata-only layout `migrated`; the Start route preserves the legacy partner content, CTAs, outbound links, local partner primitives, and copied public logo assets without auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                               |
| `/:locale/products/ai`, `/calendar`, `/crm`, `/documents`, `/drive`, `/finance`, `/inventory`, `/lms`, `/mail`, `/tasks`, and `/workflows`                                                                                                                                      | `apps/tanstack-web` TanStack Start static routes  | `route-overrides.json` marks each static product page and layout `migrated`; the Start routes preserve the legacy product copy, metadata, and shared page primitives without adding auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                                                                           |
| `/:locale/ai/chats/:chatId`                                                                                                                                                                                                                                                     | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the public AI chat page and metadata layout `migrated`; the Start route fetches only `ai_chats.is_public=true` rows and their ordered public messages through a server function backed by Supabase REST, hydrates with TanStack Query, preserves not-found behavior for missing/private chats, and renders a read-only transcript instead of the dashboard streaming chat client.                                                                                                                                                    |
| `/:locale/documents/:documentId`                                                                                                                                                                                                                                                | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the public document page and layout `migrated`; the Start route fetches only public `workspace_documents` rows through a server function, hydrates with TanStack Query, preserves fail-closed not-found behavior, and keeps the current empty document body shell. The migrated layout uses stable localized generic head metadata instead of the legacy document-name Open Graph lookup to avoid a second metadata-time Supabase dependency.                                                                                        |
| `/:locale/products/meet-together`                                                                                                                                                                                                                                               | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page `migrated`; `/products/meet-together` and `/:locale/products/meet-together` throw a TanStack Router `307` redirect to `/meet-together`.                                                                                                                                                                                                                                                                                                                                                                                     |
| `/:locale/qr-generator`                                                                                                                                                                                                                                                         | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page `migrated`; `/qr-generator` and `/:locale/qr-generator` redirect to the QR app origin and forward the raw query string so duplicate query keys are preserved.                                                                                                                                                                                                                                                                                                                                                               |
| `/:locale/changelog`                                                                                                                                                                                                                                                            | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the changelog index page `migrated`; the Start route reads the Rust-owned public changelog `GET` API through a server function, hydrates the list with TanStack Query, applies ISR-style CDN headers, and falls back to an empty public state when the backend cannot return published entries.                                                                                                                                                                                                                                      |
| `/:locale/changelog/:slug`                                                                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the changelog detail page `migrated`; the Start route reads the Rust-owned public changelog slug `GET` API through a server function, hydrates the entry with TanStack Query, reuses the public changelog list for adjacent navigation, applies ISR-style CDN headers, and throws the TanStack not-found response when the slug is missing. No-auth coverage uses a deterministic missing-slug 404 example so empty databases remain valid.                                                                                          |
| `/:locale/:wsId/changelog`                                                                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the dashboard changelog page artifact `migrated`; the Start route preserves fail-closed current-user auth, forwarded workspace resolution, dashboard card/list parity, public changelog links, and TanStack Query loading through the Rust-owned changelog list API instead of direct Supabase reads.                                                                                                                                                                                                                                |
| `/:locale/:wsId/infrastructure/changelog`                                                                                                                                                                                                                                       | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the infrastructure changelog admin list page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, `manage_changelog` settings redirect parity, URL search filters, TanStack Query hydration, legacy table columns/actions, and Rust-backed changelog list loading instead of direct service-role Supabase reads. New/edit pages and media upload remain separately tracked.                                                                                                           |
| `/tools/random`, `/:locale/tools/random`                                                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start route loaders  | The Start routes preserve the current web proxy contract by redirecting to `apps/tools /random` and forwarding the raw query string. The generator UI is owned by the tools satellite, not the platform shell.                                                                                                                                                                                                                                                                                                                                                    |
| `/:locale/branding`, `/blog`, and `/careers`                                                                                                                                                                                                                                    | `apps/tanstack-web` TanStack Start static routes  | `route-overrides.json` marks the visible marketing pages and metadata-only layouts `migrated`; the Start routes preserve the static brand, blog placeholder, and careers content without auth, Supabase, or protected workspace data access. Branding Open Graph/Twitter image artifacts remain legacy-owned.                                                                                                                                                                                                                                                     |
| `/:locale/facebook-mockup`                                                                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start client route   | `route-overrides.json` marks the page `migrated`; the Start route preserves the public Facebook mockup demo with local browser-safe components and no auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                                                                                                         |
| `/:locale/security`                                                                                                                                                                                                                                                             | `apps/tanstack-web` TanStack Start static route   | `route-overrides.json` marks the security landing page and metadata-only layout `migrated`; the Start route preserves the legacy static security copy, vulnerability-reporting CTAs, trust sections, and local primitives without framer-motion, Next.js APIs, auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                |
| `/:locale/security/policy` and `/bug-bounty`                                                                                                                                                                                                                                    | `apps/tanstack-web` TanStack Start static routes  | `route-overrides.json` marks the security policy page, Security Hall of Fame page, and bug-bounty metadata-only layout `migrated`; the Start routes preserve the legacy responsible-disclosure and researcher-credit copy with local security primitives and no auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                               |
| `/:locale/solutions/construction`, `/education`, `/healthcare`, `/hospitality`, `/manufacturing`, `/pharmacies`, `/realestate`, `/restaurants`, and `/retail`                                                                                                                   | `apps/tanstack-web` TanStack Start static routes  | `route-overrides.json` marks every static solution page and layout `migrated`; the Start routes preserve legacy copy, metadata, FAQ content, CTAs, success metrics, and local solution primitives without framer-motion, Next.js APIs, auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                        |
| `/:locale/ui`, `/:locale/ui/setup`, `/:locale/ui/contributing`, `/:locale/ui/components`, `/:locale/ui/components/:componentId`                                                                                                                                                 | `apps/tanstack-web` TanStack Start static routes  | `route-overrides.json` marks the public UI showcase layout and pages `migrated`; the Start routes preserve the UI docs shell, setup/contribution pages, component index, and component detail views through local registry/docs data without auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                  |
| `/:locale/visualizations/horse-racing`                                                                                                                                                                                                                                          | `apps/tanstack-web` TanStack Start client route   | `route-overrides.json` marks the page `migrated`; the Start route preserves the public horse-racing algorithm visualization with local TanStack-safe visualization components and no auth, Supabase, or protected workspace data access.                                                                                                                                                                                                                                                                                                                          |
| `/:locale/verify-token`                                                                                                                                                                                                                                                         | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page `migrated`; the Start route preserves the legacy `nextUrl` redirect sanitizer and `/onboarding` fallback without importing Next auth/session runtime into the Cloudflare-compatible frontend.                                                                                                                                                                                                                                                                                                                               |
| `/:locale/shared/user-profile/:code`                                                                                                                                                                                                                                            | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves the legacy noindex head, profile-link loader, fail-closed auth redirect for protected links, unavailable shell for expired/revoked links, localized fill form, and allowlist-scoped prefill behavior. Submit/avatar APIs still route through `packages/internal-api` and remain separate backend migration work.                                                                                                                                                             |
| `/:locale/shared/task/:shareCode`                                                                                                                                                                                                                                               | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user resolution before task data fetch, the legacy login redirect with `nextUrl`, noindex metadata, unavailable shell for revoked links, and shared task dialog rendering. `/api/v1/shared/tasks/:shareCode` remains legacy-owned backend work.                                                                                                                                                                                                          |
| `/:locale/shared/task-boards/:code`                                                                                                                                                                                                                                             | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves noindex metadata, unavailable-shell behavior for missing or revoked public board links, no-store loading through the `packages/internal-api` public board facade, and read-only public `BoardViews` rendering through TanStack-local payload adapters. `/api/v1/shared/task-boards/:code` remains legacy-owned backend work.                                                                                                                                                 |
| `/:locale/:wsId/finance` route layout plus `/:locale/:wsId/finance` and `/:locale/:wsId/finance/{analytics,budgets,categories,debts,debts/:debtId,invoices,invoices/:invoiceId,invoices/new,recurring,tags,transactions,transactions/:transactionId,wallets,wallets/:walletId}` | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks the Finance route-specific layout and page artifacts `migrated`; the Start routes preserve the accepted 307 redirects to the platform Finance paths and forward raw query strings so creation/search/pagination handoff parameters survive. Dynamic finance IDs are encoded before handoff. The legacy Finance layout's command/provider UI is not rendered in TanStack because these migrated leaves redirect; parent dashboard/session and Finance data ownership remain legacy-owned until workspace provider parity is complete. |
| `/:locale/:wsId/mail` route layout plus `/:locale/:wsId/mail` and `/:locale/:wsId/mail/sent` pages                                                                                                                                                                              | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks the Mail leaf pages `migrated` and the legacy route-specific Mail layout `accepted-removal`; the Start leaves preserve 307 handoff to the standalone Mail app through `buildMailRedirectHref`, while the Mail app centralized auth proxy and workspace-normalization boundary replace the legacy dashboard layout gate. Parent dashboard/session ownership remains legacy-owned until workspace provider parity is complete.                                                                                                         |
| `/:locale/:wsId/workforce`, `/ai-chat/new`, `/meet`, `/qr-generator`, `/drive`, education library/builder pages, `/epm`, and `/external-projects`                                                                                                                               | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks these page artifacts `migrated`; the Start routes preserve the legacy 307/308 redirects to workspace user database, chat, meet plans, QR app with query forwarding, Drive app handoff with workspace slug normalization, education library/builder, and CMS app destinations. Parent dashboard layout/session ownership remains legacy-owned until workspace provider parity is complete.                                                                                                                                            |
| `/:locale/:wsId/education/quiz-sets/:setId`                                                                                                                                                                                                                                     | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, quiz table search/pagination with the legacy 10-row default, forwarded-auth internal-api quiz reads, and TanStack Query-backed create/update/delete plus AI explanation actions. The quiz-set detail layout and quiz APIs remain separately tracked.                                                                                                                                                                    |
| `/:locale/:wsId/education/quiz-sets/:setId/linked-modules`                                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, linked course module table parity, and link/unlink workflow through forwarded-auth internal-api facades backed by Rust-owned education read endpoints. Parent dashboard/session ownership remains legacy-owned.                                                                                                                                                                                                         |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/content`                                                                                                                                                                                                          | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, forwarded internal-api module reads, localized module content summary, and TanStack Query/internal-api-backed debounced content saves. The parent module layout and module API ownership remain separately tracked.                                                                                                                                                                                                     |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/quizzes`                                                                                                                                                                                                          | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, the legacy `update_user_groups` not-found gate before data loading, URL-backed quiz search/pagination, and forwarded-auth internal-api quiz reads plus shared quiz table edit/delete actions. Quiz API and AI quiz-generation backend ownership remain separately tracked.                                                                                                                                              |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/quizzes/new`                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, localized manual quiz creation shell, and TanStack Query-backed submission through the internal-api quiz facade. Quiz create/update API ownership and the module quiz list page remain separately tracked.                                                                                                                                                                                                              |
| `/:locale/:wsId/hive` route layout                                                                                                                                                                                                                                              | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks the route-specific layout artifact `migrated`; the migrated Hive leaves redirect to the standalone Hive app, while the legacy layout only imported `@xyflow/react` styles and returned children. Hive APIs and parent dashboard/session ownership remain legacy-owned.                                                                                                                                                                                                                                                               |
| `/:locale/:wsId/mind/boards/:boardId` route layout                                                                                                                                                                                                                              | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the route-specific layout artifact `migrated`; the migrated Mind board page redirects to the standalone Mind board route with query forwarding, while the legacy layout only imported `@xyflow/react` styles and returned children. Mind APIs and parent dashboard/session ownership remain legacy-owned.                                                                                                                                                                                                                            |
| `/:locale/:wsId/documents/:documentId` route layout                                                                                                                                                                                                                             | `apps/tanstack-web` TanStack Start metadata       | `route-overrides.json` marks the static Document Details metadata layout artifact `migrated`; the legacy layout only exported title/description metadata and returned children. The document detail page, workspace dashboard/session ownership, and document data/API routes remain legacy-owned.                                                                                                                                                                                                                                                                |
| `/:locale/:wsId/infrastructure` and `/:locale/:wsId/platform` parent layouts                                                                                                                                                                                                    | `apps/tanstack-web` TanStack Start parent loaders | `route-overrides.json` marks both layout artifacts `migrated`; the Start parent routes preserve fail-closed current-user auth, workspace resolution, root `view_infrastructure` permission gating, and `Outlet` rendering for migrated children. The exact infrastructure analytics page, platform billing, platform roles, and remaining settings children stay separately tracked as legacy-next artifacts.                                                                                                                                                     |
| `/:locale/:wsId/epm/collections/:collectionId`, `/epm/entries/:entryId`, `/platform/external-projects`, and `/users/topic-announcements`                                                                                                                                        | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks these page artifacts `migrated`; the Start routes preserve the legacy 307 redirects to CMS collection/entry/admin destinations and legacy dashboard aliases. Infrastructure settings/app-coordination routes now live in `apps/infrastructure` and the old TanStack/web route is recorded as an accepted removal. Parent dashboard layout/session ownership remains legacy-owned until workspace provider parity is complete.                                                                                                        |
| `/:locale/:wsId/ai-chat/chatbots`                                                                                                                                                                                                                                               | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, `ai_chat` permission gating, route metadata, and localized `FeatureSummary` content. The create action intentionally targets the canonical `/:locale/:wsId/ai-chat/my-chatbots/new` Start route instead of the legacy `/:wsId/chat` alias. Parent dashboard and AI chat session/provider ownership remains legacy-owned.                                                                                                |
| `/:locale/:wsId/ai-chat/my-chatbots`                                                                                                                                                                                                                                            | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, the legacy `ai_chat` layout permission gate, URL-backed table search/pagination, forwarded-auth group-tag reads, internal-api-backed row deletion, and localized `FeatureSummary`/`CustomDataTable` UI. Parent dashboard and AI chat session/provider ownership remains legacy-owned.                                                                                                                                   |
| `/:locale/:wsId/ai-chat/my-chatbots/new`                                                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start client route   | `route-overrides.json` marks the static metadata layout and client-only form page `migrated`; the Start route preserves the local validation, localized summary strings, and submit toast behavior without adding protected API, Supabase, or server-action access. Parent dashboard and AI chat session/provider ownership remains legacy-owned.                                                                                                                                                                                                                 |
| `/:locale/:wsId/users/group-tags`                                                                                                                                                                                                                                               | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, URL-backed table search/pagination, forwarded-auth group-tag reads, internal-api-backed group-tag mutations/row actions, localized `FeatureSummary`/`CustomDataTable` UI, and locale-prefixed detail hrefs. Group-tag API ownership remains separately tracked for the backend Rust wave.                                                                                                                               |
| `/:locale/:wsId/users/group-tags/:tagId`                                                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the dynamic no-store Start route preserves fail-closed current-user auth, workspace resolution, URL-backed linked-group search/pagination, forwarded-auth tag detail and linked-group reads, TanStack Query-backed add/remove linked-group actions, localized `FeatureSummary`/`CustomDataTable` UI, and locale-prefixed group detail hrefs. Group-tag API ownership remains separately tracked for the backend Rust wave.                                                                             |
| `/:locale/:wsId/settings/reports`                                                                                                                                                                                                                                               | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, `manage_user_report_templates` gating, URL-backed `q` search state, report and lead-generation template tables, preview panels, and edit/reset actions through TanStack Query server functions plus `packages/internal-api` workspace-config facades.                                                                                                                                                                   |
| `/:locale/:wsId/settings/notifications`                                                                                                                                                                                                                                         | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, workspace resolution, account notification status, workspace-wide enable/disable, browser permission controls, and editable event/channel preferences through TanStack Query server functions plus `packages/internal-api` notification preference facades. Notification preference API artifacts remain separately tracked Rust backend work.                                                                                                |
| `/:locale/:wsId/billing/success`                                                                                                                                                                                                                                                | `apps/pay` satellite app via TanStack redirect    | `route-overrides.json` marks the legacy success page as a `satellite-app` accepted replacement; the Start route issues a `307` to Pay and preserves the complete query string, including `checkoutId`. Checkout result rendering and payment reads remain Pay-owned.                                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/inventory`                                                                                                                                                                                                                                                      | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the root inventory dashboard page artifact `migrated`; the Start route preserves fail-closed current-user auth, forwarded-auth workspace resolution, `view_inventory` permission handling, localized access-denied state, statistic-card loading/error states, and inventory statistics loaded through the internal-api facade. `/api/v1/workspaces/:wsId/inventory/statistics` and deeper inventory pages remain separately tracked.                                                                                                |
| `/:locale/:wsId/inventory/batches`                                                                                                                                                                                                                                              | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the inventory batches page artifact `migrated`; the Start route preserves fail-closed current-user auth, forwarded-auth workspace resolution, `view_inventory` permission handling, localized access-denied state, URL-backed `q`/`page`/`pageSize` search state, and TanStack Query table loading through the internal-api inventory facade. `/api/v1/workspaces/:wsId/inventory/batches` remains separately tracked backend work.                                                                                                  |
| `/:locale/:wsId/inventory/categories`, `/manufacturers`, `/suppliers`, `/units`, and `/warehouses`                                                                                                                                                                              | `apps/tanstack-web` TanStack Start dynamic routes | `route-overrides.json` marks these inventory resource page artifacts `migrated`; the Start routes preserve fail-closed current-user auth, forwarded-auth workspace resolution, inventory view/create/update/delete or catalog/setup permission booleans, localized access-denied states, URL-backed `q`/`page`/`pageSize` table state, and TanStack Query table loading plus create/update/delete actions through the internal-api inventory facades. The matching workspace inventory and product compatibility APIs remain separately tracked backend work.     |
| `/:locale/:wsId/inventory/products` and `/:productId`                                                                                                                                                                                                                           | `apps/tanstack-web` TanStack Start dynamic routes | `route-overrides.json` marks the inventory product list and product detail/new form page artifacts `migrated`; the Start routes preserve fail-closed auth, workspace resolution, inventory and stock permission parity, route metadata, localized access-denied state, and TanStack Query product list/form loading plus mutations through internal-api inventory facades. Workspace inventory product APIs remain separately tracked backend work.                                                                                                               |
| `/:locale/:wsId/inventory/promotions`                                                                                                                                                                                                                                           | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the inventory promotions page artifact `migrated`; the Start route preserves fail-closed auth, workspace resolution, inventory view/create/update/delete permission context, route metadata, and TanStack Query CRUD through internal-api promotion facades. Workspace promotion API routes remain separately tracked backend work.                                                                                                                                                                                                  |
| `/:locale/:wsId/inventory/storefronts`                                                                                                                                                                                                                                          | `apps/tanstack-web` TanStack Start dynamic route  | `route-overrides.json` marks the inventory storefronts page artifact `migrated`; the Start route preserves fail-closed auth, workspace resolution, inventory catalog permission parity, route metadata, localized access-denied state, and TanStack Query reads/mutations through internal-api inventory storefront facades. Workspace storefront, listing, option-template, product, and public storefront APIs remain separately tracked backend work.                                                                                                          |
| `/:locale/:wsId/members`                                                                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the workspace members page artifact `migrated`; the Start route preserves fail-closed auth, workspace resolution, personal-workspace/settings redirect, `manage_workspace_members` and `manage_workspace_roles` context, tab search validation, metadata, and the shared workspace-access client. `disableInvite` currently defaults to false until a Rust/internal-api workspace secret reader lands for `DISABLE_INVITE`; invite-link creation remains protected by the existing server API check.                                 |
| `/:locale/:wsId/tasks` plus task cycles, estimates, initiatives, labels, logs, notes, projects, templates, and template marketplace pages                                                                                                                                       | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks these page artifacts `migrated`; the Start routes preserve authenticated workspace resolution, route metadata, and shared task UI clients. Project/cycle/initiative/log/template/estimate/label routes keep the legacy `manage_projects` permission gate through the forwarded-auth internal permission check, while the project/template detail routes load their initial data through forwarded-auth internal-api facades. Parent dashboard/session and remaining task data APIs remain separately owned.                          |
| `/:locale/:wsId/tasks/boards` and `/:locale/:wsId/tasks/boards/:boardId`                                                                                                                                                                                                        | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks both page artifacts `migrated`; the Start routes preserve authenticated board index/detail shells through shared task-board UI, the `next/navigation` runtime shim, forwarded-auth board authorization, legacy not-found mapping, and member/guest board access handling. The detail page omits the legacy Mira idle chat island until its local Next.js API/UI dependencies move behind shared TanStack/Rust facades.                                                                                                               |
| `/:locale/:wsId/calendar`, `/chat`, `/cron`, and `/memories`                                                                                                                                                                                                                    | `apps/tanstack-web` TanStack Start route loaders  | `route-overrides.json` marks these page artifacts `migrated`; the Start routes preserve authenticated workspace shells, route metadata, and legacy permission gates (`manage_calendar`, `view_chat`, or `ai_lab`) through forwarded-auth internal permission checks. Calendar/chat clients self-load through existing facades, while cron and memories keep data-free shared headers until app-local data clients move behind shared internal-api/Rust facades.                                                                                                   |
| `/:locale/:wsId/users/tutoring`                                                                                                                                                                                                                                                 | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, forwarded-auth full workspace resolution, personal-workspace and `view_user_groups` not-found handling, `update_user_groups_scores` management context, route metadata, and the shared tutoring client. Tutoring backing APIs remain separately tracked Rust migration work.                                                                                                                                                                  |
| `/:locale/:wsId/polls`                                                                                                                                                                                                                                                          | `apps/tanstack-web` TanStack Start static route   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves the legacy mock polls dashboard with local English/Vietnamese message bundles and shared UI primitives, without adding auth, Supabase, protected API, or server-action access. Parent dashboard layout/session ownership remains legacy-owned.                                                                                                                                                                                                                               |
| `/:locale/:wsId/users/structure`                                                                                                                                                                                                                                                | `apps/tanstack-web` TanStack Start static route   | `route-overrides.json` marks the page artifact `migrated`; the Start route ports the legacy local-state organizational-structure mock page, metadata, message bundle keys, canvas interactions, profile/details panel, and management dialogs without adding Supabase, protected API, or server-action access. Parent dashboard layout/session ownership remains legacy-owned.                                                                                                                                                                                    |
| `/:locale/:wsId/users/feedbacks`                                                                                                                                                                                                                                                | `apps/tanstack-web` TanStack Start route loader   | `route-overrides.json` marks the page artifact `migrated`; the Start route preserves fail-closed current-user auth, full workspace resolution, personal-workspace and `view_user_groups` not-found handling, `update_user_groups_scores` management context, route metadata, and the shared feedbacks client through internal-api user facades. Feedback data APIs remain separately tracked backend/internal-api work.                                                                                                                                           |
| `/:locale` error and not-found shells                                                                                                                                                                                                                                           | `apps/tanstack-web` root route                    | `route-overrides.json` marks both artifacts `migrated`; the Start root route owns the legacy reset button, localized `404` copy, and onboarding link through route error/not-found components.                                                                                                                                                                                                                                                                                                                                                                    |
| `/~offline` page                                                                                                                                                                                                                                                                | `apps/tanstack-web` TanStack Start route          | `route-overrides.json` marks the page `migrated`; the Start route renders the shared `OfflinePage` with the legacy title, message, and foreground/background classes.                                                                                                                                                                                                                                                                                                                                                                                             |
| `/~offline` layout                                                                                                                                                                                                                                                              | `apps/tanstack-web` root document                 | `route-overrides.json` marks the layout `migrated`; the Start root document imports shared UI globals and applies the legacy scroll/background body classes without relying on Next.js font helpers.                                                                                                                                                                                                                                                                                                                                                              |

Accepted removals:

| Legacy artifact                                                         | Decision           | Evidence                                                                                                                                                                                                                                                 |
| ----------------------------------------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apps/web/src/app/api/auth/me/session/route.ts`                         | `accepted-removal` | The debug-style route returns raw `sb-*` auth cookie values plus the full Supabase session payload. No in-repo caller references `/api/auth/me/session`, and the TanStack/Rust cutover must not preserve raw session export behavior.                    |
| `apps/web/src/app/api/workspaces/[wsId]/categories/route.ts`            | `accepted-removal` | The file is zero bytes and exports no HTTP methods, so there is no runtime behavior to port. The override keeps the artifact visible and terminal instead of silently dropping it from the inventory.                                                    |
| `apps/web/src/app/api/v1/workspaces/[wsId]/encryption/migrate/route.ts` | `accepted-removal` | The legacy route performs admin calendar-event encryption status reads and E2EE data writes. Rust owns a terminal `410 MIGRATION_DISABLED` response with the original `GET, POST` allow list so cutover does not preserve broad migration writes.        |
| `apps/web/src/app/api/v1/workspaces/[wsId]/storage/migrate/route.ts`    | `accepted-removal` | The legacy route mutates workspace storage providers after privileged permission checks. Rust owns a terminal `410 MIGRATION_DISABLED` response with the original `POST` allow list; storage moves must use maintained runbooks or local backfills.      |
| `apps/web/src/app/api/v2/workspaces/[wsId]/migrate/[module]/route.ts`   | `accepted-removal` | The legacy route exposes broad API-key migration exports backed by admin Supabase reads, private schemas, and RPCs. Rust owns a terminal `410 MIGRATION_DISABLED` response with the original `GET` allow list instead of preserving this export surface. |

Recently migrated backend runtime candidates:

| Legacy route                                                                                                                                                                               | Decision   | Evidence                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/auth/me`                                                                                                                                                                         | `migrated` | Rust `handle_backend_request` revalidates the Supabase browser cookie or non-app-session Bearer token with Supabase Auth, preserves the raw legacy user payload, no-store headers, and unauthorized response.                                                                                                                                                                                                                                                           |
| `GET /api/auth/mfa/totp/assurance-level`                                                                                                                                                   | `migrated` | Rust `handle_backend_request` revalidates the Supabase browser cookie or non-app-session Bearer token with Supabase Auth, then derives the no-argument Supabase MFA AAL payload from JWT claims and verified factors.                                                                                                                                                                                                                                                   |
| `GET` / `POST` `/api/auth/mfa/totp/factors`                                                                                                                                                | `migrated` | Rust `handle_backend_request` mirrors Auth JS factor listing from the revalidated Supabase user JSON and enrolls TOTP factors through Supabase Auth REST with QR-code normalization.                                                                                                                                                                                                                                                                                    |
| `GET` / `DELETE` `/api/auth/mfa/totp/factors/:factorId`                                                                                                                                    | `migrated` | Rust `handle_backend_request` resolves verified TOTP factor detail from the Auth JS-compatible list and unenrolls factors through Supabase Auth REST with the legacy success wrapper.                                                                                                                                                                                                                                                                                   |
| `GET /api/v1/workspaces/:wsId/posts/permissions`                                                                                                                                           | `migrated` | Rust `handle_backend_request` returns the legacy post approval/force-send flags through `has_workspace_permission` RPC checks, with missing auth or permission failures collapsed to false flags.                                                                                                                                                                                                                                                                       |
| `GET /api/v1/workspaces/:wsId/Mention`                                                                                                                                                     | `migrated` | Rust `handle_backend_request` returns the legacy singular email array after Supabase auth revalidation and exact `MEMBER` workspace membership, with caller-token `workspace_users.email` reads and legacy error bodies.                                                                                                                                                                                                                                                |
| `GET /api/v1/workspaces/:wsId/habits/access`                                                                                                                                               | `migrated` | Rust `handle_backend_request` returns the legacy enabled habits access probe after Supabase auth revalidation, workspace normalization, service-role `MEMBER` validation, and exact `ENABLE_HABITS=true` secret matching.                                                                                                                                                                                                                                               |
| `GET /api/v1/workspaces/:wsId/mobile/module-flags`                                                                                                                                         | `migrated` | Rust `handle_backend_request` returns the legacy sorted hiddenModuleIds payload after Supabase auth revalidation, caller-token workspace membership, and server-owned `workspace_secrets` mobile module flag reads.                                                                                                                                                                                                                                                     |
| `GET /api/v1/workspaces/:wsId/education/access`                                                                                                                                            | `migrated` | Rust `handle_backend_request` returns the legacy enabled education access probe after Supabase auth, getPermissions-compatible `ai_lab` checks, and server-owned `workspace_secrets` feature-flag reads, with workspace/secret/permission lookup failures collapsed to `enabled: false`.                                                                                                                                                                                |
| `GET /api/v1/workspaces/:wsId/finance/budgets/status`                                                                                                                                      | `migrated` | Rust `handle_backend_request` accepts finance/platform app-session and CLI credentials before Supabase fallback, normalizes the workspace, checks `manage_finance`, calls `get_budget_status` with service-role auth, and returns the raw legacy payload/error bodies.                                                                                                                                                                                                  |
| `GET /api/workspaces/:wsId/finance/charts/balance`                                                                                                                                         | `migrated` | Rust `handle_backend_request` accepts finance app-session, CLI, or Supabase credentials, normalizes the workspace, checks `view_finance_stats`, calls `get_wallet_balance_at_date`, and returns the legacy balance/date payload.                                                                                                                                                                                                                                        |
| `GET /api/v1/workspaces/:wsId/finance/debts/summary`                                                                                                                                       | `migrated` | Rust `handle_backend_request` accepts finance app-session, CLI, or Supabase credentials, normalizes the workspace, checks `manage_finance`, calls private `get_debt_loan_summary` with `_actor_id`, and returns the first row or legacy zero summary.                                                                                                                                                                                                                   |
| `GET /api/v1/workspaces/:wsId/finance/filter-users`                                                                                                                                        | `migrated` | Rust `handle_backend_request` accepts finance app-session, CLI, or Supabase credentials, normalizes the workspace, checks `view_transactions`, returns legacy users filter rows, and preserves caller-token workspace user reads for normal sessions.                                                                                                                                                                                                                   |
| `GET /api/v1/workspaces/:wsId/finance/invoices/subscription/context`                                                                                                                       | `migrated` | Rust `handle_backend_request` accepts finance app-session, CLI, or Supabase credentials, normalizes the workspace, checks `create_invoices`, validates requested student groups, and returns the legacy attendance plus latest paid invoice context.                                                                                                                                                                                                                    |
| `GET /api/v1/workspaces/:wsId/finance/recurring-transactions/upcoming`                                                                                                                     | `migrated` | Rust `handle_backend_request` accepts finance app-session, CLI, or Supabase credentials, normalizes the workspace, checks `view_transactions`, preserves `daysAhead` parseInt behavior, and returns the legacy upcomingTransactions envelope.                                                                                                                                                                                                                           |
| `GET /api/v1/workspaces/:wsId/settings/permissions`                                                                                                                                        | `migrated` | Rust `handle_backend_request` mirrors the legacy `getPermissions` result for settings permission flags after Supabase auth revalidation and workspace membership/default/role permission resolution.                                                                                                                                                                                                                                                                    |
| `GET /api/v1/workspaces/:wsId/settings/permissions/check`                                                                                                                                  | `migrated` | Rust `handle_backend_request` mirrors the legacy `getPermissions(...).containsPermission(...)` result after Supabase auth revalidation and workspace membership/default/role permission resolution.                                                                                                                                                                                                                                                                     |
| `GET` / `PUT` `/api/v1/infrastructure/mobile-versions`                                                                                                                                     | `migrated` | Rust `handle_backend_request` revalidates the browser cookie or non-app-session Bearer token, requires root `manage_workspace_roles`, returns the legacy mobile policy snapshot, and upserts normalized mobile policy writes through the server-owned Supabase REST adapter.                                                                                                                                                                                            |
| `GET` / `POST` `/api/v1/infrastructure/timezones` and `PUT` / `DELETE` `/api/v1/infrastructure/timezones/:timezoneId`                                                                      | `migrated` | Rust `handle_backend_request` revalidates the browser cookie or non-app-session Bearer token, requires root `manage_workspace_roles`, reads and writes `private.timezones` with private-schema headers, normalizes legacy create/update payloads, omits missing/null create IDs for database UUID defaults, and preserves legacy success/error bodies.                                                                                                                  |
| `GET /api/v1/infrastructure/user-status-changes`                                                                                                                                           | `migrated` | Rust `handle_backend_request` forwards the caller's Supabase token to PostgREST for `workspace_user_status_changes`, preserving RLS, required `ws_id`, parseInt-style range headers, exact count, and the legacy data/count body.                                                                                                                                                                                                                                       |
| `GET /api/v1/infrastructure/users`                                                                                                                                                         | `migrated` | Rust `handle_backend_request` forwards the caller's Supabase token to PostgREST for `workspace_users`, preserving RLS, required `ws_id`, parseInt-style range headers, exact count, and the legacy data/count body.                                                                                                                                                                                                                                                     |
| `GET /api/v1/infrastructure/classes`, `/product-categories`, and `/score-names`                                                                                                            | `migrated` | Rust `handle_backend_request` uses the shared caller-token paginated export helper for `workspace_user_groups`, `product_categories`, and `user_group_metrics`, preserving RLS, exact count, and the legacy data/count bodies.                                                                                                                                                                                                                                          |
| `GET /api/v1/infrastructure/lessons` and `/packages`                                                                                                                                       | `migrated` | Rust `handle_backend_request` preserves the no-auth private-schema lesson export and revalidates package callers before requiring `view_inventory`, while keeping exact-count pagination and the legacy data/count bodies.                                                                                                                                                                                                                                              |
| `GET /api/v1/infrastructure/product-prices`, `/product-units`, and `/warehouses`                                                                                                           | `migrated` | Rust `handle_backend_request` accepts inventory app-session credentials or normal Supabase browser/Bearer credentials, requires inventory catalog/setup read permissions, and reads private inventory setup rows through the service-role Supabase REST adapter with exact-count pagination. Product prices scope through the `workspace_products` inner workspace filter.                                                                                              |
| `GET` / `POST` `/api/v1/infrastructure/ai/whitelist/domains` and `/emails`                                                                                                                 | `migrated` | Rust `handle_backend_request` revalidates the Supabase browser session or non-app-session Bearer token, requires a `@tuturuuu.com` operator email, reads and inserts private whitelist rows through the service-role private-schema REST adapter, and preserves `page`/`pageSize`/`q`, `created_at.desc` ordering, exact-count pagination, Zod-style create validation messages, `enabled` defaults, 201 create wrappers, 403 denial bodies, and plain-text 500 bodies. |
| `PUT` / `DELETE` `/api/v1/infrastructure/ai/whitelist/:email` and `/domain/:domain`                                                                                                        | `migrated` | Rust `handle_backend_request` revalidates the same operator boundary as the list routes, decodes the path segment, patches/deletes matching private whitelist rows through the service-role private-schema REST adapter, applies legacy `Boolean(enabled)` update truthiness, and preserves the legacy success/error bodies.                                                                                                                                            |
| `GET /api/v1/infrastructure/post-email-queue`                                                                                                                                              | `migrated` | Rust `handle_backend_request` revalidates the Supabase browser session or non-app-session Bearer token, requires root workspace membership, reads `post_email_queue` through the service-role Supabase REST adapter, preserves the legacy summary/workspace/recent-batch aggregation payload, and keeps workspace/batch breakdown failures non-fatal.                                                                                                                   |
| `GET /api/v1/infrastructure/bills`, `/roles`, and `/transaction-categories`                                                                                                                | `migrated` | Rust `handle_backend_request` uses the shared caller-token paginated export helper for `finance_invoices`, `workspace_user_groups`, and `transaction_categories`, preserving RLS, exact count, and the legacy data/count bodies.                                                                                                                                                                                                                                        |
| `GET /api/v1/infrastructure/wallet-transactions`                                                                                                                                           | `migrated` | Rust `handle_backend_request` forwards the caller's Supabase token to `get_wallet_transactions_with_permissions`, preserving the legacy RPC payload, raw rows, and first-row `total_count` envelope.                                                                                                                                                                                                                                                                    |
| `GET /api/v1/infrastructure/abuse-intelligence`                                                                                                                                            | `migrated` | Rust `handle_backend_request` validates the Supabase browser session or Bearer token, requires root `view_infrastructure`, reads caller-scoped abuse reputation subjects, activity signals, and challenges, reads active overrides with service-role auth, and returns the legacy summary plus `topRiskySubjects` payload while leaving POST legacy-owned.                                                                                                              |
| `GET /api/v1/infrastructure/abuse-events`                                                                                                                                                  | `migrated` | Rust `handle_backend_request` validates the Supabase browser session or Bearer token, checks root workspace membership with the caller token, reads `abuse_events` with legacy filters and page/pageSize pagination, and returns the legacy pagination envelope.                                                                                                                                                                                                        |
| `GET /api/v1/infrastructure/blocked-ips`                                                                                                                                                   | `migrated` | Rust `handle_backend_request` validates the Supabase browser session or Bearer token, checks root workspace membership with the caller token, reads `blocked_ips` with legacy filters and page/pageSize pagination, and leaves POST/DELETE legacy-owned.                                                                                                                                                                                                                |
| `GET /api/v1/infrastructure/suspensions`                                                                                                                                                   | `migrated` | Rust `handle_backend_request` validates the Supabase browser session or Bearer token, requires root `manage_workspace_roles`, reads active `user_suspensions` rows through the service-role Supabase REST adapter, and leaves POST/detail DELETE legacy-owned.                                                                                                                                                                                                          |
| `GET` / `POST` `/api/v1/infrastructure/email-blacklist` and `GET` / `PUT` / `DELETE` `/api/v1/infrastructure/email-blacklist/:entryId`                                                     | `migrated` | Rust `handle_backend_request` validates the Supabase browser session or Bearer token, checks root workspace membership with the caller token, returns the legacy ordered collection/detail rows, writes with caller-token Supabase REST, preserves POST/PUT Zod-style validation bodies, maps duplicate creates to `409`, and preserves detail update/delete prefetch/not-found behavior.                                                                               |
| `GET /api/v1/infrastructure/bill-coupons`, `/bill-packages`, `/class-attendance`, `/class-members`, `/class-packages`, `/class-scores`, `/package-stock-changes`, and `/student-feedbacks` | `migrated` | Rust `handle_backend_request` uses the shared caller-token paginated export helper with route-specific embedded select strings and related-table workspace filters while preserving exact count and the legacy data/count bodies.                                                                                                                                                                                                                                       |
| `GET /api/v1/infrastructure/user-monthly-reports` and `/user-monthly-report-logs`                                                                                                          | `migrated` | Rust `handle_backend_request` requires `manage_external_migrations`, resolves workspace aliases through the shared permission helper, and reads the private monthly report views through private-schema Supabase REST with exact-count pagination.                                                                                                                                                                                                                      |
| `GET /api/v1/workspaces/:wsId/crawlers/status`                                                                                                                                             | `migrated` | Rust `handle_backend_request` preserves the legacy exact-URL crawler status lookup, raw Supabase row payloads, missing-URL validation, and `crawledUrl: null` fallback when no row exists.                                                                                                                                                                                                                                                                              |
| `GET /api/v1/workspaces/:wsId/course-modules` and `GET /api/v1/workspaces/:wsId/quiz-sets/:setId/linked-modules`                                                                           | `migrated` | Rust `handle_backend_request` resolves education workspace access, requires `ENABLE_EDUCATION`, reads service-role course-module rows with exact-count pagination, and verifies linked quiz sets belong to the resolved workspace before listing linked modules.                                                                                                                                                                                                        |
| `PATCH /api/v1/user/profile`                                                                                                                                                               | `migrated` | Rust `handle_backend_request` validates browser Supabase auth, validates legacy profile fields, and updates only the authenticated user's `users` row through the server-owned Supabase REST adapter.                                                                                                                                                                                                                                                                   |
| `GET` / `PATCH` `/api/v1/users/me/default-workspace`                                                                                                                                       | `migrated` | Rust `handle_backend_request` resolves the authenticated user's default workspace with the legacy personal-workspace/null fallback and updates `default_workspace_id` after caller-token membership validation.                                                                                                                                                                                                                                                         |
| `GET` / `PATCH` `/api/v1/users/calendar-settings`                                                                                                                                          | `migrated` | Rust `handle_backend_request` accepts calendar app-session tokens or revalidated browser Supabase sessions, reads and updates the authenticated user's calendar settings in `user_private_details`, defaults missing values to `auto`, and preserves legacy patch validation/cache behavior.                                                                                                                                                                            |
| `GET /api/v1/users/me/identities`                                                                                                                                                          | `migrated` | Rust `handle_backend_request` revalidates browser Supabase auth, reads the raw Supabase Auth user JSON, returns the legacy linked identities list plus `canUnlink`, and preserves the private cache directive.                                                                                                                                                                                                                                                          |
| `PATCH /api/v1/users/me/full-name`                                                                                                                                                         | `migrated` | Rust `handle_backend_request` validates browser Supabase auth, validates the required trimmed `full_name`, and upserts `user_private_details` for the authenticated user with the caller token.                                                                                                                                                                                                                                                                         |
| `GET /api/cron/discord/daily-report`                                                                                                                                                       | `migrated` | Rust `handle_backend_request` proxies to `DISCORD_APP_DEPLOYMENT_URL/daily-report` with cron bearer auth, upstream status/body passthrough, invalid-JSON fallback, OpenAPI coverage, and native/Worker outbound support.                                                                                                                                                                                                                                                |
| `GET /api/cron/discord/wol/daily/remind`                                                                                                                                                   | `migrated` | Rust `handle_backend_request` reuses the same proxy contract for `DISCORD_APP_DEPLOYMENT_URL/wol-reminder` with route tests and Cloudflare Worker config requirements for the cron secret and Discord app deployment URL.                                                                                                                                                                                                                                               |

Frontend pages now terminal:

| Legacy route                                                                                                   | Status     | Evidence                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| -------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/:locale/add-account`                                                                                         | `migrated` | Dynamic no-store TanStack Start route `/$locale/add-account` is registered in `routeTree.gen.ts`, preserves the legacy account-switcher add-account handoff, carries `returnUrl` through TanStack Router search validation, renders localized loading/success/error states, and persists the current session through a TanStack Query mutation backed by `@tuturuuu/internal-api` auth helpers instead of Next navigation or raw protected API calls.                                                                                                                                                                                                                                                                                                                                    |
| `/:locale/:wsId/habits`                                                                                        | `migrated` | TanStack Start route `/$locale/$wsId/habits` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, checks the Rust-owned `/api/v1/workspaces/:wsId/habits/access` feature probe, and renders the shared `HabitsClientPage`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `/:locale/:wsId/posts`                                                                                         | `migrated` | TanStack Start route `/$locale/$wsId/posts` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves pass-through URL search state for the shared posts client, and uses internal-api facades including the Rust-owned posts permission probe.                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `/:locale/:wsId/crawlers`                                                                                      | `migrated` | TanStack Start route `/$locale/$wsId/crawlers` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves legacy `ai_lab` gating, carries URL page/pageSize/domain/search state through TanStack Router, and renders a read-only crawled URL table plus uncrawled/domain stats through Rust-owned crawler backend facades.                                                                                                                                                                                                                                                                                                                                                                                               |
| `/:locale/:wsId/crawlers/uncrawled`                                                                            | `migrated` | TanStack Start route `/$locale/$wsId/crawlers/uncrawled` is registered in `routeTree.gen.ts`, uses the same authenticated workspace and `ai_lab` gate, carries URL filters through TanStack Router, and renders grouped read-only uncrawled URLs through the Rust-owned crawler backend facades while leaving crawl-trigger mutations out of scope.                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `/:locale/:wsId/pipelines`                                                                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/pipelines` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves legacy `ai_lab` gating, carries URL page/pageSize/domain/search state through TanStack Router, and renders the crawler-backed read-only list through Rust-owned crawler backend facades. Legacy crawler create/update actions remain separately tracked.                                                                                                                                                                                                                                                                                                                                     |
| `/:locale/:wsId/queues`                                                                                        | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/queues` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves legacy `ai_lab` gating, carries URL page/pageSize/domain/search state through TanStack Router, and renders the crawler-backed read-only list through Rust-owned crawler backend facades. Legacy crawler create/update actions remain separately tracked.                                                                                                                                                                                                                                                                                                                                        |
| `/:locale/:wsId/cron` layout                                                                                   | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/cron` preserves the legacy cron route-specific layout gate by requiring current-user auth, resolving the workspace, enforcing `ai_lab`, and rendering exact-match Overview, Cron jobs, and Executions tabs. Child cron pages stay separately tracked until their tables and mutations move behind internal-api or Rust facades.                                                                                                                                                                                                                                                                                                                                                                                                    |
| `/:locale/:wsId/cron/jobs`                                                                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/cron/jobs` is registered in `routeTree.gen.ts`, duplicates fail-closed current-user/workspace/`ai_lab` gates before loading protected data, carries `q`, `page`, and `pageSize` through TanStack Router search state, and renders the cron job list through a typed internal-api facade instead of direct Supabase reads or raw browser `/api` fetches. Create, edit, delete, next-run calculation, and job detail navigation remain separately tracked until dataset readers, mutation flows, and `/:locale/:wsId/cron/jobs/:jobId` move behind internal-api or Rust facades.                                                                                                                                                     |
| `/:locale/:wsId/documents`                                                                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/documents` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy `manage_documents` permission gate, and renders the workspace document list/create/delete flow through TanStack Query plus the typed documents internal-api facade. Document editor mutations and workspace document APIs remain separately tracked.                                                                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/documents/:documentId`                                                                         | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/documents/$documentId` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy `manage_documents` permission gate, loads the protected document row through the typed documents internal-api facade with forwarded request auth, and renders document metadata plus a read-only rich-text preview. Document edit/share/delete/autosave behavior and workspace document APIs remain separately tracked.                                                                                                                                                                                                                                               |
| `/:locale/:wsId/infrastructure/abuse-events`                                                                   | `migrated` | TanStack Start route `/$locale/$wsId/infrastructure/abuse-events` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves `view_infrastructure` not-found gating, carries URL search filters through TanStack Router, and loads rows through the Rust-owned abuse-events backend facade.                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/infrastructure/abuse-intelligence`                                                             | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/abuse-intelligence` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary, requires root `view_infrastructure`, and renders shared TanStack Query/internal-api-backed reputation subject, signal, and trust override controls. Abuse Intelligence mutation APIs remain separately tracked.                                                                                                                                                                                                                                                                                                         |
| `/:locale/:wsId/infrastructure/app-coordination`                                                               | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/app-coordination` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary, accepts root `manage_workspace_secrets` or `manage_workspace_roles`, and renders shared TanStack Query/internal-api-backed app-session policy controls. App Coordination APIs remain separately tracked.                                                                                                                                                                                                                                                                                                                  |
| `/:locale/:wsId/infrastructure/blocked-ips`                                                                    | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/blocked-ips` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves root and workspace `view_infrastructure` not-found gating, carries URL search/status/pagination filters through TanStack Router, and renders localized block/unblock controls through typed internal-api facades instead of direct Supabase reads or raw client `/api` fetches. Blocked IP APIs remain separately tracked.                                                                                                                                                                                                                                                  |
| `/:locale/:wsId/infrastructure/realtime`                                                                       | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/realtime` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace alias, preserves root and workspace `view_infrastructure` not-found gating, and renders the realtime analytics TanStack Query surface through createServerFn wrappers plus typed internal-api facades instead of raw protected `/api` fetches. Realtime analytics API artifacts remain separately tracked backend migration work.                                                                                                                                                                                                                                                         |
| `/:locale/:wsId/infrastructure/external-apps`                                                                  | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/external-apps` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary, accepts root `manage_workspace_secrets` or `manage_workspace_roles`, and renders shared TanStack Query/internal-api-backed external app registration and secret rotation controls. External Apps APIs remain separately tracked.                                                                                                                                                                                                                                                                                             |
| `/:locale/:wsId/infrastructure/github-bot`                                                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/github-bot` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary, requires root `manage_workspace_secrets`, loads the initial GitHub Bot state through forwarded internal-api auth, and renders localized TanStack Query/internal-api-backed configuration, validation, watcher client, and audit controls. GitHub Bot APIs remain separately tracked.                                                                                                                                                                                                                                            |
| `/:locale/:wsId/infrastructure/ai/whitelist/{domains,emails}`                                                  | `migrated` | TanStack Start routes `/$locale/$wsId/infrastructure/ai/whitelist/domains` and `/emails` are registered in `routeTree.gen.ts`, gate anonymous users through `requireCurrentUser`, preserve the `@tuturuuu.com` operator not-found boundary plus root `view_infrastructure` gating, carry URL pagination/search through TanStack Router, and load/mutate rows through the Rust-owned AI whitelist internal-api facade.                                                                                                                                                                                                                                                                                                                                                                    |
| `/:locale/:wsId/infrastructure/mobile-versions`                                                                | `migrated` | TanStack Start route `/$locale/$wsId/infrastructure/mobile-versions` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, preserves the legacy root-workspace redirect boundary, requires root `manage_workspace_roles`, loads policies through the Rust-owned mobile-versions internal-api facade, and saves updates through TanStack Query mutations.                                                                                                                                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/infrastructure/mobile-deployment`                                                              | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/mobile-deployment` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary, requires root `manage_mobile_deployment_vault`, loads the initial vault state through forwarded internal-api auth, and renders localized secret, file, activation, rollback, and CI token controls through TanStack Query/internal-api facades. Mobile Deployment APIs remain separately tracked.                                                                                                                                                                                                                        |
| `/:locale/:wsId/infrastructure/monitoring/stress-tests`                                                        | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/monitoring/stress-tests` is registered under the TanStack monitoring layout in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary and root `view_infrastructure` not-found gate, renders the localized monitoring hero/section navigation, and uses TanStack Query/internal-api facades for stress-test snapshots, queue, abort, run detail polling, metrics, and history. Stress-test APIs remain separately tracked.                                                                                                                                                                                           |
| `/:locale/:wsId/infrastructure/monitoring/cron`                                                                | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/monitoring/cron` is registered under the TanStack monitoring layout in `routeTree.gen.ts`, relies on the parent current-user, root-workspace redirect, and root `view_infrastructure` gates, and uses TanStack Query/internal-api facades for cron snapshots, execution archives, manual run queueing, control toggles, and console-log detail. Cron APIs remain separately tracked.                                                                                                                                                                                                                                                                                                                                |
| `/:locale/:wsId/infrastructure/monitoring/requests`                                                            | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/monitoring/requests` is registered under the TanStack monitoring layout in `routeTree.gen.ts`, relies on the parent current-user, root-workspace redirect, and root `view_infrastructure` gates, and uses TanStack Query/internal-api facades for retained request archives, status/route/render/traffic filters, pagination, deployment context, and request inspection. Request archive APIs remain separately tracked.                                                                                                                                                                                                                                                                                           |
| `/:locale/:wsId/infrastructure/monitoring/watcher-logs`                                                        | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/monitoring/watcher-logs` is registered under the TanStack monitoring layout in `routeTree.gen.ts`, relies on the parent current-user, root-workspace redirect, and root `view_infrastructure` gates, and uses TanStack Query/internal-api facades for watcher snapshots, deployment scope/level/rollout status filters, pagination, commit context, and log detail inspection. Watcher-log APIs remain separately tracked.                                                                                                                                                                                                                                                                                          |
| `/:locale/:wsId/infrastructure/monitoring/rollouts`                                                            | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/monitoring/rollouts` is registered under the TanStack monitoring layout in `routeTree.gen.ts`, relies on the parent current-user, root-workspace redirect, and root `view_infrastructure` gates, and uses TanStack Query/internal-api facades for rollout summaries, deployment stage panels, standby sync controls, deployment pin controls, watcher event streams, and deployment history. Rollout mutation APIs remain separately tracked.                                                                                                                                                                                                                                                                       |
| `/:locale/:wsId/infrastructure/monitoring{,/analytics,/deployments,/logs,/observability,/projects,/resources}` | `migrated` | Dynamic no-store TanStack Start routes are registered under the TanStack monitoring layout in `routeTree.gen.ts`, rely on the parent current-user, root-workspace redirect, and root `view_infrastructure` gates, and render the observability overview, analytics, deployment history, grouped logs, health signals, project controls, and resource inventory through TanStack Query/internal-api facades. Project deletion and deeper observability API ownership remain separately tracked follow-ups.                                                                                                                                                                                                                                                                                |
| `/:locale/:wsId/infrastructure/timezones`                                                                      | `migrated` | TanStack Start route `/$locale/$wsId/infrastructure/timezones` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, preserves the legacy root-workspace redirect boundary, requires root `manage_workspace_roles`, overlays Rust-owned persisted timezone rows onto the bundled timezone catalog, and performs create/update/delete sync mutations through the backend timezones facade.                                                                                                                                                                                                                                                                                                                                                             |
| `/:locale/:wsId/infrastructure/holidays`                                                                       | `migrated` | TanStack Start route `/$locale/$wsId/infrastructure/holidays` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, preserves the legacy root-workspace redirect boundary, requires root `manage_workspace_roles`, carries the year filter through TanStack Router search state, and performs list/create/update/delete/bulk-import work through the Rust-owned holidays backend facade.                                                                                                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/infrastructure/email-blacklist`                                                                | `migrated` | TanStack Start route `/$locale/$wsId/infrastructure/email-blacklist` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves `view_infrastructure` not-found gating, carries URL search/type/pagination filters through TanStack Router, and loads/mutates rows through the Rust-owned email blacklist backend facade.                                                                                                                                                                                                                                                                                                                                                                                                |
| `/:locale/:wsId/infrastructure/email-templates`                                                                | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/email-templates` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves root and workspace `view_infrastructure` not-found gating, and renders the localized React Email template selector, property editor, server-function preview renderer, dark-mode simulation, and iframe HTML preview without raw `/api` fetches or Supabase reads.                                                                                                                                                                                                                                                                                                      |
| `/:locale/:wsId/infrastructure/rate-limits`                                                                    | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/rate-limits` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy root-workspace redirect boundary, requires root `view_infrastructure`, forwards `manage_workspace_roles` as can-manage state, and renders the shared TanStack Query/internal-api-backed protection toggles, rate-limit rule, live-usage, and workspace-secret controls. Rate-limit APIs remain separately tracked.                                                                                                                                                                                                                                               |
| `/:locale/:wsId/infrastructure/post-email-queue`                                                               | `migrated` | TanStack Start route `/$locale/$wsId/infrastructure/post-email-queue` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves `view_infrastructure` not-found gating, and renders the read-only queue summary, workspace breakdown, and recent batches through the Rust-owned post-email-queue backend facade while leaving the legacy cron trigger out of scope.                                                                                                                                                                                                                                                                                                                                                     |
| `/:locale/:wsId/education`                                                                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, and renders the legacy education overview shell with forwarded-auth internal-api counts for courses, flashcards, and quizzes. Education list APIs remain separately tracked.                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `/:locale/:wsId/education/library/flashcards`                                                                  | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/library/flashcards` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize` search state through TanStack Router, and renders the legacy flashcard library table through forwarded internal-api auth plus shared TanStack Query-backed create/update/delete components. Flashcard API ownership remains separately tracked.                                                                                                                                                                                                                                                                                                       |
| `/:locale/:wsId/education/library/quizzes`                                                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/library/quizzes` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize` search state through TanStack Router with the legacy 10-row default, and renders the legacy quiz library table through forwarded internal-api auth plus shared TanStack Query-backed create/update/delete components and AI explanation generation. Quiz API ownership remains separately tracked.                                                                                                                                                                                                                                                       |
| `/:locale/:wsId/education/library/quiz-sets`                                                                   | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/library/quiz-sets` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize` search state through TanStack Router with the legacy 10-row default, and renders the legacy quiz-set library table through forwarded internal-api auth plus linked course/module label hydration and shared TanStack Query-backed create/update/delete components. Quiz-set and linked-module API ownership remains separately tracked.                                                                                                                                                                                                                |
| `/:locale/:wsId/education/attempts`                                                                            | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/attempts` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy `view_user_groups_reports` not-found gate, carries filter/sort/page/pageSize search state through TanStack Router, and renders the legacy attempts review table through forwarded internal-api auth with learner and quiz-set metadata. Attempts APIs remain separately tracked.                                                                                                                                                                                                                                                                                         |
| `/:locale/:wsId/education/attempts/:attemptId`                                                                 | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/attempts/$attemptId` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the `view_user_groups_reports` not-found gate used by the list/API, and renders the legacy attempt detail header, learner card, KPI strip, and per-question answer correctness cards through forwarded internal-api auth. Attempts APIs remain separately tracked.                                                                                                                                                                                                                                                                                                       |
| `/:locale/:wsId/education/courses`                                                                             | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/courses` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize`/`view` search state through TanStack Router, and renders the legacy course card/table page through forwarded internal-api auth plus shared CourseCardView, CoursePagination, CustomDataTable, and internal-api-backed create/edit/delete actions. Course API ownership and course builder remain separately tracked.                                                                                                                                                                                                                                             |
| `/:locale/:wsId/education/quiz-sets/:setId`                                                                    | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/quiz-sets/$setId` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize` search state through TanStack Router with the legacy 10-row default, and renders the legacy quiz-set quiz table through forwarded internal-api auth plus shared TanStack Query-backed create/update/delete components and AI explanation generation. The exact `/education/quiz-sets` redirect is an index route so detail children are reachable; the quiz-set detail layout and quiz APIs remain separately tracked.                                                                                                                                  |
| `/:locale/:wsId/ai-chat` layout                                                                                | `migrated` | Dynamic no-store TanStack Start parent route `/$locale/$wsId/ai-chat` wraps migrated AI chat child routes with fail-closed current-user auth, workspace resolution, the legacy `ai_chat` permission redirect, and localized New Chat, Chatbots, and My Chatbots tabs. The exact `/ai-chat` leaf deliberately remains not-found in TanStack until the legacy chat page is migrated; parent dashboard/session ownership also remains separately tracked.                                                                                                                                                                                                                                                                                                                                   |
| `/:locale/:wsId/ai-chat/my-chatbots`                                                                           | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/ai-chat/my-chatbots` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy `ai_chat` permission gate, carries `q`/`page`/`pageSize` search state through TanStack Router, and renders the legacy My Chatbots table through forwarded internal-api auth plus internal-api-backed row deletion. Group-tag API ownership remains separately tracked.                                                                                                                                                                                                                                                                                                  |
| `/:locale/:wsId/users/approvals`                                                                               | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/approvals` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the personal-workspace notice and approve reports/posts not-found gating, carries `status`/`page`/`limit`/`groupId`/`userId`/`creatorId` filter state through TanStack Router, and renders the shared approvals tabs through TanStack Query-backed reads and internal-api-backed approve/reject/unapprove mutations. Approval APIs remain separately tracked.                                                                                                                                                                                                                          |
| `/:locale/:wsId/users/group-tags`                                                                              | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/group-tags` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize` search state through TanStack Router, and renders the legacy group-tag table through forwarded internal-api auth plus shared create/update/delete components and locale-prefixed detail hrefs. Group-tag API ownership remains separately tracked.                                                                                                                                                                                                                                                                                                                |
| `/:locale/:wsId/users/group-tags/:tagId`                                                                       | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/group-tags/$tagId` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries `q`/`page`/`pageSize` search state through TanStack Router, and renders the legacy linked user-group table through forwarded internal-api auth plus TanStack Query-backed linked-group add/remove components. Group-tag API ownership remains separately tracked.                                                                                                                                                                                                                                                                                                                |
| `/:locale/:wsId/users/topic-announcements/announcements`                                                       | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/topic-announcements/announcements` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves personal-workspace not-found parity, enforces `ENABLE_TOPIC_ANNOUNCEMENTS` and `manage_users`, carries `status`/`q`/`page` search state through TanStack Router, and renders the legacy announcements composer/table with send-permission-aware create/send/schedule flows, attachment upload, live email preview, save-as-template, and typed topic-announcement internal-api contracts.                                                                                                                                                                      |
| `/:locale/:wsId/users/topic-announcements/templates`                                                           | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/topic-announcements/templates` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves personal-workspace not-found parity, enforces `ENABLE_TOPIC_ANNOUNCEMENTS` and `manage_users`, and renders the legacy templates CRUD page through TanStack Query plus typed topic-announcement and user-group internal-api facades. The exact parent redirect now only fires on `/topic-announcements`, so migrated child tabs can render.                                                                                                                                                                                                                         |
| `/:locale/:wsId/users/topic-announcements/contacts`                                                            | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/topic-announcements/contacts` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves personal-workspace not-found parity, enforces `ENABLE_TOPIC_ANNOUNCEMENTS` and `manage_users`, and renders the legacy contacts table, create dialog, linked workspace-user selector, delete confirmation, and verification request action through TanStack Query plus typed topic-announcement and workspace-user internal-api facades. Verification controls stay hidden unless the caller has `send_user_group_post_emails`.                                                                                                                                      |
| `/:locale/:wsId/users/topic-announcements/delivery`                                                            | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/topic-announcements/delivery` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves personal-workspace not-found parity, enforces `ENABLE_TOPIC_ANNOUNCEMENTS` and `manage_users`, and renders the legacy read-only delivery history with forwarded-auth `listTopicAnnouncements({ status: "sent" })` loader hydration, calendar timezone normalization, TanStack Query refreshes, sent-only defensive filtering, recipient summary chips, sent-at formatting, and empty-state compose handoff. Delivery does not require `send_user_group_post_emails`.                                                                                                |
| `/:locale/:wsId/users/topic-announcements/import`                                                              | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/topic-announcements/import` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves personal-workspace not-found parity, enforces `ENABLE_TOPIC_ANNOUNCEMENTS` and `manage_users`, derives `send_user_group_post_emails` for create-and-send availability, and renders the legacy bulk import flow with client-only XLSX template download/first-sheet parsing, custom CSV/header alias parsing, editable spreadsheet grid, row validation/result summaries, and TanStack Query mutations through `importTopicAnnouncements` plus `sendTopicAnnouncementsBulk`. Rust backend ownership of the import and send-bulk API routes remains separately tracked. |
| `/:locale/:wsId/settings/reports`                                                                              | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/settings/reports` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves `manage_user_report_templates` permission gating, carries `q` search state through TanStack Router, and renders the legacy reports and lead-generation template tables plus previews through TanStack Query server functions and the shared workspace-config internal-api facade.                                                                                                                                                                                                                                                                                                     |
| `/:locale/:wsId/users/groups/calendar`                                                                         | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/groups/calendar` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves manage-users/view-user-groups not-found gating, forwards update-user-groups schedule permission state, and renders the shared user-group session calendar through internal-api-backed session reads and mutations. User-group session APIs remain separately tracked.                                                                                                                                                                                                                                                                                                            |
| `/:locale/:wsId/users/groups/:groupId/attendance`                                                              | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/groups/$groupId/attendance` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves `check_user_attendance` not-found gating and `update_user_attendance` save gating, hydrates group/session/member/config/attendance data through forwarded internal-api auth, and renders the attendance calendar/session/member cards with TanStack Query-backed reads and saves. User-group attendance/member/config/session APIs remain separately tracked for the backend Rust wave.                                                                                                                                                                               |
| `/:locale/:wsId/users/groups/:groupId/requests`                                                                | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/groups/$groupId/requests` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves approve reports/posts not-found gating, and renders the shared group requests tabs through TanStack Query and internal-api-backed approval mutations. Parent group detail page and approval APIs remain separately tracked.                                                                                                                                                                                                                                                                                                                                             |
| `/:locale/:wsId/users/groups/:groupId/schedule`                                                                | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/users/groups/$groupId/schedule` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, loads the target group through forwarded internal-api auth, preserves update-user-groups schedule permission state, and renders the shared end-date dialog and user-group session calendar. Parent group detail page and schedule APIs remain separately tracked.                                                                                                                                                                                                                                                                                                                 |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/content`                                         | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/courses/$courseId/modules/$moduleId/content` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, loads the requested module through forwarded internal-api auth, and renders the legacy rich-text module content editor with TanStack Query/internal-api-backed debounced saves. Parent module layout and module API ownership remain separately tracked.                                                                                                                                                                                                                                                                                                   |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/youtube-links`                                   | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/courses/$courseId/modules/$moduleId/youtube-links` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, loads the requested module through forwarded internal-api auth, and renders the legacy Youtube Links management page with shared form/delete/embed UI backed by strict internal-api mutations. Parent module layout and module API ownership remain separately tracked.                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/quiz-sets`                                       | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/courses/$courseId/modules/$moduleId/quiz-sets` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries list search state through TanStack Router, and renders the legacy module quiz-set table through forwarded internal-api auth plus shared TanStack Query-backed create/update/delete components. Course-module quiz-set API ownership remains separately tracked.                                                                                                                                                                                                                                                                                  |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/quizzes`                                         | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/courses/$courseId/modules/$moduleId/quizzes` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the legacy `update_user_groups` not-found gate before quiz reads, carries search state through TanStack Router, and renders the shared quiz table through forwarded internal-api auth. Quiz API and AI quiz-generation backend ownership remain separately tracked.                                                                                                                                                                                                                                                                              |
| `/:locale/:wsId/education/courses/:courseId/modules/:moduleId/quizzes/new`                                     | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/education/courses/$courseId/modules/$moduleId/quizzes/new` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, renders the legacy manual quiz creation shell, and submits through the shared TanStack Query/internal-api quiz form before returning to the locale-prefixed module quizzes route. Quiz API ownership and the module quiz list page remain separately tracked.                                                                                                                                                                                                                                                                                          |
| `/:locale/logout`                                                                                              | `migrated` | Dynamic TanStack Start route `/$locale/logout` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, renders the legacy localized confirmation card with `from` copy, and logs out through the typed internal-api browser-session facade without raw protected app API or Supabase access in TanStack source. The underlying `POST /api/auth/logout` route remains legacy-owned until the auth backend wave.                                                                                                                                                                                                                                                                                                                                          |
| `/:locale/:wsId/infrastructure/ai-agents`                                                                      | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/infrastructure/ai-agents` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, preserves the root-workspace and `manage_workspace_secrets` redirect gates, and renders the legacy AI Agents controls through forwarded internal-api auth plus shared TanStack Query-backed agent, channel, identity, secret, and external-thread actions. AI Agents APIs remain separately tracked for Rust backend ownership.                                                                                                                                                                                                                                                         |
| `/:locale/:wsId/notifications`                                                                                 | `migrated` | Dynamic no-store TanStack Start route `/$locale/$wsId/notifications` is registered in `routeTree.gen.ts`, gates anonymous users through `requireCurrentUser`, resolves the workspace, carries tab/type/scope/priority/page/pageSize search state through TanStack Router, and renders the legacy read-only notifications inbox through forwarded internal-api auth. Mark read/unread, mark all read, delete, invite actions, metadata updates, realtime subscription behavior, and entity action links remain separately tracked follow-ups.                                                                                                                                                                                                                                             |

Frontend migration candidates blocked on auth/data ownership:

| Legacy route                                                                     | Blocker                                                                                                                                                                                                                                                                                                       | Required design                                                                                                                                                                                                                                                                      |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `/:locale/meet` and `/:locale/meet-together`                                     | Public TanStack preview shells are available, but the legacy routes also load authenticated meeting plans and create plans through Next-only Supabase/server-action paths.                                                                                                                                    | Add Rust-owned or TanStack server-function-backed plan list/create APIs, route them through `packages/internal-api`, preserve unauthenticated empty/login-required behavior, and add E2E evidence before adding the `page:/:locale/meet` or `page:/:locale/meet-together` overrides. |
| `/:locale/:wsId/usage`                                                           | The wrapper is small, but the content fans out into many server-side workspace stats backed by Supabase RPCs, admin reads, storage provider helpers, and per-feature permission checks.                                                                                                                       | Create a Rust-owned workspace usage summary endpoint or a small set of typed server functions that return the same permission-masked stats, then render the dashboard through TanStack Query without direct Supabase reads.                                                          |
| `/:locale/:wsId/ai/spark`, `/:locale/:wsId/mira`, and `/:locale/:wsId/assistant` | These look compact at the page file level, but their clients call AI object generation, Mira focus/task/calendar/pet APIs, live voice/audio helpers, or assistant multimodal providers that are still Next/API coupled.                                                                                       | Move each AI surface as a dedicated product lane with typed AI/Mira/assistant facades and focused browser evidence; avoid shell-only migrations that would expose incomplete AI behavior.                                                                                            |
| `/:locale/games/farm`                                                            | The visible game page is client-only, but the legacy layout gates access through Supabase auth and `isValidTuturuuuEmail(user?.email)` before rendering.                                                                                                                                                      | Add a TanStack server gate that validates the session and email domain through server-owned auth helpers, then port the game UI without exposing it publicly.                                                                                                                        |
| `/:locale` app-shell providers                                                   | The root route now centralizes locale validation, legacy root head metadata, `html lang`, theme bootstrapping, Query, and tooltip providers, but full legacy layout parity still includes `next-intl`, `NuqsAdapter`, theme-aware toasts, auth-backed version/DB badges, and service-worker runtime behavior. | Finish the provider/runtime contract in TanStack Start, decide which legacy badges and service-worker behaviors are accepted removals versus ports, then add route-level E2E or screenshot evidence before marking remaining localized layout artifacts terminal.                    |
| `/:locale/login`                                                                 | Login owns OAuth callback forwarding, Supabase session redirects, app-token confirmation, OTP/password/passkey/MFA flows, account switching, Turnstile state, and session hydration.                                                                                                                          | Complete the auth/session contract for TanStack Start and Rust, then port login as a dedicated auth milestone with focused E2E coverage.                                                                                                                                             |

## Frontend Runtime Adapters

TanStack route ports should use the adapter modules under
`apps/tanstack-web/src/lib/platform/` instead of rebuilding Next.js behavior in
each route:

| Adapter         | Owns                                                                                                                           |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `locale.ts`     | `en` / `vi` locale detection, `NEXT_LOCALE`, as-needed prefixes, and `Accept-Language` fallback.                               |
| `head.ts`       | TanStack-compatible metadata, canonical links, alternates, and stylesheet descriptors.                                         |
| `theme.ts`      | The class-based `system` / `light` / `dark` theme boot script used by the root shell.                                          |
| `navigation.ts` | Typed redirect and not-found errors that can be converted to `Response` objects in loaders or server functions.                |
| `session.ts`    | Sanitized auth/session hydration snapshots from request cookies without exposing token values to the browser.                  |
| `query.ts`      | Shared TanStack Query defaults and dehydration behavior for loader-prefetched data.                                            |
| `app-shell.ts`  | Root locale validation, localized document language derivation, and legacy-compatible head descriptors.                        |
| `redirects.ts`  | Legacy-compatible redirect destinations for public, auth, dashboard alias, QR, Mail, CMS, CMS deep-link, and education routes. |

The root TanStack shell already uses the head, locale, theme, and Query
adapters. New route ports should add route-specific metadata through
`createPageHead`, prefetch loader data through the shared QueryClient, and pass
only sanitized session state to client components.

## Data And API Rules

* TanStack loaders and server functions may act as a BFF layer for SSR,
  cookies, headers, and query hydration.
* Product data reads/writes move to Rust-owned endpoints in `apps/backend`.
* Browser/shared UI code calls `packages/internal-api` helpers, not scattered
  raw API paths.
* Protected data stays behind server-owned private/admin access. Do not expose
  private Supabase or protected workspace reads directly to browser code.
* Use TanStack Query for client fetching and mutation. Do not fetch data in
  `useEffect`.
* `bun check` runs `node scripts/check-tanstack-api-access.js` to enforce that
  `apps/tanstack-web/src` does not call relative protected `/api`, `/internal`,
  or `/trpc` paths directly and does not import or create Supabase clients. Run
  the focused command when reviewing a frontend port before the full repo check.

## Backend Crate Structure And The 700-LOC Ceiling

Every source file in the repo — Rust included — must stay well-maintained and
under a hard **700-LOC ceiling** whenever possible (start splitting around
\~400 LOC). The `apps/backend` crate root was decomposed to honor this:

* `src/lib.rs` (\~680 LOC) is now just the module registry (`mod <handler>;`),
  the public types, and `pub(crate) use` re-exports.
* `src/dispatch/` holds `handle_backend_request` plus one
  `dispatch_chunk_NN.rs` per route-table chunk. **New route arms append to a
  `dispatch_chunk_NN.rs`**; when a chunk approaches 700 LOC, add a fresh
  `chunk_NN.rs` and wire it into `dispatch/mod.rs`. Each chunk does
  `use crate::*;` to reach crate-root helpers/types.
* Cohesive helper families live in named submodules, each under 700 LOC:
  `types.rs`, `response.rs`, `runtime.rs`, `migration.rs`, `legacy_routes.rs`,
  `static_routes.rs`, `route_predicates.rs`, `config_env.rs`, `constants.rs`,
  `native.rs`, `worker_runtime.rs`. Each is re-exported from `lib.rs` with
  `pub(crate) use <mod>::*;` so existing call sites resolve unchanged.
* The unit-test suite lives in `src/tests.rs` (`mod tests;`), split by area so
  no test file crosses the ceiling.

To extract a new family: move the items into `src/<mod>.rs`, header it with
`use crate::*;` (plus any external `use serde…`), give moved items `pub(crate)`
visibility, then add `mod <mod>; pub(crate) use <mod>::*;` to `lib.rs`. Keep a
struct and the functions that read its private fields in the same module so
fields only need `pub(crate)` where a cross-module reader (e.g. `tests.rs`)
requires it. Do not bulk-restructure `lib.rs`/`dispatch/` while batches are
appending without a `tmp/agent-coordination/` claim. See `apps/backend/AGENTS.md`
for the full rules.

## No New Debt While The Switch Is Pending

Treat `apps/web`, `apps/backend`, and `apps/tanstack-web` as **one system**. The
migration runs in parallel with normal feature work, so any change that touches
only `apps/web` silently grows the backlog the cutover must clear. All future
work must keep the three surfaces consistent where applicable:

* **New or changed `apps/web` API route (any method).** If `apps/backend` already
  owns that path, port the same behavior change into the Rust handler in the same
  PR (match status codes, body shape, cache headers; migrate GET first and return
  `None` for un-ported methods so they fall through). If it is not owned yet,
  register/refresh the route in
  `apps/tanstack-web/migration/route-overrides.json` and regenerate with
  `bun migration:tanstack:manifest`, so the new surface is tracked as backlog
  instead of invisible debt. Verify ownership with the runtime coverage probe in
  `apps/backend/AGENTS.md` (migrated method = COVER, un-ported = FRESH).
* **New or changed dashboard page/route.** Mirror the manifest registration so
  `apps/tanstack-web` tracking stays accurate, and route shared data access
  through `packages/internal-api` (consumed by both frontends) rather than
  app-local fetchers, so the eventual TanStack port is a move, not a rewrite.
* **Shared data access.** Prefer adding a `packages/internal-api` facade over a
  one-off `apps/web` fetcher; the facade is the seam both the Next.js and
  TanStack frontends call, and it forwards to the Rust backend server-side.
* **Tracking, not blocking.** You do not have to finish the Rust/TanStack port in
  every PR, but you must leave the manifest accurate. A route that is added to
  `apps/web` and not reflected in the manifest is the debt this migration exists
  to avoid. `bun migration:tanstack:check` and the backend coverage probe are the
  guards.

## Security And Test Requirements

Every migrated Rust endpoint needs the same ownership evidence before its
manifest entry can move out of `legacy-next`:

* a `route-overrides.json` entry with a non-empty evidence note that marks the
  legacy artifact as `migrated` or `accepted-removal`
* an OpenAPI path or schema update in `apps/backend/api/openapi.yaml`
* a Rust route dispatcher test covering the success case; full-route ownership
  also needs unsupported method behavior, while method-level ownership needs an
  assertion that still-legacy sibling methods are not claimed by Rust
* a `packages/internal-api` facade when the TanStack app or shared UI needs to
  call the endpoint

Contact/profile backend routes now meet that terminal bar for the app-session
contract used by TanStack contact: `GET /api/v1/users/me/profile`,
`PATCH /api/v1/users/me/profile`, and `POST /api/v1/inquiries` verify
`ttr_app_` app-session JWTs, enforce same-origin mutation checks for cookie
auth, validate request bodies, call Supabase REST through the server-owned Rust
outbound adapter, and have mocked native/Worker persistence tests.
`PATCH /api/v1/users/me/full-name` separately revalidates the browser Supabase
session, validates the required trimmed `full_name`, and upserts the
authenticated user's `user_private_details` row with the caller token.
`GET` / `PATCH` `/api/v1/users/me/default-workspace` separately preserves the
legacy default-workspace read fallback to `null`, supports current-user
app-session reads, and updates the authenticated user's saved default workspace
only after caller-token workspace membership validation.
`PATCH /api/v1/inquiries/:id` separately revalidates the browser Supabase
session, requires a Tuturuuu/XWF email domain, and updates the inquiry admin
flags through the same Rust Supabase REST adapter. Broader Supabase session
revalidation remains part of the dedicated auth migration milestone, so route
notes must stay explicit about the app-session versus browser-session boundary.

`scripts/backend-openapi-migration-contract.test.js` compares the migrated
Rust-owned route artifacts in `apps/tanstack-web/migration/route-manifest.json`
with `apps/backend/api/openapi.yaml`. Add or update the OpenAPI operation in the
same commit that marks a Rust route artifact `migrated`; otherwise `bun check`
fails.

For method-level overrides, the same evidence applies to each migrated method,
and the route override must leave every unmigrated sibling method as a generated
`legacy-next` artifact. Do not mark a full route migrated only because a safe
preflight or placeholder method is implemented in Rust.

The manifest check compares both aggregate method counts and each route's method
list against the current `apps/web/src/app` tree, including generated export
patterns such as `createOfflineRoute(...)` exports. Regenerate
the manifest after adding, removing, or changing exported methods in a legacy
`route.ts`. Non-terminal routes with `methods: []` are still artifacts in the
ownership inventory; port, restore an exported method, or mark them
`accepted-removal` with an explicit reason before cutover.

Rust JSON responses must keep the shared response security defaults:
`Content-Type: application/json`, `Content-Security-Policy: default-src 'none';
frame-ancestors 'none'; base-uri 'none'`, `Referrer-Policy: no-referrer`,
`X-Content-Type-Options: nosniff`, and `X-Frame-Options: DENY`. Route ports that
replace legacy public probes or API handlers must preserve explicit cache
behavior, including `Cache-Control: no-store` for `/api/health` and
`Cache-Control: public, max-age=300, must-revalidate` for `/.well-known/*`.
Non-JSON routes should use the empty-response path instead of serializing JSON
`null` when the legacy handler returned no body.

Protected workspace, cron, job, and admin endpoints stay server-owned. Browser
code cannot call protected Rust routes directly, cannot receive service tokens,
and cannot bypass `packages/internal-api` / TanStack server functions for
session-aware data access. Worker-bound secrets belong in Cloudflare secret
bindings; keep local, Docker, and Wrangler configuration to environment
variable names only.

For Cloudflare specifically:

* Bind `BACKEND_INTERNAL_TOKEN`, `BACKEND_PUBLIC_ORIGIN`, `SUPABASE_URL`,
  `SUPABASE_SERVICE_ROLE_KEY`, `CRON_SECRET`, and
  `DISCORD_APP_DEPLOYMENT_URL`, plus `AURORA_EXTERNAL_URL` and
  `AURORA_EXTERNAL_WSID`, with `wrangler secret put`,
  `wrangler versions secret put`, or Cloudflare dashboard secret bindings.
  The TanStack Worker reaches the backend Worker through the `BACKEND` service
  binding; configure `BACKEND_INTERNAL_URL` only for non-binding HTTP fallback
  runs. Use `secret put` for first preview bootstrap only because it deploys a
  new active version immediately; use the versions command family for
  rotations and canaries.
* Bind `TUTURUUU_APP_COORDINATION_SECRET` on the backend Worker before testing
  contact/profile routes. The Rust verifier also accepts existing
  app-coordination fallback secret names for compatibility, but the dedicated
  secret name is the preferred Cloudflare binding.
* Keep local Worker secret values in ignored `apps/backend/.dev.vars` and
  `apps/tanstack-web/.dev.vars` files. Do not commit literal origins that are
  account-specific private targets, tokens, API keys, cookies, or session
  material.
* `CMS_APP_URL` and `NEXT_PUBLIC_CMS_APP_URL` are public origin allowlist inputs
  for the WebGL upload preflight. They may be supplied through Wrangler vars or
  local `.dev.vars`, but they are not backend tokens and must not be listed as
  required secrets.
* Keep private/admin data ownership server-side. If a migrated endpoint needs a
  Supabase service role or private schema access, the Rust backend owns that
  call path; the browser receives only the authorized response shape.
* Review CORS, cookie domain, `SameSite`, secure-cookie, and session-origin
  behavior before mapping a custom hostname. Preview `workers.dev` origins are
  different sites from `tuturuuu.localhost` and production `tuturuuu.com`, so
  cookie/session behavior must be proven with smoke or E2E evidence rather than
  assumed from Docker.
* Keep `BACKEND_ENV=preview` for Cloudflare preview. Development-only
  migration routes and local E2E bypasses must not be enabled by Worker deploys.
* Do not bypass the migration gate because a Worker smoke passed. Worker smoke
  proves deploy compatibility; cutover still requires manifest, Docker E2E, and
  benchmark evidence.

Migration inventory endpoints are also protected because they expose checked
legacy route source paths and route ownership state. `GET /api/migration/status`,
`GET /api/migration/manifest`, `GET /api/migration/progress`, and
`GET /api/migration/cutover-gates` require
`Authorization: Bearer <BACKEND_INTERNAL_TOKEN>`. The TanStack migration
dashboard calls them from a Start server function through
`packages/internal-api`, which adds the bearer token only on the server.

The first Rust-owned migration contracts are exposed from `apps/backend` and
consumed by the TanStack shell through a Start server function:

| Endpoint                                                                                                                                                                                   | Purpose                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /.well-known/*` / `HEAD /.well-known/*`                                                                                                                                               | Legacy-compatible cacheable empty `404` for unsupported well-known probes.                                                                                                                                                                                                                                                                                                                                                                            |
| `GET /~recover-browser-state` / `POST /~recover-browser-state`                                                                                                                             | Legacy-compatible browser recovery route with no-store HTML, same-origin POST protection, Clear-Site-Data, auth cookie clearing, and login redirect.                                                                                                                                                                                                                                                                                                  |
| `GET /api/health`                                                                                                                                                                          | Legacy-compatible health route migrated from `apps/web` to Rust.                                                                                                                                                                                                                                                                                                                                                                                      |
| `GET /api/auth/me`                                                                                                                                                                         | Legacy-compatible current Supabase user route backed by browser Supabase cookie or non-app-session Bearer revalidation through Supabase Auth, returning the raw user payload with no-store headers.                                                                                                                                                                                                                                                   |
| `GET /api/auth/mfa/totp/assurance-level`                                                                                                                                                   | Legacy-compatible Supabase MFA assurance-level route backed by browser Supabase cookie or non-app-session Bearer revalidation, JWT `aal`/`amr` claims, and verified factors from the revalidated user JSON.                                                                                                                                                                                                                                           |
| `GET` / `POST` `/api/auth/mfa/totp/factors`                                                                                                                                                | Legacy-compatible Supabase TOTP factor list/enrollment routes backed by browser Supabase cookie or non-app-session Bearer revalidation and Supabase Auth REST for enrollment.                                                                                                                                                                                                                                                                         |
| `GET` / `DELETE` `/api/auth/mfa/totp/factors/:factorId`                                                                                                                                    | Legacy-compatible Supabase TOTP factor detail/unenrollment routes backed by Auth JS-compatible factor listing and Supabase Auth REST unenrollment.                                                                                                                                                                                                                                                                                                    |
| `GET /api/v1/calendar/mock`                                                                                                                                                                | Legacy-compatible deterministic mock calendar events migrated from `apps/web` to Rust.                                                                                                                                                                                                                                                                                                                                                                |
| `GET /api/v1/devboxes/cache` and `POST /api/v1/devboxes/cache/prune`                                                                                                                       | Legacy-compatible devbox cache routes accepting platform CLI app-session access tokens or browser Supabase sessions, requiring root workspace `MEMBER` access, returning the current empty cache list body, and acknowledging prune requests without private devbox table mutations.                                                                                                                                                                  |
| `GET` / `POST` `/api/v1/aurora/forecast`, `/ml-metrics`, and `/statistical-metrics`                                                                                                        | Legacy-compatible Aurora forecast and metric readers plus protected ingest routes backed by Supabase Auth, the legacy Tuturuuu email-domain gate, external Aurora fetches, and caller-token Supabase inserts.                                                                                                                                                                                                                                         |
| `POST` / `DELETE` `/api/v1/infrastructure/languages`                                                                                                                                       | Legacy-compatible locale preference cookie route for `NEXT_LOCALE`.                                                                                                                                                                                                                                                                                                                                                                                   |
| `POST` / `DELETE` `/api/v1/infrastructure/sidebar`                                                                                                                                         | Legacy-compatible sidebar collapsed preference cookie route for `sidebar-collapsed`.                                                                                                                                                                                                                                                                                                                                                                  |
| `POST` / `DELETE` `/api/v1/infrastructure/sidebar/sizes`                                                                                                                                   | Legacy-compatible sidebar sizing preference cookie route for `sidebar-size` and `main-content-size`.                                                                                                                                                                                                                                                                                                                                                  |
| `GET /api/v1/infrastructure/users/fields/types`                                                                                                                                            | Legacy-compatible static user field type metadata route returning `TEXT`, `NUMBER`, `BOOLEAN`, `DATE`, and `DATETIME` in the original order.                                                                                                                                                                                                                                                                                                          |
| `GET /api/v1/infrastructure/ai/models`                                                                                                                                                     | Legacy-compatible public AI model catalog backed by private-schema Supabase REST reads with a fixed public column list, filters, sanitized search, capped ID filters, and exact-count pagination.                                                                                                                                                                                                                                                     |
| `GET /api/admin/tasks/embeddings/stats`                                                                                                                                                    | Legacy-compatible Tuturuuu-admin task embedding coverage stats backed by Supabase Auth cookie validation and server-owned exact task counts. The SSE embedding generator remains legacy-owned.                                                                                                                                                                                                                                                        |
| `GET /api/:wsId/crawlers/list`                                                                                                                                                             | Legacy-compatible authenticated crawled URL listing backed by Supabase Auth cookie validation, server-owned raw `crawled_urls` reads, exact-count pagination, and an explicit 401 for non-Tuturuuu callers.                                                                                                                                                                                                                                           |
| `GET /api/v1/workspaces/:wsId/crawlers/status`                                                                                                                                             | Legacy-compatible workspace-agnostic crawler status lookup backed by server-owned exact `crawled_urls.url` reads and raw related `crawled_url_next_urls` rows ordered by `created_at.desc`.                                                                                                                                                                                                                                                           |
| `GET /api/v1/ai/whitelist/me`                                                                                                                                                              | Legacy-compatible authenticated current-user AI whitelist status backed by satellite app-session auth or browser Supabase cookie auth and a server-owned private-schema enabled-flag lookup.                                                                                                                                                                                                                                                          |
| `GET /api/v1/cms/workspaces`                                                                                                                                                               | Legacy-compatible CMS workspace list backed by app-session or browser Supabase auth, service-role workspace reads, root-admin/per-workspace external-project permission checks, active binding resolution, and subscription tier metadata.                                                                                                                                                                                                            |
| `GET /api/v1/mira/achievements`                                                                                                                                                            | Legacy-compatible Mira achievement catalog backed by browser Supabase auth, private-schema service-role catalog reads, caller-token unlocked-achievement reads, and derived unlock/grouping/stat payloads.                                                                                                                                                                                                                                            |
| `GET /api/v1/storage/list`                                                                                                                                                                 | Legacy-compatible workspace Drive object list backed by `ttr_` workspace API-key validation, `manage_drive` permission checks, path sanitization, reserved mobile-deployment vault blocking, server-owned Supabase Storage list calls, placeholder/reserved-entry filtering, and recursive file-count pagination.                                                                                                                                     |
| `GET /api/time-tracking/export`                                                                                                                                                            | Legacy-compatible root-only grouped time-tracking export backed by browser Supabase auth, Tuturuuu email-domain gating, root workspace membership checks, caller-token `get_grouped_sessions_paginated` RPC calls, parseInt-style query defaults, a 1000-row limit cap, and the legacy empty-result fallback.                                                                                                                                         |
| `GET /api/v1/hive/ai/models`                                                                                                                                                               | Legacy-compatible Hive AI model catalog backed by Hive app-session or browser Supabase auth, Hive member/admin access, and server-owned private-schema model reads mapped to the shared UI model shape.                                                                                                                                                                                                                                               |
| `GET /api/v1/users/me/hive-access`                                                                                                                                                         | Legacy-compatible authenticated current-user Hive access status backed by current-user app-session auth or browser Supabase cookie auth and server-owned membership/admin flag lookups.                                                                                                                                                                                                                                                               |
| `GET /api/v1/nova/me/team`                                                                                                                                                                 | Legacy-compatible authenticated current-user Nova team lookup backed by Nova app-session auth or browser Supabase cookie auth and a server-owned private-schema team membership lookup.                                                                                                                                                                                                                                                               |
| `GET /api/v1/task-board-status-templates`                                                                                                                                                  | Legacy-compatible authenticated global task-board status template catalog backed by Supabase cookie or Bearer auth and server-owned ordered catalog reads.                                                                                                                                                                                                                                                                                            |
| `GET /api/v1/workspaces/limits`                                                                                                                                                            | Legacy-compatible authenticated workspace creation limit check backed by Supabase Auth cookie validation and server-owned exact counts of non-deleted workspaces created by the caller.                                                                                                                                                                                                                                                               |
| `GET /api/v1/workspaces/:wsId/posts/permissions`                                                                                                                                           | Legacy-compatible post permission flag reader backed by Supabase Auth revalidation and server-owned `has_workspace_permission` RPC checks, preserving quiet false flags for missing auth or unresolved permissions.                                                                                                                                                                                                                                   |
| `GET /api/v1/workspaces/:wsId/Mention`                                                                                                                                                     | Legacy-compatible mention email endpoint backed by Supabase Auth revalidation, exact `MEMBER` workspace membership, and caller-token `workspace_users.email` reads.                                                                                                                                                                                                                                                                                   |
| `GET /api/v1/workspaces/:wsId/habits/access`                                                                                                                                               | Legacy-compatible habits feature access probe backed by Supabase Auth revalidation, workspace normalization, service-role membership validation, and exact `ENABLE_HABITS=true` workspace secret matching.                                                                                                                                                                                                                                            |
| `GET /api/v1/workspaces/:wsId/mobile/module-flags`                                                                                                                                         | Legacy-compatible mobile module flag endpoint backed by Supabase Auth revalidation, caller-token workspace membership, and server-owned `workspace_secrets` reads for hidden module policy.                                                                                                                                                                                                                                                           |
| `GET /api/v1/workspaces/:wsId/education/access`                                                                                                                                            | Legacy-compatible education feature access probe backed by Supabase Auth revalidation, getPermissions-compatible `ai_lab` checks, and server-owned `workspace_secrets` `ENABLE_EDUCATION` reads.                                                                                                                                                                                                                                                      |
| `GET /api/v1/workspaces/:wsId/finance/budgets/status`                                                                                                                                      | Legacy-compatible budget status probe backed by finance/platform app-session or Supabase Auth revalidation, workspace normalization, `manage_finance` permission checks, and server-owned `get_budget_status` RPC reads.                                                                                                                                                                                                                              |
| `GET /api/workspaces/:wsId/finance/charts/balance`                                                                                                                                         | Legacy-compatible balance chart point backed by finance/platform app-session or Supabase Auth revalidation, workspace normalization, `view_finance_stats` checks, and `get_wallet_balance_at_date` RPC reads.                                                                                                                                                                                                                                         |
| `GET /api/v1/workspaces/:wsId/finance/debts/summary`                                                                                                                                       | Legacy-compatible debt and loan summary probe backed by finance/platform app-session or Supabase Auth revalidation, workspace normalization, `manage_finance` checks, and private `get_debt_loan_summary` RPC reads.                                                                                                                                                                                                                                  |
| `GET /api/v1/workspaces/:wsId/finance/filter-users`                                                                                                                                        | Legacy-compatible finance filter user endpoint backed by finance/platform app-session or Supabase Auth revalidation, workspace normalization, `view_transactions` checks, service-role creator reads, and caller-token workspace user reads.                                                                                                                                                                                                          |
| `GET /api/v1/workspaces/:wsId/finance/invoices/subscription/context`                                                                                                                       | Legacy-compatible subscription invoice context endpoint backed by finance/platform app-session or Supabase Auth revalidation, workspace normalization, `create_invoices` checks, student group validation, and service-role attendance/invoice reads.                                                                                                                                                                                                 |
| `GET /api/v1/workspaces/:wsId/finance/recurring-transactions/upcoming`                                                                                                                     | Legacy-compatible upcoming recurring transaction probe backed by finance/platform app-session or Supabase Auth revalidation, workspace normalization, `view_transactions` checks, and `get_upcoming_recurring_transactions` RPC reads.                                                                                                                                                                                                                |
| `GET /api/v1/workspaces/:wsId/settings/permissions`                                                                                                                                        | Legacy-compatible workspace settings permission flags backed by Supabase Auth revalidation, personal/workspace identifier resolution, membership validation, server-owned role/default permission reads, and the private 30-second success cache directive.                                                                                                                                                                                           |
| `GET /api/v1/workspaces/:wsId/settings/permissions/check`                                                                                                                                  | Legacy-compatible workspace permission checker backed by Supabase Auth revalidation, personal/workspace identifier resolution, membership validation, and server-owned role/default permission reads.                                                                                                                                                                                                                                                 |
| `GET /api/v1/workspaces/:wsId/course-modules` and `GET /api/v1/workspaces/:wsId/quiz-sets/:setId/linked-modules`                                                                           | Legacy-compatible education module readers backing the TanStack linked-modules page, with browser Supabase auth, `ai_lab` permission resolution, `ENABLE_EDUCATION` gating, exact-count pagination, and quiz-set workspace binding.                                                                                                                                                                                                                   |
| `GET` / `PATCH` `/api/v1/user/onboarding-progress`                                                                                                                                         | Legacy-compatible authenticated onboarding progress reader/updater backed by Supabase Auth cookie validation, server-owned `onboarding_progress` reads/upserts, and the legacy allowed-field update contract.                                                                                                                                                                                                                                         |
| `PATCH /api/v1/user/profile`                                                                                                                                                               | Legacy-compatible browser-session profile update backed by Supabase Auth cookie validation, legacy profile field validation, and server-owned `users` row updates scoped to the authenticated user.                                                                                                                                                                                                                                                   |
| `GET` / `PATCH` `/api/v1/users/me/default-workspace`                                                                                                                                       | Legacy-compatible default-workspace reader/updater backed by current-user app-session or browser Supabase auth for reads, caller-token membership validation for writes, and the legacy personal-workspace/null fallback.                                                                                                                                                                                                                             |
| `GET` / `PATCH` `/api/v1/users/calendar-settings`                                                                                                                                          | Legacy-compatible current-user calendar settings reader/updater backed by calendar app-session or browser Supabase auth, `user_private_details` reads/writes, `auto` defaults, and legacy enum/string patch validation.                                                                                                                                                                                                                               |
| `GET /api/v1/users/me/identities`                                                                                                                                                          | Legacy-compatible browser-session linked identity reader backed by Supabase Auth revalidation, raw user JSON identity extraction, derived `canUnlink`, and the private success cache directive.                                                                                                                                                                                                                                                       |
| `PATCH /api/v1/users/me/full-name`                                                                                                                                                         | Legacy-compatible browser-session full-name update backed by Supabase Auth cookie validation, required trimmed `full_name` validation, and caller-token `user_private_details` upsert scoped to the authenticated user.                                                                                                                                                                                                                               |
| `POST /api/v1/aurora/health`                                                                                                                                                               | Legacy-compatible protected Aurora health probe backed by Supabase Auth cookie validation, the legacy Tuturuuu email-domain gate, and an outbound `AURORA_EXTERNAL_URL/health` check.                                                                                                                                                                                                                                                                 |
| `GET` / `POST` `/api/v1/internal/holidays`, `POST` `/api/v1/internal/holidays/bulk`, and `PUT` / `DELETE` `/api/v1/internal/holidays/:holidayId`                                           | Rust counterparts for the Infrastructure-owned Vietnamese holiday list/create/bulk-import/update/delete routes. GET uses the Rust server-owned Supabase REST adapter with optional parseInt-style year filtering. Mutations revalidate Supabase auth, require root workspace `MEMBER` access, and write with the caller token so holiday RLS stays active. Bulk import preserves the replace-existing year delete plus date-conflict upsert behavior. |
| `GET /api/v1/topic-announcement-verifications/:token`                                                                                                                                      | Legacy-compatible public Topic Announcements email verification route backed by server-owned private-schema Supabase REST reads and updates. Workspace Topic Announcements management APIs remain legacy-owned.                                                                                                                                                                                                                                       |
| `GET /api/v1/users/me/profile`                                                                                                                                                             | App-session current-user profile route. It verifies `ttr_app_` JWTs, reads `users` and `user_private_details` through the server-owned Supabase REST adapter, and returns the legacy profile shape with no-store headers.                                                                                                                                                                                                                             |
| `PATCH /api/v1/users/me/profile`                                                                                                                                                           | App-session profile mutation route. It enforces same-origin confirmation for cookie auth, validates `display_name`, `bio`, and `avatar_url`, and persists the allowed fields to the `users` row through Supabase REST.                                                                                                                                                                                                                                |
| `POST /api/v1/inquiries`                                                                                                                                                                   | App-session support-inquiry route. It enforces same-origin confirmation for cookie auth, validates the legacy payload and field limits, and inserts `support_inquiries` with `creator_id` from the resolved app-session user.                                                                                                                                                                                                                         |
| `PATCH /api/v1/inquiries/:id`                                                                                                                                                              | Browser-session inquiry admin update route. It validates the legacy `is_read` and `is_resolved` flags, requires a Tuturuuu/XWF email domain, and patches `support_inquiries` through the server-owned Supabase REST adapter.                                                                                                                                                                                                                          |
| `OPTIONS /api/v1/auth/password-login`, `/otp/send`, and `/otp/verify`; `GET` / `OPTIONS` `/api/v1/auth/otp/settings`                                                                       | Legacy-compatible shared wildcard CORS preflights plus public OTP availability lookup backed by the root workspace OTP config reads. Paired OTP send/verify and password auth methods remain legacy-owned.                                                                                                                                                                                                                                            |
| `OPTIONS /api/v1/auth/mobile/password-login`, `/send-otp`, and `/verify-otp`                                                                                                               | Method-level legacy-compatible shared wildcard CORS `204` preflights; paired mobile auth methods remain legacy-owned.                                                                                                                                                                                                                                                                                                                                 |
| `GET` / `PUT` `/api/v1/infrastructure/mobile-versions`                                                                                                                                     | Legacy-compatible protected mobile policy snapshot and write route requiring a revalidated Supabase browser session or Bearer token plus root `manage_workspace_roles`; writes normalize the policy payload and upsert all nine root config rows.                                                                                                                                                                                                     |
| `GET` / `POST` `/api/v1/infrastructure/timezones` and `PUT` / `DELETE` `/api/v1/infrastructure/timezones/:timezoneId`                                                                      | Legacy-compatible protected timezone collection plus detail update/delete routes requiring a revalidated Supabase browser session or Bearer token plus root `manage_workspace_roles`, backed by server-owned private-schema `timezones` reads/writes.                                                                                                                                                                                                 |
| `GET /api/v1/infrastructure/user-status-changes`                                                                                                                                           | Legacy-compatible workspace user status change list backed by caller-token Supabase REST reads so `workspace_user_status_changes` RLS, exact count, required `ws_id`, and legacy `limit`/`offset` range behavior stay intact.                                                                                                                                                                                                                         |
| `GET /api/v1/infrastructure/users`                                                                                                                                                         | Legacy-compatible workspace user export list backed by caller-token Supabase REST reads so `workspace_users` RLS, exact count, required `ws_id`, and legacy `limit`/`offset` range behavior stay intact.                                                                                                                                                                                                                                              |
| `GET /api/v1/infrastructure/classes`, `/product-categories`, and `/score-names`                                                                                                            | Legacy-compatible catalog export lists backed by caller-token Supabase REST reads so `workspace_user_groups`, `product_categories`, and `user_group_metrics` RLS and exact-count pagination stay intact.                                                                                                                                                                                                                                              |
| `GET /api/v1/infrastructure/lessons` and `/packages`                                                                                                                                       | Legacy-compatible content export lists for private `user_group_posts` and `workspace_products`, preserving exact-count pagination, legacy auth shape for packages, and the no-auth lesson export behavior.                                                                                                                                                                                                                                            |
| `GET /api/v1/infrastructure/product-prices`, `/product-units`, and `/warehouses`                                                                                                           | Legacy-compatible inventory setup exports for private `inventory_products`, `inventory_units`, and `inventory_warehouses`, preserving inventory app-session auth, catalog/setup permission checks, exact-count pagination, and error bodies.                                                                                                                                                                                                          |
| `GET` / `POST` `/api/v1/infrastructure/ai/whitelist/domains` and `/emails`                                                                                                                 | Legacy-compatible protected AI whitelist collection routes backed by service-role private-schema reads/inserts after Supabase auth and `@tuturuuu.com` operator email validation.                                                                                                                                                                                                                                                                     |
| `PUT` / `DELETE` `/api/v1/infrastructure/ai/whitelist/:email` and `/domain/:domain`                                                                                                        | Legacy-compatible protected AI whitelist detail update/delete backed by service-role private-schema writes after Supabase auth and `@tuturuuu.com` operator email validation.                                                                                                                                                                                                                                                                         |
| `GET /api/v1/infrastructure/post-email-queue`                                                                                                                                              | Legacy-compatible protected post email queue infrastructure summary backed by service-role `post_email_queue` reads after root workspace membership validation, preserving summary, workspace, and batch aggregation behavior.                                                                                                                                                                                                                        |
| `GET /api/v1/infrastructure/bills`, `/roles`, and `/transaction-categories`                                                                                                                | Legacy-compatible workspace export lists backed by caller-token Supabase REST reads so `finance_invoices`, `workspace_user_groups`, and `transaction_categories` RLS and exact-count pagination stay intact.                                                                                                                                                                                                                                          |
| `GET /api/v1/infrastructure/wallet-transactions`                                                                                                                                           | Legacy-compatible protected wallet transaction export backed by the caller-token `get_wallet_transactions_with_permissions` RPC with legacy ordering, limit/offset, raw rows, and first-row `total_count` extraction.                                                                                                                                                                                                                                 |
| `GET /api/v1/infrastructure/abuse-intelligence`                                                                                                                                            | Legacy-compatible protected abuse intelligence snapshot backed by caller-token reputation subject, signal, and challenge reads plus service-role active trust override reads after root `view_infrastructure` permission validation.                                                                                                                                                                                                                  |
| `GET /api/v1/infrastructure/abuse-events`                                                                                                                                                  | Legacy-compatible root-workspace abuse event list backed by caller-token Supabase REST reads with legacy `ip`/`type`/`success` filters, page/pageSize pagination, exact counts, and auth/error bodies.                                                                                                                                                                                                                                                |
| `GET /api/v1/infrastructure/blocked-ips`                                                                                                                                                   | Legacy-compatible root-workspace blocked IP list backed by caller-token Supabase REST reads with the legacy `unblocked_by_user` embed, status/ip filters, page/pageSize pagination, exact counts, and auth/error bodies.                                                                                                                                                                                                                              |
| `GET /api/v1/infrastructure/suspensions`                                                                                                                                                   | Legacy-compatible active user suspension list backed by service-role `user_suspensions` reads after root `manage_workspace_roles`; POST and detail DELETE remain legacy-owned mutation methods.                                                                                                                                                                                                                                                       |
| `GET` / `POST` `/api/v1/infrastructure/email-blacklist` and `GET` / `PUT` / `DELETE` `/api/v1/infrastructure/email-blacklist/:entryId`                                                     | Legacy-compatible root-workspace email blacklist reads, creation, detail update, and detail deletion backed by caller-token Supabase REST with Zod-style write validation parity.                                                                                                                                                                                                                                                                     |
| `GET /api/v1/infrastructure/bill-coupons`, `/bill-packages`, `/class-attendance`, `/class-members`, `/class-packages`, `/class-scores`, `/package-stock-changes`, and `/student-feedbacks` | Legacy-compatible related-filter export lists backed by caller-token Supabase REST reads with embedded workspace relationships and exact-count pagination.                                                                                                                                                                                                                                                                                            |
| `GET /api/v1/infrastructure/user-monthly-reports` and `/user-monthly-report-logs`                                                                                                          | Legacy-compatible protected monthly report export lists backed by shared workspace permission resolution and private-schema Supabase REST exact-count pagination.                                                                                                                                                                                                                                                                                     |
| `GET` / `OPTIONS` `/api/v1/mobile/version-check`                                                                                                                                           | Legacy-compatible public mobile version policy evaluation and shared wildcard CORS preflight backed by fixed root workspace policy config IDs read through the Rust backend Supabase REST adapter.                                                                                                                                                                                                                                                    |
| `OPTIONS /api/v1/auth/qr-login/challenges[...]`                                                                                                                                            | Method-level legacy-compatible bare empty `204` preflights for QR login challenge create, poll, and approve routes.                                                                                                                                                                                                                                                                                                                                   |
| `OPTIONS /api/v1/auth/mfa/mobile/challenges[...]` and `/approvals[...]`                                                                                                                    | Method-level legacy-compatible bare empty `204` preflights for MFA mobile challenge create, poll, approve, and approval listing routes.                                                                                                                                                                                                                                                                                                               |
| `OPTIONS /api/v1/workspaces/:wsId/external-projects/webgl-packages/upload`                                                                                                                 | Method-level legacy-compatible WebGL upload preflight with credentialed CMS CORS headers only for allowed CMS origins.                                                                                                                                                                                                                                                                                                                                |
| `POST /api/v1/workspaces/:wsId/user-groups/:groupId/group-checks/:postId/email`                                                                                                            | Legacy-compatible removed direct post email route returning `410 Gone`; queue-based sending owns approved emails.                                                                                                                                                                                                                                                                                                                                     |
| `GET` / `POST` `/api/v1/workspaces/:wsId/slides`                                                                                                                                           | Legacy-compatible workspace slides collection placeholder returning `501 Not implemented`.                                                                                                                                                                                                                                                                                                                                                            |
| `PUT` / `DELETE` `/api/v1/workspaces/:wsId/slides/:slideId`                                                                                                                                | Legacy-compatible workspace slide item placeholder returning `501 Not implemented`.                                                                                                                                                                                                                                                                                                                                                                   |
| `PUT /api/v1/infrastructure/migrate/grouped-score-names`                                                                                                                                   | Disabled infrastructure migration route migrated from `apps/web` to Rust with the same development-only guard and `410 MIGRATION_DISABLED` body.                                                                                                                                                                                                                                                                                                      |
| `GET` / `PUT` / `PATCH` / `POST` `/api/v1/infrastructure/migrate/:migration`                                                                                                               | Accepted-removal terminal decommission for legacy batch migration helpers; Rust preserves the development/local-E2E guard and per-slug legacy method allow lists while returning `410 MIGRATION_DISABLED`.                                                                                                                                                                                                                                            |
| `PUT /api/workspaces/:wsId/products/categories/migrate`, `/products/units/migrate`, `/transactions/categories/migrate`, `/users/indicators/migrate`, and `/wallets/transactions/migrate`   | Obsolete workspace migration writes accepted for removal; Rust keeps the development-only guard and returns a terminal `410 MIGRATION_DISABLED` response.                                                                                                                                                                                                                                                                                             |
| `GET` / `POST` `/api/v1/workspaces/:wsId/encryption/migrate`, `POST /api/v1/workspaces/:wsId/storage/migrate`, `GET /api/v2/workspaces/:wsId/migrate/:module`                              | Production auth/API-key migration helpers accepted for removal; Rust keeps the legacy method allow lists and returns terminal `410 MIGRATION_DISABLED` in all environments.                                                                                                                                                                                                                                                                           |
| `GET /api/migration/status`                                                                                                                                                                | Runtime, environment, deployment target, and manifest pointer.                                                                                                                                                                                                                                                                                                                                                                                        |
| `GET /api/migration/manifest`                                                                                                                                                              | The checked route manifest JSON.                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `GET /api/migration/progress`                                                                                                                                                              | Owner/kind progress buckets and representative remaining legacy route artifacts.                                                                                                                                                                                                                                                                                                                                                                      |
| `GET /api/migration/cutover-gates`                                                                                                                                                         | Backend-derived manifest gates plus required E2E and benchmark evidence placeholders.                                                                                                                                                                                                                                                                                                                                                                 |

`/api/migration/cutover-gates` is the dashboard authority for cutover state. It
must stay blocked while any manifest route remains `legacy-next`, any backend
route artifact is not mapped to `rust-backend`, or required Docker E2E and
benchmark evidence is missing.

## Docker And E2E

The production compose stack defines `tanstack-web`, `tanstack-web-blue`, and
`tanstack-web-green` services. The Docker Bake file includes matching
`blue-green-tanstack-web*` targets so benchmark and cutover work can build
candidate TanStack images beside the legacy web images.

`apps/backend/Dockerfile` copies
`apps/tanstack-web/migration/route-manifest.json` into the Rust build context
because the backend includes the manifest at compile time for the migration
contract endpoints. Run `bun check:docker` after manifest path or Dockerfile
changes.

Legacy E2E remains the default:

```bash theme={null}
bun test:e2e:web:docker -- --frontend next
```

TanStack E2E uses the same Playwright suite and points at the TanStack route:

```bash theme={null}
bun test:e2e:web:docker -- --frontend tanstack
```

Run both modes sequentially before cutover:

```bash theme={null}
bun test:e2e:web:docker -- --frontend compare
```

Compare mode writes `tmp/e2e/web-migration/compare-report.json` after running
both frontends. Each frontend result includes normalized origin evidence,
`passRate`, `wallMs`, and Playwright JSON reporter test counts so
`bun migration:tanstack:gates` can evaluate same-origin mistakes, E2E
regressions, and zero-test false positives from the same evidence file. The gate
rejects missing, credentialed, invalid, or identical Next/TanStack origins, and
it rejects compare reports that do not prove nonzero Playwright execution for
both frontends. Set `E2E_COMPARE_REPORT_PATH` when a run needs to write the file
elsewhere under `tmp/`.

`apps/web/e2e/public-marketing-routes.noauth.spec.ts` is the first shared
public-route parity suite for this migration. It runs under the existing
`apps/web` Playwright project so `--frontend tanstack` and `--frontend compare`
reuse the same assertions for migrated landing, product, legal, redirect,
offline, branding, blog, careers, demo, security, partners, UI docs,
visualization, and static solution routes.

`scripts/public-marketing-e2e-coverage.test.js` compares the migrated public
page entries in `apps/tanstack-web/migration/route-manifest.json` with that
no-auth Playwright spec. When a public marketing, UI docs, redirect, or offline
page is marked `migrated`, the route needs a concrete default-locale E2E
example in the shared spec before `bun check` can pass.

## Benchmarks

Use the benchmark harness to compare reachable Next and TanStack frontend
routes, plus independent Rust backend smoke routes. It does not yet compare
legacy Next.js API route timing against equivalent Rust endpoints. Reports are
written under ignored
`tmp/benchmarks/web-migration/<timestamp>/report.json`.

```bash theme={null}
bun benchmark:web-setups -- --setup compare --profile smoke
```

Backend benchmark samples include protected migration endpoints. Set
`BACKEND_INTERNAL_TOKEN` when running the benchmark against local Docker,
preview Workers, or any backend that requires internal authorization; otherwise
the protected samples correctly fail as unreachable `4xx` responses.

To compare the legacy production/staging origin against Cloudflare preview
Workers, pass all origins explicitly:

```bash theme={null}
BACKEND_INTERNAL_TOKEN="${BACKEND_INTERNAL_TOKEN:?set BACKEND_INTERNAL_TOKEN}" \
bun benchmark:web-setups -- \
  --setup compare \
  --profile smoke \
  --next-origin https://<legacy-next-origin> \
  --tanstack-origin https://<tanstack-worker-origin> \
  --backend-origin https://<backend-worker-origin>
```

Compare reports must prove that the legacy Next.js and TanStack Start samples
came from distinct normalized frontend origins. `bun benchmark:web-setups`
rejects same-origin compare runs before writing a report, and
`bun migration:tanstack:gates` rejects benchmark evidence with missing origins,
credentialed origins, identical Next/TanStack origins, route/sample URLs that do
not match the recorded setup origin, or matched frontend routes without their
own `frontend-route-p95` comparison. Docker E2E compare evidence uses the same
distinct-origin rule for the browser-facing Next and TanStack frontend runs.

Use full mode when both frontends are running with representative seeded data:

```bash theme={null}
bun benchmark:web-setups -- --setup compare --profile full --require-all
```

In compare mode, `--require-all` fails the benchmark command when any required
metric evidence is missing. That keeps local benchmark rehearsals aligned with
`bun migration:tanstack:gates` instead of deferring missing dev-ready, build,
image-size, RSS/CPU, JS-output, E2E, or API latency evidence until cutover.

Pass reviewer-approved non-HTTP metrics and accepted regression notes through
`--evidence` when the harness cannot measure them directly:

```json theme={null}
{
  "metrics": {
    "backend": {
      "apiLatencyP50Ms": 80,
      "apiLatencyP95Ms": 120,
      "apiLatencyP99Ms": 180
    },
    "next": {
      "apiLatencyP50Ms": 75,
      "apiLatencyP95Ms": 110,
      "apiLatencyP99Ms": 170,
      "devReadyMs": 2200,
      "dockerBuildMs": 240000,
      "e2ePassRate": 1,
      "e2eWallMs": 90000,
      "firstRouteColdMs": 650,
      "imageSizeBytes": 1200000000,
      "jsOutputBytes": 850000,
      "productionCpuPercent": 4,
      "productionRssBytes": 640000000,
      "warmNavigationMs": 180
    },
    "tanstack": {
      "devReadyMs": 1800,
      "dockerBuildMs": 180000,
      "e2ePassRate": 1,
      "e2eWallMs": 84000,
      "firstRouteColdMs": 520,
      "imageSizeBytes": 760000000,
      "jsOutputBytes": 620000,
      "productionCpuPercent": 3,
      "productionRssBytes": 420000000,
      "warmNavigationMs": 140
    }
  },
  "acceptedRegressions": [
    {
      "metric": "first-route-cold-time",
      "note": "Approved while Cloudflare preview cache is cold."
    }
  ]
}
```

```bash theme={null}
bun benchmark:web-setups -- \
  --setup compare \
  --profile full \
  --require-all \
  --evidence tmp/benchmarks/web-migration/evidence.json
```

After the full benchmark writes a report, pass that report to
`bun migration:tanstack:gates` with the Docker E2E compare report and
Cloudflare smoke report. Generated benchmark, smoke, and E2E reports stay under
ignored `tmp/` paths. Cutover gates reject evidence older than 24 hours by
default; use `--evidence-max-age-ms <milliseconds>` only when a rehearsal
explicitly accepts a longer freshness window.

Default gates:

* frontend route p95 must not regress more than `25%`
* Cloudflare smoke evidence must include passing `backend-health`,
  `backend-ready`, `backend-migration-status`,
  `backend-migration-status-missing-token`,
  `backend-migration-status-invalid-token`, and `tanstack-root` probes
* cutover reports must include the full metric comparison contract:
  API p50/p95/p99, dev ready time, first-route cold time, warm navigation time,
  Docker build time, image size, JS output size, production RSS/CPU baseline,
  E2E wall time, and E2E pass rate, with numeric baseline, candidate, ratio,
  and threshold values for each required comparison
* full compare evidence must include complete matching frontend route coverage;
  unmatched Next-only or TanStack-only routes fail `--require-all` and cutover
  gate validation
* representative backend smoke routes must stay below the smoke ceiling
* strict runs fail when any required route is unreachable

Route samples include aggregate `p50Ms`, `p95Ms`, and `p99Ms`, plus `coldMs`
for the first successful request and `warmP50Ms` / `warmP95Ms` / `warmP99Ms`
for later samples. Use those fields for first-route cold time, warm navigation
time, and representative API latency notes. Add Docker build time, image size,
process RSS/CPU, JS output size, and E2E wall-time evidence to the same
benchmark directory when running full cutover rehearsals.

Record approved exceptions in the migration PR. Do not silently widen thresholds
to make a run pass.

## Cutover Checklist

1. Every manifest route is `migrated` or `accepted-removal`.
2. `bun migration:tanstack:cutover-check` passes.
3. `bun test:e2e:web:docker -- --frontend compare` passes and has a compare
   evidence report.
4. `bun benchmark:web-setups -- --setup compare --profile full --require-all` passes or has approved exceptions. HTTPS origins must present a certificate trusted by the host; use the local development CA or `NODE_EXTRA_CA_CERTS` instead of disabling certificate verification.
5. `bun smoke:cloudflare --output <path>` passes against the preview Workers.
6. `bun migration:tanstack:gates -- --e2e-report <path> --benchmark-report <path> --cloudflare-smoke-report <path>` passes.
7. `bun check:docker` and `bun check` pass.
8. Legacy `apps/web` remains available as the rollback fixture until production
   monitoring shows the TanStack/Rust path is stable.
