Files
2026-08-27 10:25:37 +00:00

7.0 KiB

created, status, requirements, system_design, legacy_specs
created status requirements system_design legacy_specs
2026-08-27 complete
REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-001
../../specs/integrations/system-design/github-authentication-01.md
../../specs/integrations/system-design/github-authentication-02.md
../../specs/integrations/system-design/github-authentication-03.md

Fix Plan: Resolve GitHub Clone Protocol Per Host At Use Time

Overview

Replace the backend-startup Git protocol snapshots with one host-aware resolver. Evaluate this resolver when Kandev constructs a clone URL or an executor-inherited managed-checkout origin. Then route the long-lived cloner and review-repository adapter through it. The tests prove that all paths observe configuration changes without a restart.

Confirmed root cause

repoclone.DetectGitProtocol runs only gh config get git_protocol. Thus, a global https value wins when gh config get -h github.com git_protocol reports the effective ssh preference. backendapp/main.go passes that incorrect startup result into one long-lived repoclone.Cloner. backendapp/orchestrator.go stores a second startup result on repositoryResolverAdapter. Executor-inherited origin reconciliation selects the wrong transport. It cannot observe later gh configuration changes until the backend restarts.

The smallest reproduction uses an isolated GH_CONFIG_DIR. Set global git_protocol=https and host-specific github.com git_protocol=ssh. The current detector reads https. gh config get -h github.com git_protocol reads ssh.

Scope

In scope

  • Resolve the github.com clone protocol from host-specific configuration first. Use global configuration second. Use SSH by default when neither scope yields ssh or https.
  • Resolve the protocol at clone URL construction and Local/Worktree launch or resume origin reconciliation, not backend startup.
  • Remove the cached protocol field from repositoryResolverAdapter and route it through the same live resolver as repoclone.Cloner.
  • Preserve canonical HTTPS for managed task credentials and preserve user-managed local origins.
  • Add deterministic tests with injected command and protocol resolvers.

Out of scope

  • Executor-mode credential-helper or token bridging tracked by #3072.
  • Discovering or validating the actor behind inherited SSH agents or credential managers.
  • GitHub Enterprise Server or hosts other than the existing github.com contract.
  • Frontend, API, persistence, schema, or workspace-policy changes.

Technical approach

Host-aware protocol resolver

  • In apps/backend/internal/repoclone/protocol.go, make protocol resolution accept a context and a provider host. Query gh config get -h <host> git_protocol first. Then query gh config get git_protocol. Accept only ssh and https. Otherwise, return the existing SSH default. Bound the complete host-plus-global resolution operation with one five-second command context.
  • Isolate command execution behind an injected runner. Unit tests control the results and assert command order without reading the developer's gh configuration. Keep one five-second command timeout for the complete resolution operation.

Use-boundary resolution

  • In apps/backend/internal/repoclone/clone.go, store an injected protocol resolver, not a resolved protocol string. Make protocol-aware URL construction resolve the normalized provider host on every call.
  • In apps/backend/internal/backendapp/main.go, construct the cloner with the live resolver and remove the startup call to DetectGitProtocol.
  • In apps/backend/internal/orchestrator/executor/executor.go and executor_resume.go, thread the operation context through the protocol-aware RepoCloner URL builder. The shared launch and resume path continues to reconcile only Kandev-managed GitHub checkouts. Managed mode remains explicitly HTTPS.
  • In apps/backend/internal/backendapp/orchestrator.go, replace the adapter's concrete cached protocol field with a narrow cloner interface that builds the URL at ResolveForReview use time. Production wiring supplies the same repoclone.Cloner. Tests supply a deterministic fake.

Tests

  • TestDetectGitProtocolPrefersHostConfiguration in apps/backend/internal/repoclone/protocol_test.go is the primary regression. Before the correction, the command runner observes no host-specific lookup. The result is HTTPS. Companion cases cover global fallback, unsupported values, command failures, and SSH default.
  • TestClonerBuildCloneURLUsesCurrentProtocol in apps/backend/internal/repoclone/clone_test.go mutates an injected resolver between calls and proves one long-lived cloner does not cache a result.
  • TestEnsureRepoLocalPathReevaluatesGitHubProtocol in apps/backend/internal/orchestrator/executor/executor_resume_clone_transport_test.go performs two preparation passes with different resolver results. It proves that the managed origin changes without executor recreation. Existing managed-HTTPS and user-managed-local cases cover the exclusions.
  • TestRepositoryResolverAdapterUsesCurrentGitProtocol in apps/backend/internal/backendapp/adapters_test.go performs two resolutions through an injected fake and proves the adapter has no independent startup cache.

Execution checklist

  • Audit the current plan, specifications, work order, and working tree.
  • Implement the live host-aware protocol resolver and use-time URL construction.
  • Update executor origin reconciliation and review-repository wiring.
  • Add and pass the specified regression tests.
  • Update plan/work-order verification results.
  • Commit with hooks, push the branch, and create a ready-for-review PR.
  • Wait 15 minutes, run PR fixup, and report the final PR state.

Work orders

Verification results

  • rtk go test -race ./internal/repoclone ./internal/orchestrator/executor ./internal/backendapp -run 'Test(DetectGitProtocol|ClonerBuildCloneURLUsesCurrentProtocol|EnsureRepoLocalPathReevaluatesGitHubProtocol|RepositoryResolverAdapterUsesCurrentGitProtocol)' -count=1 passed with 11 tests in 3 packages, including the total-timeout regression.
  • rtk go test -race ./internal/repoclone ./internal/orchestrator/executor ./internal/backendapp passed with 1,316 tests in 3 packages.
  • PR 3078 at 662d3c98d3ddd560ff46cab83e2d8cf965571f65 completed with 44 checks passed, 0 failed, 0 pending, and 0 unresolved review threads. GitHub reports MERGEABLE / CLEAN.

Risks

  • Adding context to protocol-aware URL construction touches executor test fakes. All implementations must preserve the same host and operation context.
  • A gh lookup now occurs on each relevant URL construction. One five-second bound covers the complete host-plus-global resolution, and the shared gh subprocess throttle limits the cost. Correctness requires no process cache.
  • Provider-host normalization must pass github.com, not an HTTPS URL, to gh --host. Clone URL construction must retain the canonical persisted provider origin.