Files
kandev/docs/plans/integration-provider-auth-errors/plan.md
T
2026-08-24 11:09:03 +00:00

5.4 KiB

spec, related_spec, created, status
spec related_spec created status
docs/specs/auth/requirements/auth.md docs/specs/integrations/requirements/github-authentication.md 2026-07-31 done

Implementation Plan: Integration Provider Authentication Errors

Overview

The shared web API client currently treats every HTTP 401 as an expired Kandev browser session. GitHub, GitLab, Jira, and Linear also return 401 when their own credentials expire, so the global handler navigates to /login before each integration page can render its existing loading error. Gate the global redirect on the backend's Kandev session challenge, then prove provider errors stay local and invalid GitHub PAT saves remain visible and retryable.

Confirmed root cause

  • apps/web/lib/api/client.ts calls the global onUnauthorized callback for every 401 response.
  • apps/web/src/main.tsx implements that callback with window.location.assign("/login").
  • Kandev's global auth middleware identifies a real session challenge with WWW-Authenticate: Bearer; upstream-provider 401 responses from integration handlers do not.
  • The four provider data pages (/github, /gitlab, /jira, /linear) already catch request failures and render result errors, but the unconditional global redirect prevents users from seeing them.
  • GitHub PAT replacement is already validated before persistence and the connection dialog already retains failed drafts; focused coverage is missing for a connection-only invalid PAT rejection.

Frontend

Shared API authentication classification

  • Update apps/web/lib/api/client.ts so onUnauthorized runs only for a 401 carrying Kandev's WWW-Authenticate: Bearer session challenge.
  • Continue parsing and throwing ApiError for every non-2xx response so provider pages and settings forms receive the original sanitized error message.
  • Add apps/web/lib/api/client.test.ts covering challenged and unchallenged 401 responses.

GitHub PAT save feedback

  • Extend apps/web/components/github/github-connection-dialog.test.tsx with a connection-only invalid-PAT rejection. Assert the dialog stays open, the error toast is visible, the token draft is retained, and onSaved is not called.
  • No production component change is expected unless the regression exposes behavior that differs from the amended spec.

Mobile contract

The repair changes request classification only. It does not change composition, navigation, overlays, touch behavior, scrolling, or viewport-dependent interaction. Desktop and mobile share the same API client and provider-error state, so focused unit/component coverage plus the existing mobile integration settings suites satisfy mobile parity; no new mobile-only composition is needed.

Tests

  • What: a Kandev session challenge still clears the stale browser identity. File: apps/web/lib/api/client.test.ts. How: mock a 401 response with WWW-Authenticate: Bearer and assert onUnauthorized runs once before ApiError is thrown.
  • What: an integration/provider 401 remains a normal request error. File: apps/web/lib/api/client.test.ts. How: mock a 401 without the challenge header, assert onUnauthorized is not called, and assert the provider error body becomes the thrown ApiError message.
  • What: an invalid GitHub PAT is visible and retryable. File: apps/web/components/github/github-connection-dialog.test.tsx. How: reject setGitHubWorkspaceConnection, save a PAT-only draft, and assert the open dialog, retained input, error toast, and unchanged saved callback.

E2E Tests

  • Scenario: GIVEN configured GitHub, GitLab, Jira, and Linear integrations, WHEN each provider data request returns an unchallenged 401, THEN its page remains on the provider route and displays the loading error instead of navigating to /login. File: apps/web/e2e/tests/integrations/provider-auth-errors.spec.ts. What to verify: seed each integration with existing E2E helpers, intercept its primary data endpoint with a sanitized 401 response, assert the provider-specific error text and unchanged URL.
  • Scenario: GIVEN GitHub settings with a connected workspace, WHEN a replacement PAT save is rejected as invalid, THEN the connection surface remains open, displays the error, and retains the submitted token for correction. File: apps/web/e2e/tests/integrations/provider-auth-errors.spec.ts. What to verify: intercept PUT /api/v1/github/workspace-connection, submit the dialog, and assert no /login navigation, visible error feedback, retained PAT input, and existing connection.

Implementation Tasks

Execution is sequential: Task 02 depends on Task 01. No task is parallel-safe because the E2E proof depends on the shared API-client behavior implemented by Task 01.

Risks And Out Of Scope

  • The challenge check must preserve redirect behavior for truly expired Kandev sessions.
  • Provider error bodies remain subject to each backend handler's existing sanitization; this repair does not redesign provider-specific copy or HTTP status mappings.
  • No credential schema, persistence, health-poller, settings layout, or mobile composition changes.
  • No new behavior for integration settings beyond GitHub's requested invalid-PAT save feedback.