--- kind: task slug: forge-discovery-api title: Forge account repository discovery API 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 Expose an admin-only, paginated tRPC query that discovers repositories visible to the current user's linked GitHub identity or a configured Forgejo/Gitea instance and marks repos already connected to the current workspace. ## Description The existing forge adapter is repository-specific and resolves credentials through `token_env_var`. Discovery needs a separate account/instance context and typed connection states. Credentials stay on the server: GitHub uses the current user's `accounts` row, while Forgejo/Gitea uses an instance URL plus a token environment-variable reference. ## Subtasks - [ ] Add shared zod schemas for discovery source, normalized repository summary, pagination, and typed states such as `connected`, `configuration_required`, and `reauthorization_required`. - [ ] Configure GitHub authorization scopes and detect linked accounts whose stored scope is insufficient. - [ ] Implement paginated GitHub `/user/repos` and Forgejo/Gitea `/user/repos` adapters with validated response mapping. - [ ] Add `connectedRepos.listAvailable`, restricted to workspace owner/admin. - [ ] Resolve credentials using the current user/workspace only and redact provider response details from client errors. - [ ] Mark existing repos using `(workspace_id, api_base_url, owner, repo_name)`. - [ ] Add mocked tests for pagination, private repos, malformed responses, missing credentials/scopes, and tenant-scoped matching. ## Security constraints - No raw token in tRPC input or output. - Never select another member's linked GitHub account. - Do not store a plaintext Forgejo/Gitea PAT in the database. - Preserve existing manual connect/test/update/disconnect behavior. ## Estimation M ## Acceptance criteria - [ ] Normalized results include stable remote ID, full name, owner, HTTPS clone URL, web URL, default branch, privacy, description, and updated time. - [ ] Accounts with more than one provider page are not silently truncated. - [ ] Missing/insufficient credentials return an actionable typed state without leaking secrets. - [ ] Already-connected status is accurate only within the resolved workspace. - [ ] Shared tests, web lint, and web type-check pass. ## Links - Epic: `./Epic-repo-discovery-onboarding.md` - Convoy brief: `../../../.convoys/repo-discovery-onboarding/brief-1-api.md`