diff --git a/docs/plans/github-credential-upgrade-recovery/plan.md b/docs/plans/github-credential-upgrade-recovery/plan.md new file mode 100644 index 0000000000..d7f2d75313 --- /dev/null +++ b/docs/plans/github-credential-upgrade-recovery/plan.md @@ -0,0 +1,149 @@ +--- +created: 2026-09-12 +status: complete +requirements: + - REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-001 +system_design: + - ../../specs/integrations/system-design/github-authentication-01.md + - ../../specs/integrations/system-design/github-authentication-03.md +legacy_specs: [] +--- + +# Fix Plan: Explain GitHub Credential Upgrade Recovery + +Issue: [#3071](https://github.com/kdlbs/kandev/issues/3071). + +## Overview + +The issue remains useful as a documentation repair. Its original runtime proposals need separate treatment. +This package records the historical default change and keeps the public task-access guidance concise. +The upgrade-specific recovery runbook is deferred because it is temporary migration guidance. +It preserves the current policy contract and uses one documentation work order. + +## Investigation evidence + +Investigation date: 2026-09-12. Local HEAD and remote main both equal +`49df3794bc15d610988acc674637384ce8f1d4be`. Latest stable: v0.94.0, published 2026-09-09. +The issue was opened on 2026-08-26 against v0.91.0+ and contains no attachments or comments. + +| Concern | Current evidence | Disposition | +| --- | --- | --- | +| Historical managed default | `github.Store.addTaskGitCredentialsMode` still adds the column with `DEFAULT 'managed'`, including in v0.94.0. | The historical upgrade behavior remains. | +| New workspace default | PR #2156, commit `190eeddbc`, persists executor access. First containing stable tag: v0.84.1. | Already fixed before this issue. | +| Existing workspace policy | `InitializeFreshWorkspaceDefaults` skips existing stores. Missing settings still resolve to managed. | Preserve intentional managed choices. | +| Stale prepared checkout | PR #3077, commit `c2e2b3a43`, reconciles origins before prepared launches. | Fixed in v0.92.0. | +| Host clone protocol | PR #3078, commit `e4d17b3925`, resolves host-specific protocol dynamically. | Fixed in v0.92.0. | +| Preflight | `PreflightManagedGitCredentials` validates persisted repository identity and skips executor mode. | It does not prove SSH or HTTPS authentication. | +| Public recovery guide | The **Choose task Git credentials** section explains the current modes and entry points. | Keep durable task-access guidance concise; defer the temporary upgrade runbook. | + +## Confirmed root cause and reproduction + +The original column migration supplied managed mode to existing settings rows. +The current new-workspace initializer deliberately excludes existing installations. +The database stores the resulting policy without evidence of whether the user selected it. +A missing settings row also uses the managed compatibility fallback. + +The smallest current reproduction uses an existing GitHub store with no workspace settings row. +Run `InitializeFreshWorkspaceDefaults`, then read the workspace settings. The policy remains managed. +`TestInitializeFreshWorkspaceDefaultsSkipsExistingGitHubStore` proves this behavior through the real SQLite store. +The public guide does not connect this behavior to the reported healthy-host-login symptom. + +There is no production regression to correct within this package. +The documentation acceptance review currently fails because the historical explanation and recovery procedure are absent. +A code test that expects automatic policy conversion would contradict the current design. + +## Scope + +### In scope + +- Explain the historical managed default and the current new-workspace default. +- Summarize task-access selection and the managed, user-managed, and remote-executor boundaries. +- Keep the public guidance concise and scan-friendly. +- Qualify the existing description of managed access as an opt-in policy for historical workspaces. + +### Out of scope + +- Automatic conversion of saved or missing policies to executor mode. +- Conditional policy selection based on App presence or temporary credential health. +- A new transport-authentication probe, launch warning, settings UI, or schema migration. +- A temporary upgrade-specific recovery runbook in the public guide. +- Reimplementation of #3069 or #3070. +- Editing generated changelog history or closing the entire issue automatically. + +## Technical approach + +Update the existing task-access section in `docs/public/integrations.md` with short bullets. +Keep workspace API authentication separate from credentials inside task processes. +Use **Workspace GitHub access**, **Change connection** when an automation connection exists, **Connect GitHub** otherwise, and **Inherit executor Git credentials** as the existing control labels. +Explain saved policy preservation, task-only executor selection, and the need for a new terminal after a launch or resume. +Do not add a temporary upgrade-specific recovery section; keep its investigation evidence in this plan. + +Keep the origin, service-user, and preflight findings in this plan as evidence for a possible future +runbook. Do not publish those migration details in the current public guide. + +The current specifications intentionally preserve existing policies. +This package follows that boundary and adds only documentation criterion `AC-INTEGRATIONS-GITHUB-AUTHENTICATION-001.13`. +No new ADR is necessary because the runtime boundary does not change. + +## Tests + +Existing source-backed evidence covers the preserved behavior: + +- `workspace_defaults_test.go`: existing-store fallback, explicit managed preservation, and new executor defaults. +- `executor_resume_clone_transport_test.go`: policy-driven origins and prepared launch reconciliation. +- `executor_credentials_preflight_test.go`: executor mode skips managed identity admission. + +All paths are under `apps/backend/internal/github` or `apps/backend/internal/orchestrator/executor` respectively. +The focused command passed in both packages during this investigation: + +```bash +(cd apps/backend && go test -tags fts5 ./internal/github ./internal/orchestrator/executor -run 'TestInitializeFreshWorkspaceDefaultsSkipsExistingGitHubStore|TestInitializeWorkspaceDefaultsPersistsExecutorAndBindsActiveCLI|TestInitializeWorkspaceDefaultsPreservesExistingWorkspaceState|TestLaunchPreparedSession_ExistingWorkspace_ReconcilesGitHubOriginsBeforeAgentStart|TestEnsureRepoLocalPath_ReconcilesGitHubOriginForCredentialPolicy|TestPreflightManagedGitCredentialsSkipsWhenExecutorModePolicy' -count=1) +``` + +No new unit or browser test is needed for a documentation-only correction. +Task 01 owns the public document validation and manual acceptance checklist. + +## Companion packages + +The completed packages remain unchanged because this repair changes none of their implementation scope: + +- [New workspace defaults](../new-workspace-github-access-defaults/plan.md). +- [Prepared workspace origins](../prepared-workspace-origin-reconciliation/plan.md). +- [Executor clone transport](../github-executor-clone-transport/plan.md). +- [Managed admission](../managed-git-credential-admission-repair/plan.md). + +## Work orders + +- [x] [Task 01: Document upgrade recovery](task-01-document-upgrade-recovery.md). + +## Verification results + +Investigation: the focused Go command passed in both packages. +Package validation passed: catalog validation (264 decisions, 818 specifications), specification lint, and `git diff --check`. +Public documentation implementation completed in `docs/public/integrations.md` and +`docs/public/use-kandev.md`. The integration guide now uses short bullets for historical saved +policies, conditional task-access entry points, managed and executor credentials, task-only +executor selection, fresh terminals, and managed, user-managed, and remote-executor boundaries. +The temporary upgrade-specific recovery section was removed from the public guide; its +investigation evidence remains here for a later runbook if needed. +Documentation validation passed: public-doc tests (62), public-doc validation (46 pages), and +the three work-order acceptance conditions. +Build validation passed: `make -C apps/backend build` and +`pnpm --filter @kandev/web build`. +Follow-up source review corrected the disconnected-workspace entry point and the fresh-terminal +recovery instruction; the public upgrade/recovery section was later removed as temporary guidance. +Review follow-up also clarified that historical workspaces may preserve either saved task Git +policy, aligned the plan's control labels with the UI, and completed the work-order touched-file +inventory. Focused post-fixup documentation validation passed: public-doc validation (46 pages), +catalog validation (264 decisions and 818 specifications), specification lint, and +`git diff --check`. +No temporary tests, instances, or database mutations were needed. + +## Risks + +Saved managed policies cannot distinguish migration defaults from deliberate user choices. +A blanket conversion can change credentials for working automation. +An App-only heuristic also excludes valid PAT and named CLI managed connections. +A host credential check cannot establish credential availability inside a remote executor. +The broader transport preflight proposal remains deferred and requires its own executor-aware design. +Completing this package addresses the documentation gap, not every proposal in #3071. diff --git a/docs/plans/github-credential-upgrade-recovery/task-01-document-upgrade-recovery.md b/docs/plans/github-credential-upgrade-recovery/task-01-document-upgrade-recovery.md new file mode 100644 index 0000000000..364253bbea --- /dev/null +++ b/docs/plans/github-credential-upgrade-recovery/task-01-document-upgrade-recovery.md @@ -0,0 +1,112 @@ +--- +id: "01-document-upgrade-recovery" +title: "Document GitHub credential upgrade recovery" +status: done +wave: 1 +depends_on: [] +plan: "plan.md" +requirements: + - REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-001 +acceptance_criteria: + - AC-INTEGRATIONS-GITHUB-AUTHENTICATION-001.13 +system_design: + - ../../specs/integrations/system-design/github-authentication-01.md + - ../../specs/integrations/system-design/github-authentication-03.md +--- + +# Task 01: Document Upgrade Recovery + +## Summary + +Keep the public task-access guidance concise and consistent with preserved policies. +Record the upgrade recovery evidence internally for possible later use. + +## In scope + +- Qualify the managed opt-in description for historical workspaces. +- Keep the existing **Choose task Git credentials** section focused on durable user actions. +- Describe explicit policy selection, task-only executor inheritance, and a fresh terminal after launch or resume. +- Distinguish managed checkouts, user-managed checkouts, and remote executors in short bullets. +- Keep the upgrade investigation evidence in this plan instead of adding a temporary public runbook. +- Include the checklist in Acceptance as a manual documentation review. + +## Out of scope + +Production code, test code, UI copy, automatic migration, credential probes, a temporary public +upgrade runbook, and generated changelog edits. + +## Acceptance + +1. The guide explains historical managed defaults, current executor defaults, and preservation of existing workspace policies. +2. Task-access bullets describe explicit executor selection, a fresh terminal after launch or resume, + and the managed, user-managed, and remote-executor boundaries. +3. The guide does not promise automatic policy conversion or comprehensive credential preflight, + and it does not add a temporary upgrade-specific recovery runbook. + +## Verification + +Run from the repository root: + +```bash +node --test scripts/validate-public-docs.test.mjs +node scripts/validate-public-docs.mjs +python3 scripts/list-docs.py validate +python3 scripts/lint-spec-files.py --all +git diff --check +``` + +Review the three acceptance conditions against the final document and current source. +No new test is required because the correction changes documentation only. + +## Files likely touched + +- `docs/public/integrations.md` +- `docs/public/use-kandev.md` (cross-page summary) +- `docs/plans/github-credential-upgrade-recovery/plan.md` (status and results) +- `docs/plans/github-credential-upgrade-recovery/task-01-document-upgrade-recovery.md` (status and results) + +## Dependencies + +None. The origin fixes already exist in current main and v0.94.0. + +## Risks + +Host `gh` authentication does not establish task Git transport access. +Managed clone worktrees share remote settings. A running agent retains its existing credential environment. +The procedure must not suggest broad manual rewrites, token disclosure, or automatic policy changes. + +## Parallelism + +`sequential` + +## Inputs + +- [Requirement](../../specs/integrations/requirements/github-authentication.md), criterion 001.13. +- [Design](../../specs/integrations/system-design/github-authentication-03.md#upgrade-recovery-guidance). +- [Investigation](plan.md#investigation-evidence). +- `apps/backend/internal/github/store.go`: `addTaskGitCredentialsMode`, `defaultWorkspaceSettings`. +- `apps/backend/internal/github/workspace_defaults.go`: existing-installation guard. +- `apps/backend/internal/orchestrator/executor/executor_credentials.go`: managed admission scope. +- `apps/backend/internal/orchestrator/executor/executor_execute.go`: prepared launch ordering. +- Existing **Choose task Git credentials** section in the public guide. + +## Results + +Implemented concise task-access guidance in +[`docs/public/integrations.md`](../../public/integrations.md). The guide now explains the +historical `managed` compatibility policy, current executor inheritance, preserved saved +policies, conditional **Connect GitHub** and **Change connection** entry points, task-only +executor selection, fresh-terminal requirements, and managed, user-managed, and remote-executor +boundaries. The cross-page summary in +[`docs/public/use-kandev.md`](../../public/use-kandev.md) no longer describes managed access as the +default for new workspaces. +The temporary upgrade-specific recovery section was removed from the public guide; the +investigation evidence remains in the plan for possible later documentation. + +All three acceptance conditions pass by manual review. Public-doc tests (62), public-doc +validation (46 pages), catalog validation, specification lint, focused Go tests, both backend and +web builds, and `git diff --check` pass. The final documentation pass removed the temporary +upgrade-specific recovery section, retained concise task-access guidance, and aligned the plan +and work-order scope. Post-fixup focused documentation validation passed: public-doc validation +(46 pages), catalog validation (264 decisions and 818 specifications), specification lint, and +`git diff --check`. diff --git a/docs/public/integrations.md b/docs/public/integrations.md index a888f4c2e6..e93c6b5274 100644 --- a/docs/public/integrations.md +++ b/docs/public/integrations.md @@ -144,13 +144,24 @@ select **Save changes** once. GitHub App creation, import, and installation rema GitHub workflows. The help control beside **Task Git access** explains the effective credential path on desktop hover or focus and in a touch-accessible drawer on mobile. -- **Managed workspace credentials** (an opt-in policy) uses the selected workspace PAT, named GitHub - CLI account, or GitHub App through Kandev's short-lived, task/repository-scoped broker. Kandev - configures `agentctl` as Git's credential helper so an attached repository can redeem its - matching lease on demand; the returned credential is not written to the repository or Git - configuration. A separate broker-aware shim handles `gh`. The task receives neither the stored - PAT nor an App private key. An executor-profile `GH_TOKEN` or `GITHUB_TOKEN` deliberately takes - precedence for that task. +- Existing workspaces keep their saved task-access policy during upgrades. A historical workspace + may still use managed mode. New workspaces default to **Inherit executor Git credentials**. +- Select **Change connection** when the workspace has an automation connection. Select **Connect + GitHub** when it does not. Both entry points show **Task Git access**. +- **Managed workspace credentials** use the selected PAT, named GitHub CLI account, or GitHub App + through Kandev's task/repository-scoped broker. Kandev provides a short-lived Git helper and `gh` + shim; stored PATs and App private keys are not exposed to the task. An executor-profile + `GH_TOKEN` or `GITHUB_TOKEN` takes precedence. +- **Inherit executor Git credentials** does not install Kandev's helper or `gh` shim. Local and + Worktree tasks use host Git credentials. Docker, SSH, and cloud tasks use credentials configured + in the executor. +- A disconnected workspace can select **Inherit executor Git credentials** and save only the + task-access setting. It does not need a PAT or GitHub App. +- The policy applies to newly launched task processes. After a launch or resume, use **New + terminal** to create a fresh shell process. Reopening or reconnecting the same terminal does not + refresh its environment. +- For Kandev-managed GitHub checkouts, Local and Worktree preparation follows the host's current + `gh` clone protocol. A user-managed checkout keeps its existing origin. For a managed **Improve Kandev** task, Kandev keeps the task attached to the canonical `kdlbs/kandev` repository. Before the first launch, the workspace automation connection resolves @@ -161,15 +172,6 @@ connection does not need a fork. An App connection without direct write access c automatic personal fork, so managed fork preparation fails closed; the Improve Kandev issue-only option remains available. -- **Inherit executor Git credentials** is the default for newly created workspaces and does not - install Kandev's broker helper or `gh` shim. Local - and Worktree tasks use credentials already visible to the host Git process (including SSH). - Docker, SSH, and cloud tasks use only credentials intentionally configured in that executor. - For Kandev-managed GitHub checkouts, Local and Worktree preparation also updates `origin` to the - host's configured `gh` clone protocol. Selecting SSH therefore lets Git conditional includes that - match `remote.*.url` apply; switching back to managed credentials restores the canonical HTTPS - origin. Repositories you registered from an existing local checkout are never rewritten. - If Git rejects a managed checkout with **detected dubious ownership**, the Kandev service account and the checkout owner do not match. Repository preparation stops and the session error identifies the ownership boundary; inspect the service unit and the managed home/repository owner, then @@ -293,23 +295,6 @@ deletes only the encrypted catalog credential bundle, and does not delete or uni GitHub. Remove the provider-side App separately only after confirming that no other deployment uses it. -### Upgrade and recovery - -Workspaces that existed when workspace authentication was introduced receive a **Legacy shared** connection so upgrades do not immediately lose GitHub access. It preserves the previous installation-wide resolution behavior while the workspace is migrated. Existing workspaces and their saved task-access policies are not rewritten by the new-workspace defaults. After a legacy workspace selects a PAT, named CLI account, or App installation, it cannot return to legacy mode. Copying a workspace never copies authentication or App installation bindings. - -Legacy shared resolution checks an authenticated host `gh` CLI first, then backend `GITHUB_TOKEN`, backend `GH_TOKEN`, and finally the old stored `GITHUB_TOKEN`/`github_token` secret. Those ambient sources are migration compatibility only; configure an explicit workspace connection to make identity and access deterministic. - -For recovery: - -- Replace an invalid PAT or select the exact CLI account again; validation must succeed before Kandev swaps the connection. -- Run `gh auth status --hostname github.com` as the Kandev service user when a selected CLI login disappears, then sign in that account again if necessary. -- Reconnect **My GitHub identity** after authorization expiry/revocation. App automation remains available while the personal connection is invalid. -- Ask an organization owner to unsuspend or reinstall an App, restore its repository selection, or grant a reported missing permission. Refresh the workspace status afterward. -- Disconnect and repeat **Install GitHub App** when the workspace is bound to the wrong installation. Removing the binding does not uninstall the provider-side App. -- To replace compromised App root credentials, disconnect every binding, delete the catalog - registration, rotate the credentials in GitHub, and add the App again. Kandev does not rotate App - private keys, OAuth client secrets, or webhook secrets automatically. - ### Configure and use the workspace diff --git a/docs/public/use-kandev.md b/docs/public/use-kandev.md index 5a02f4450e..7e05a038aa 100644 --- a/docs/public/use-kandev.md +++ b/docs/public/use-kandev.md @@ -196,7 +196,8 @@ See [Sessions and review](sessions-and-review.md) for the workbench and [Tasks a - **Auto Approve**, permission-skipping flags, and unrestricted passthrough remove human gates inside the agent CLI. They are security decisions. - Local and worktree sessions run on the Kandev host. Worktree separation does not limit process, filesystem, network, or credential access. - Containers and remote executors change the boundary, but their mounted files, copied credentials, environment, daemon/socket access, and prepare scripts can reintroduce host or provider access. -- Managed GitHub task access (the default) uses task/repository-bound broker leases from the workspace automation connection. GitHub App tokens are minted for the redeemed repository; PAT and named-CLI bearer tokens retain all provider-granted scopes once delivered to the trusted agent subprocess. Personal tokens and the App private key never enter executors. Choose **Inherit executor Git credentials** in the workspace GitHub settings only when task Git and `gh` should use host-visible credentials for Local/Worktree or intentionally configured credentials for remote executors. +- **Managed GitHub task access** may remain the saved policy for historical workspaces. New workspaces default to **Inherit executor Git credentials**. Managed mode uses task/repository-bound broker leases; stored PATs and App private keys stay out of task processes. +- **Inherit executor Git credentials** uses host-visible credentials for Local and Worktree tasks, or credentials configured in remote executors. See [Choose task Git credentials](integrations.md#choose-task-git-credentials) for the credential paths and entry points. - A profile-supplied `GITHUB_TOKEN` or `GH_TOKEN` is an explicit unmanaged override and bypasses workspace broker selection. Ambient backend tokens and the host-active `gh` account are used only by migration-only **Legacy shared** workspace connections. - Repository, executor, and task action scripts are executable configuration. Review them like code. - Authentication is opt-in. When it is disabled, treat anyone who can reach the backend as an operator. Keep the whole origin on loopback or a trusted network, or put it behind an authenticated TLS proxy. diff --git a/docs/specs/integrations/requirements/github-authentication.md b/docs/specs/integrations/requirements/github-authentication.md index bbb10284e2..31b49fc262 100644 --- a/docs/specs/integrations/requirements/github-authentication.md +++ b/docs/specs/integrations/requirements/github-authentication.md @@ -32,6 +32,8 @@ GitHub credentials must not silently cross workspace boundaries. A local workspa - **AC-INTEGRATIONS-GITHUB-AUTHENTICATION-001.11:** When a Local or Worktree task launches or resumes, the system shall inspect each attached Kandev-managed GitHub checkout before the agent starts. This behavior includes a prepared workspace that the task reuses. - **AC-INTEGRATIONS-GITHUB-AUTHENTICATION-001.12:** The system shall reconcile each managed checkout to the canonical transport for the current task policy. It shall not rewrite an already-canonical origin or a user-managed local checkout. +- **AC-INTEGRATIONS-GITHUB-AUTHENTICATION-001.13:** The public guide shall explain historical managed defaults, preserved upgrade policies, and recovery through explicit task-access selection. It shall distinguish managed checkouts, user-managed checkouts, and remote executors. + ## System design The migrated technical source is split into [part 1](../system-design/github-authentication-01.md), [part 2](../system-design/github-authentication-02.md), [part 3](../system-design/github-authentication-03.md). diff --git a/docs/specs/integrations/system-design/github-authentication-03.md b/docs/specs/integrations/system-design/github-authentication-03.md index a2676fb32b..a91e49972e 100644 --- a/docs/specs/integrations/system-design/github-authentication-03.md +++ b/docs/specs/integrations/system-design/github-authentication-03.md @@ -257,3 +257,21 @@ New-workspace defaults are defined by [ADR-2026-08-02-new-workspace-github-access-defaults](../../../decisions/2026-08-02-new-workspace-github-access-defaults.md). The system-service ownership boundary is defined by [ADR-2026-07-31-system-service-user-continuity](../../../decisions/2026-07-31-system-service-user-continuity.md). + + +## Upgrade recovery guidance + +`AC-INTEGRATIONS-GITHUB-AUTHENTICATION-001.13` uses the existing public integration guide. +The guide distinguishes the historical `managed` schema default from the executor default for new workspaces. +An existing policy does not record whether the user selected it or a migration supplied it. +Recovery therefore uses an explicit task-access selection through the existing workspace connection dialog. +The procedure does not infer consent from an absent App registration or current credential health. +PAT and named CLI connections also support managed task access. + +Local and Worktree launches reconcile Kandev-managed origins through the existing repository preparation path. +User-managed origins remain under user control. Remote executors require credentials in their own execution environment. +The guide must not promise that host `gh auth status` proves task Git access. +The current managed admission gate validates repository identity, not inherited transport authentication. + +The [upgrade recovery fix package](../../../plans/github-credential-upgrade-recovery/plan.md) +owns delivery of this guidance. It changes no runtime or persistence boundary.