--- kind: task slug: repo-picker-modal title: Repository picker and batch connection plan_slug: automation-foundation epic_slug: repo-discovery-onboarding status: ready priority: P1 tenant_id: global owner: unassigned cursor_todo_id: null updated_at: "2026-09-25" --- # Task summary Add a searchable, paginated repository picker to Connected Repos and an admin-only batch mutation that safely connects selected remote repositories to the current workspace. ## Description The discovery result from `Task-forge-discovery-api` is an untrusted client boundary. The server must re-resolve or validate selected remote IDs against the authorized forge account instead of accepting arbitrary URLs supplied by the browser. The existing manual URL dialog remains available. ## Subtasks - [ ] Add `connectedRepos.batchConnect` with zod validation and workspace owner/admin authorization. - [ ] Re-resolve selected remote IDs server-side and derive forge URL, owner, repo, default branch, and metadata from the authorized provider response. - [ ] Insert in one transaction with conflict-safe handling of `connected_repos_workspace_repo_unique`. - [ ] Add a discovery dialog using existing Radix/UI primitives with provider connection states, search, pagination/load-more, multi-select, and connected/disabled rows. - [ ] Preserve selection while paging and show loading, empty, partial-error, and import-progress states. - [ ] Invalidate both connected and available repo queries after success. - [ ] Add tests for forged selections, duplicate imports, tenant isolation, and selection helpers where feasible. ## Estimation M ## Acceptance criteria - [ ] GitHub and Forgejo/Gitea sources display actionable authorization/configuration states. - [ ] Search matches full name and description while selected repos remain selected across pages. - [ ] Already-connected repos cannot be selected. - [ ] Batch connection is atomic for valid selections, idempotent for duplicates, and returns per-repo results. - [ ] A stale or manipulated browser payload cannot connect an arbitrary repository URL. - [ ] Manual URL connection continues to work. - [ ] Web lint and type-check pass. ## Links - Epic: `./Epic-repo-discovery-onboarding.md` - Depends on: `./Task-forge-discovery-api.md` - Convoy brief: `../../../.convoys/repo-discovery-onboarding/brief-2-ui.md`