--- kind: task slug: trpc-models-router title: tRPC ai.models router — CRUD, role routes, testProvider plan_slug: automation-foundation epic_slug: model-provider-registry status: ready priority: P1 tenant_id: global owner: unassigned cursor_todo_id: null updated_at: "2026-07-03" agent_prompt: | Read docs/adr-model-routing.md. apps/web/server only. Admin-only mutations (match updateWorkflowPrompt bar). testProvider runs a minimal completion server-side — never return API keys to client. claim_task before work. --- # Task summary Add `ai.models` tRPC router: provider CRUD, role route upsert/delete, `testProvider`, and `resolveForRole` debug procedure. ## Description ### Procedures | Procedure | Auth | Notes | |-----------|------|-------| | `listProviders` | member | workspace-scoped | | `createProvider` / `updateProvider` / `deleteProvider` | admin | zod validate; unique alias | | `testProvider` | admin | one short completion; return `{ ok, latencyMs, error? }` | | `listRoleRoutes` | member | join provider alias for display | | `upsertRoleRoute` / `deleteRoleRoute` | admin | custom `roleId` allowed | | `resolveForRole` | member | calls shared `resolveModel` with DB rows | ### Model client factory - Add `packages/ai/src/providers/resolve-client.ts` (or similar): given `ResolvedModel`, return Vercel AI SDK model instance for `generateText` in `testProvider` - Support at least: `anthropic`, `openai`, `google`, `openai_compatible` ### Wire router - Register in `apps/web/server/root.ts` - Export input schemas from shared where possible ## Subtasks - [ ] Implement provider CRUD - [ ] Implement role route CRUD - [ ] Implement testProvider with provider factory - [ ] Implement resolveForRole ## Estimation M ## Acceptance criteria - [ ] Admin can create provider via tRPC; non-admin gets FORBIDDEN - [ ] testProvider works against env-configured Anthropic or Ollama when aliases exist - [ ] `pnpm lint && pnpm type-check` clean ## Links - Epic: `./Epic-model-provider-registry.md` - Depends on: `Task-db-model-providers-migration.md`, `Task-shared-schemas-resolve-model.md`