Submatter/.convoys/repo-discovery-onboarding/brief-1-api.md

51 lines
3.7 KiB
Markdown
Raw Normal View History

---
brief: 1
convoy: repo-discovery-onboarding
role: role-implementer
title: Forge account repository discovery API
status: ready
priority: P1
slice_dependencies: []
recommended_model: qwen-coder
model_tier: local
workspace_id: global
---
# Brief 1 — Forge account repository discovery API
## Goal
A workspace admin can request a normalized, paginated list of repositories visible to either their linked GitHub identity or a configured Forgejo/Gitea instance. Already-connected repositories are identified without exposing credentials to the client.
Backlog task: `plans/Plan-automation-foundation/Epic-repo-discovery-onboarding/Task-forge-discovery-api.md`.
## Security and product contract
- Do not accept or return raw access tokens in tRPC input/output.
- GitHub credentials come from the current user's `accounts` row for `provider='github'`; never use another workspace member's account.
- Update the existing GitHub provider authorization parameters to request repository discovery scopes. Return a typed `reauthorization_required` state when the stored account lacks the required scope instead of treating it as a forge API failure.
- Forgejo/Gitea discovery uses a workspace-admin-supplied instance descriptor and `tokenEnvVar`; resolve the token only on the server with the existing `readToken` pattern.
- Only workspace owner/admin may call discovery. All connected-repo comparisons filter by `workspace_id`.
- Keep the existing paste-URL flow working.
## Files
- `packages/shared/src/connected-repos/schemas.ts` — add zod schemas/types for discovery source, normalized remote repository summary, pagination cursor/page, and typed connection state; export through `packages/shared/src/connected-repos/index.ts`.
- `apps/web/lib/auth.ts` — configure GitHub authorization scopes while preserving the existing sign-in and account-linking flow.
- `apps/web/server/lib/forge/adapters.ts` — add a discovery context separate from repo-specific `ForgeAdapterContext`; implement paginated GitHub `/user/repos` and Forgejo/Gitea `/user/repos` mapping. Preserve `fetchRepoMetadata` and `createPullRequest` behavior.
- `apps/web/server/routers/connected-repos.ts` — add admin-only `listAvailable`; resolve credentials server-side, call the selected adapter, and mark an item connected using the unique tuple `(workspace_id, api_base_url, owner, repo_name)`.
- Add focused tests for response validation, pagination, missing credentials/scopes, private repository mapping, and already-connected matching. If web tests require missing infrastructure, add the smallest Vitest setup consistent with existing package configs.
## Acceptance
- GitHub and Forgejo/Gitea payloads map to one zod-validated result containing stable remote ID, name/full name, owner, HTTPS clone URL, web URL, default branch, privacy flag, description, and updated time.
- Pagination is explicit; the implementation does not silently truncate accounts with more than 100 repositories.
- A credentials or scope problem returns a typed connection state suitable for UI remediation and does not leak a token or provider response body.
- Existing connected repos are marked accurately within the current workspace only.
- Existing manual connect/test/update/disconnect procedures continue to work.
- `pnpm --filter @tasks/shared test`, `pnpm --filter @tasks/web lint`, and `pnpm --filter @tasks/web type-check` pass.
## Prompt for implementer
Implement only Brief 1. Read `AGENTS.md`, the matching backlog task, `apps/web/lib/auth.ts`, `apps/web/server/lib/forge/adapters.ts`, and `apps/web/server/routers/connected-repos.ts` before editing. Use TDD for adapter normalization and credential-state behavior. Do not build the picker UI, batch connection, document ingestion, or agent configuration in this brief. Do not persist plaintext PATs.