Files
kandev/docs/plans/azure-devops-integration/plan.md
T
2026-07-21 08:40:26 +01:00

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/azuredevops package. Do not add Azure methods to github.Client or 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_url task inputs alongside the legacy github_url compatibility 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, and main.go where pollers are started.
  • Repository provider parsing/discovery where provider enums are currently restricted to GitHub/GitLab.
  • Runtime defaults: profiles.yaml for 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.ts and apps/web/lib/types/azure-devops.ts.
  • Domain hooks under apps/web/hooks/domains/azure-devops/.
  • Settings route and integration menu entry.
  • /azure-devops browse 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-chrome flows 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 fmt
  • rtk go test ./internal/azuredevops/... from apps/backend
  • rtk make -C apps/backend test
  • rtk make -C apps/backend lint
  • rtk pnpm --filter @kandev/web typecheck from apps
  • rtk pnpm --filter @kandev/web test -- --run from apps
  • rtk pnpm --filter @kandev/web lint from apps
  • pnpm e2e:run --host --project chromium -- e2e/tests/integrations/azure-devops.spec.ts from apps/web
  • pnpm e2e:run --host --project mobile-chrome -- e2e/tests/integrations/mobile-azure-devops.spec.ts e2e/tests/task/mobile-create-task-remote-repo.spec.ts from apps/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

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.