7.2 KiB
Azure DevOps Integration Plan
Scope
Implement the read-only Azure DevOps Services integration defined in
../../specs/azure-devops-integration/spec.md:
workspace-scoped PAT configuration, direct REST work-item and pull-request
reads, persistent task PR links, responsive settings/browse surfaces, immediate
integration availability updates, provider-neutral remote repository selection,
and server-side authenticated Azure clones. No Azure runtime path may require
gh or az.
Architecture
- Add an independent
internal/azuredevopspackage. Do not add Azure methods togithub.Clientor translate Azure records into GitHub API structs. - Reuse Jira's workspace-scoped config/secret/health patterns and GitLab's source-host REST/task-review patterns.
- Persist provider-native Azure identifiers. Normalize only the summary fields required by shared task UI.
- Persist canonical credential-free remote URLs for provider repositories and
normalize new
remote_urltask inputs alongside the legacygithub_urlcompatibility field. - Resolve Azure clone credentials by workspace inside the backend clone path. Never expose the PAT to task metadata, an agent environment, a persisted URL, or command output.
- Use Azure DevOps REST API 7.1, an injected HTTP client for deterministic tests, bounded response bodies, context-aware requests, and typed API errors.
- Register the service as non-fatal during backend boot and expose mock routes
only under
KANDEV_MOCK_AZURE_DEVOPS=true.
Backend Touch Points
- New package:
apps/backend/internal/azuredevops/. - Service wiring:
apps/backend/internal/backendapp/services.go,helpers.go, andmain.gowhere pollers are started. - Repository provider parsing/discovery where provider enums are currently restricted to GitHub/GitLab.
- Runtime defaults:
profiles.yamlfor the E2E mock selector only. - Workspace cleanup and task/repository validation through existing service interfaces rather than integration-specific SQL outside the new package.
Frontend Touch Points
- Typed API and types under
apps/web/lib/api/domains/azure-devops-api.tsandapps/web/lib/types/azure-devops.ts. - Domain hooks under
apps/web/hooks/domains/azure-devops/. - Settings route and integration menu entry.
/azure-devopsbrowse page with a compact work-item/PR segmented view, desktop filter rail, and mobile filter sheet.- Task PR summary integration through a provider-tagged view model; Azure detail remains in Azure-specific components.
- A shared integration availability invalidation channel updates every consumer after configuration mutations while retaining periodic health polling.
- A shared source-control repository picker merges GitHub, GitLab, and Azure discovery and dispatches branch reads to the selected provider.
- Azure browse presets and saved views reuse the interaction model of GitHub and GitLab, with raw WIQL contained in an Advanced disclosure.
- No required action may be hover-only or desktop-only.
Tests
- Go table tests for URL validation, PAT headers, API errors, WIQL batching, PR conversion, workspace isolation, persistence, and route status codes.
- Go service tests for repository/task association validation and restart persistence.
- TypeScript unit tests for API request/response normalization and pure filter or status helpers.
- Playwright desktop and
mobile-chromeflows using the Azure mock controller: connect, browse work items, browse PRs, and open PR feedback. - Security review of secret isolation, URL/SSRF validation, response-size bounds, and error redaction before final verification.
- Go tests for provider-neutral task inputs, canonical remote URLs, and credential cleanup around Azure clone processes.
- Component and Playwright coverage for immediate availability, Enabled chips, provider grouping, preset/saved-view behavior, and mobile parity.
Verification
rtk make -C apps/backend fmtrtk go test ./internal/azuredevops/...fromapps/backendrtk make -C apps/backend testrtk make -C apps/backend lintrtk pnpm --filter @kandev/web typecheckfromappsrtk pnpm --filter @kandev/web test -- --runfromappsrtk pnpm --filter @kandev/web lintfromappspnpm e2e:run --host --project chromium -- e2e/tests/integrations/azure-devops.spec.tsfromapps/webpnpm e2e:run --host --project mobile-chrome -- e2e/tests/integrations/mobile-azure-devops.spec.ts e2e/tests/task/mobile-create-task-remote-repo.spec.tsfromapps/web
Risks
- Azure organization URLs are an outbound-request boundary. V1 accepts only
canonical HTTPS
dev.azure.com/<organization>URLs to avoid an SSRF-capable arbitrary host setting. - WIQL returns references rather than hydrated work items and Azure caps batch retrieval at 200 IDs; ordering and partial omissions require explicit tests.
- Azure reviewer votes and branch policies do not map one-to-one to GitHub reviews and checks. Only summary states are shared.
- Existing task PR UI is GitHub-heavy. The implementation must extract only the smallest provider-tagged presentation contract required for Azure, not begin a broad GitHub/GitLab refactor.
- The task creation API and branch loader are GitHub-named today. Compatibility fields must remain accepted while internal contracts become provider-neutral.
- Azure PAT clone auth must not leak through process arguments, persisted remote URLs, executor metadata, structured logs, or agent-visible environment state.
- Remote executors receive credential-free clone URLs. A private Azure repo is guaranteed to clone through the backend materialization path; remote executor push/clone credentials remain separately configured.
Task Waves
Wave 1: backend foundation
Wave 2: backend product reads
Wave 3: frontend
Wave 4: integrated validation
Wave 5: integration navigation and Azure browse UX
Wave 6: provider-neutral repository selection
- Task 10: Remote repository contracts and discovery
- Task 11: Secure Azure repository materialization
- Task 12: Unified task repository picker
Wave 7: integrated validation
Tasks within a wave are listed separately for ownership clarity but should run sequentially in the current workspace when they touch the same package or state composition files.