Files
kandev/docs/specs/integrations/system-design/github-authentication-03.md
T
2026-08-24 11:09:03 +00:00

249 lines
18 KiB
Markdown

---
status: draft
system: integrations
requirements:
- REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-001
created: 2026-07-19
owners:
- Kandev
---
# Workspace GitHub Authentication System Design Part 3
## Purpose and boundaries
This design preserves the technical source detail for `REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-001` during migration.
## Requirement mapping
| Requirement | Design section |
| --- | --- |
| `REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-001` | [Migrated source detail](#migrated-source-detail) |
## Migrated source detail
## Scenarios
- **GIVEN** a brand-new Kandev database and an authenticated active host `gh` account, **WHEN** the
initial workspace is seeded, **THEN** its automation connection records that exact CLI
host/login, its task access is executor inheritance, and its first task does not request a
managed credential lease.
- **GIVEN** an administrator or internal trusted caller and an authenticated active host `gh`
account, **WHEN** a workspace is created, **THEN** the workspace records that exact named CLI
automation connection and executor task access.
- **GIVEN** a non-admin member and an authenticated server-operator `gh` account, **WHEN** the
member creates a workspace, **THEN** the workspace has executor task access but no automatic
GitHub automation connection.
- **GIVEN** no usable authenticated host `gh` account, **WHEN** an authorized caller creates a
workspace, **THEN** workspace creation succeeds, task access is executor inheritance, and
GitHub automation remains disconnected.
- **GIVEN** an existing installation with managed, disconnected, or legacy missing workspace
settings, **WHEN** Kandev upgrades, **THEN** those connections and task policies remain
unchanged.
- **GIVEN** a workspace GitHub status is visible, **WHEN** the user refreshes it and the status
request is still pending, **THEN** the existing workspace content remains visible and usable
while the refresh control is busy, on both desktop and mobile.
- **GIVEN** the user navigates to a workspace with no loaded GitHub status, **WHEN** its initial
status request is pending, **THEN** the UI shows the connection-status placeholder and no status
from the previous workspace.
- **GIVEN** two workspaces, **WHEN** each selects a different App registration and installation,
**THEN** status, tokens, webhooks, repositories, actors, and revocation remain isolated.
- **GIVEN** two workspaces intentionally reuse one registration, **WHEN** each installs it into a
different account, **THEN** each workspace receives only its own installation and repository
scope while the UI identifies the shared root App identity.
- **GIVEN** a private managed App, **WHEN** creation completes, **THEN** the UI says it is installable
only on its owner and does not imply Marketplace publication.
- **GIVEN** a user chooses public, **WHEN** the manifest is submitted, **THEN** `public: true` is sent
and the confirmation explains that installation approval still controls repository access.
- **GIVEN** a correctly configured existing App, **WHEN** the import is verified, **THEN** it appears
in the workspace chooser without becoming the active connection until installation succeeds.
- **GIVEN** an imported App misses a required GitHub setting, **WHEN** validation or installation
runs, **THEN** the guide identifies the exact setting without returning submitted secrets.
- **GIVEN** App creation, import, or installation is canceled, **WHEN** the user returns, **THEN** the
previous workspace automation connection remains active.
- **GIVEN** an App workspace with personal OAuth, **WHEN** it switches registration or to PAT/CLI,
**THEN** the incompatible personal connection is removed and its old tokens cannot be resolved.
- **GIVEN** a webhook for registration A, **WHEN** it is sent to registration B's route or signature,
**THEN** no delivery or workspace state is mutated.
- **GIVEN** a PAT or named CLI workspace, **WHEN** an agent uses the managed credential helper,
**THEN** it receives that workspace's automation token and the UI does not promise provider-side
repository narrowing.
- **GIVEN** a named CLI workspace in managed mode, **WHEN** a task launches, **THEN** Kandev resolves
the selected host/login, makes both managed `git` and `gh` available in standalone and remote
runtimes, and does not depend on the host's currently active CLI account.
- **GIVEN** an authorized user opens a terminal, uses a passthrough-agent PTY, or starts a
task-scoped command in a managed task, **WHEN** it accesses an attached GitHub repository,
**THEN** it receives the same task-scoped broker helper and `gh` shim environment as the agent
subprocess.
- **GIVEN** an unauthorised user or a terminal for another task environment, **WHEN** it attempts to
open a terminal or start a process, **THEN** it cannot receive the managed task Git environment.
- **GIVEN** a workspace selects executor inheritance, **WHEN** a Local/Worktree or remote task
launches, **THEN** Kandev injects no broker helper/shim and the task uses host-visible or
executor-configured credentials respectively.
- **GIVEN** a configured workspace, **WHEN** the user views Workspace GitHub access, **THEN** one
compact summary identifies both the workspace automation identity and the effective task access
mode without rendering a separate Task Git credentials settings section.
- **GIVEN** a PAT or named CLI workspace, **WHEN** the user views Workspace GitHub access, **THEN**
the page states that the same account powers My GitHub and user-triggered actions without
rendering a separate My GitHub identity section, and accessible help explains both the workspace
identity and task-access summary.
- **GIVEN** a workspace status with GitHub rate-limit snapshots, **WHEN** the user hovers, focuses,
or taps **Show GitHub API limits**, **THEN** the disclosure shows the remaining and total API,
GraphQL query, and Search quotas with reset timing for that workspace connection.
- **GIVEN** a PAT or named CLI connection draft and a changed task access mode, **WHEN** the user
presses the dialog's single **Save changes** action, **THEN** both drafts are persisted, the dialog
closes only after both succeed, and reopening shows the selected account and task mode.
- **GIVEN** a user enters an invalid replacement PAT, **WHEN** GitHub rejects it during **Save
changes**, **THEN** the dialog remains open, the submitted PAT remains available for correction,
an error is shown, and the previously active workspace connection is unchanged.
- **GIVEN** a configured PAT has expired or been revoked, **WHEN** the user opens My GitHub and the
provider data request returns 401, **THEN** the page remains on `/github`, shows an authentication
loading error, and does not navigate to the Kandev login screen.
- **GIVEN** a changed task access mode but no PAT or CLI connection change, **WHEN** the user presses
**Save changes**, **THEN** only the task policy is persisted and the selected automation identity
remains unchanged.
- **GIVEN** managed task access, **WHEN** the user hovers, focuses, or taps the Task Git access help,
**THEN** it explains that Git calls Kandev's `agentctl` credential helper for attached GitHub
HTTPS repositories, the helper redeems a scoped broker lease on demand, `gh` uses a broker-aware
shim, and credentials are not written into the repository.
- **GIVEN** the host `gh` clone protocol is SSH and a Kandev-managed GitHub checkout currently has
an HTTPS `origin`, **WHEN** the workspace selects executor inheritance and launches a Local or
Worktree task, **THEN** Kandev changes that managed checkout's `origin` to the canonical SSH URL
before task preparation so matching Git conditional includes apply.
- **GIVEN** a Kandev-managed GitHub checkout currently has an SSH `origin`, **WHEN** the workspace
selects managed credentials and launches a Local or Worktree task, **THEN** Kandev changes that
managed checkout's `origin` to canonical HTTPS before task preparation.
- **GIVEN** a Kandev-managed checkout already has the canonical origin selected by the task policy,
**WHEN** a task launches or resumes, **THEN** Kandev inspects the origin but does not rewrite
`.git/config`.
- **GIVEN** a task with one or more attached repositories, **WHEN** launch or resume builds the
primary, multi-repository, and credential configuration, **THEN** each repository is prepared
once and the same resolved result is reused by all three consumers.
- **GIVEN** a managed checkout is owned by `brewuser` while the Kandev service runs as root,
**WHEN** Git rejects origin inspection or reconciliation as dubious ownership, **THEN** task
preparation stops and reports that the service account and managed repository owner disagree,
without suggesting `safe.directory=*`.
- **GIVEN** Git emits a failure containing credential-bearing URL userinfo, **WHEN** the failure is
returned through task preparation, **THEN** the diagnostic retains actionable Git context but
redacts the credential and bounds the output length.
- **GIVEN** a repository is registered from a user-managed local checkout, **WHEN** either task Git
credential policy is selected, **THEN** Kandev leaves its configured `origin` unchanged.
- **GIVEN** managed mode and an explicit executor-profile GitHub token, **WHEN** a task launches,
**THEN** the profile token wins and the session disclosure labels its actor runtime-selected.
- **GIVEN** managed mode and an explicit executor-profile `GITHUB_TOKEN` or `GH_TOKEN`, **WHEN** an
attached repository has incomplete managed identity, **THEN** the profile token remains the
effective source and managed broker admission does not reject the task.
- **GIVEN** a managed repository remote with an SSH password, query, or fragment, **WHEN** Kandev
resolves its credential identity, **THEN** resolution fails without exposing the remote and no
task, workflow, or session state changes.
- **GIVEN** a provider-backed repository whose only usable identity is a local checkout origin,
**WHEN** a managed task launches or the broker authorizes a request, **THEN** both paths reject
the incomplete persisted identity before session state changes.
- **GIVEN** task Git credential policy resolution fails, **WHEN** a normal or Office task launches
or resumes, **THEN** Kandev returns the error and does not create, rebind, or resume a session.
- **GIVEN** a workflow transition selects an agent profile that cannot use managed credentials,
**WHEN** the source step exits, **THEN** Kandev keeps the source step and current session and does
not route the destination step prompt.
- **GIVEN** a managed helper cannot execute or redeem its lease, **WHEN** Git requests GitHub HTTPS
credentials, **THEN** the command fails without falling through to a personal helper or prompt.
- **GIVEN** a broker-enabled managed task whose login profile replaces its inherited `PATH`,
**WHEN** Git requests GitHub HTTPS credentials, **THEN** the configured helper invokes the
instance-owned `agentctl` directly and does not search or fall through to an ambient helper.
- **GIVEN** a broker-enabled Local or Worktree task whose checkout or setup script invokes Git
before the task instance is created, **WHEN** Git requests GitHub HTTPS credentials, **THEN** the
configured helper invokes the standalone launcher's absolute `agentctl` executable without
consulting `PATH` or an ambient helper.
- **GIVEN** a broker-enabled Docker or Sprites task whose prepare script clones before `agentctl`
starts, **WHEN** Git requests GitHub HTTPS credentials during that clone, **THEN** the configured
helper invokes the already-installed absolute executor binary and redeems the task lease without
consulting `PATH` or an ambient helper.
- **GIVEN** a broker-enabled managed task with an existing Bash environment hook, **WHEN** a
non-interactive login shell replaces `PATH`, **THEN** the existing hook still runs and the
Kandev-managed `agentctl` and `gh` shims are restored ahead of ambient tools before the requested
command starts.
- **GIVEN** that existing Bash environment hook is expressed as `$HOME/hook.sh` or
`${KANDEV_HOOK_ROOT}/hook.sh`, **WHEN** Kandev composes its managed startup fragment, **THEN** it
resolves the reference from the effective child environment and sources the intended hook rather
than a filename containing literal dollar-sign text.
- **GIVEN** the host or executor exports indexed Git config for `core.hooksPath` and
`notes.augment.mergeStrategy`, **WHEN** Kandev appends its managed GitHub helper configuration,
**THEN** the agent receives one contiguous block containing the original entries first and the
Kandev entries afterward, and a real Git commit still runs the configured hook.
- **GIVEN** Docker or a remote control process already contains the same task Git config suffix,
**WHEN** that suffix is forwarded again while creating or configuring an agent instance,
**THEN** Kandev emits it once while retaining executor-added `safe.directory` and URL rewrites.
- **GIVEN** a workspace policy or automation connection changes after launch, **WHEN** the user
views the running session, **THEN** the Changes disclosure still shows its launch snapshot; a
successful resume records and shows the newly resolved contract.
- **GIVEN** an authenticated host GitHub CLI without structured status or named-token flags,
**WHEN** an operator selects its sole account and `gh auth status` reports successfully on
stderr, **THEN** Kandev discovers and validates that account without requiring a CLI upgrade.
- **GIVEN** a valid migrated `legacy_shared` connection and a legacy shared managed checkout,
**WHEN** a task needs a workspace-isolated checkout, **THEN** Kandev resolves the same automation
identity's Git credential and clones into that workspace's managed root without persisting or
exposing the token.
- **GIVEN** desktop and mobile viewports, **WHEN** users complete every App flow, **THEN** actions and
disclosures remain usable without clipping, overlap, or desktop-only capability.
- **GIVEN** a mobile coarse-pointer viewport, **WHEN** the user opens Change GitHub connection,
**THEN** the task access controls share the existing full-height drawer's single scroll owner,
remain touch reachable, clear the safe area, and introduce no horizontal overflow.
- **GIVEN** desktop fine-pointer and mobile coarse-pointer task views, **WHEN** the branch
disclosure is opened, **THEN** both show the same credential policy, method, actor truth, and
transport without horizontal overflow.
## Success Criteria
- No runtime, callback, webhook, cache, broker, or status path resolves a GitHub App without both
workspace and registration identity where workspace ownership is required.
- A seeded E2E run proves different Apps for work/personal workspaces and intentional App reuse.
- Secret scans find no PAT, private key, client secret, webhook secret, personal token, refresh
token, or live installation token in logs, API snapshots, redirects, process arguments, or
executor environments.
- Standalone, container, and remote task tests prove the managed helper is discoverable only for
broker-enabled instances and their authorized task terminals/processes, while executor
inheritance receives no Kandev GitHub helper/shim.
- A real Git subprocess test proves that host/executor indexed hooks and notes config survive
managed credential injection, and focused tests prove ordered composition and overlap handling
across standalone, container, and remote launch shapes.
## Out Of Scope
- Multiple automation connections or per-repository credential routing inside one workspace.
- Automatically editing an imported App's GitHub settings or uninstalling an App on disconnect.
- Automatic private-key/client-secret rotation; users replace an unbound stored registration or
import the replacement App credentials through the guided flow.
- GitHub Enterprise Server, enterprise-owned Apps, or hosts other than `github.com`.
- Kandev multi-user login, workspace membership, or RBAC implementation.
- Publishing Apps to GitHub Marketplace.
- Discovering or verifying the actor behind inherited credential managers, SSH agents, or explicit
profile tokens.
- Preventing a host-authority agent from manually selecting another Git transport outside
Kandev-injected managed HTTPS and `gh` commands.
## Implementation Plan
See [the original authentication implementation plan](../../../plans/github-authentication/plan.md)
and the
[task Git credential policy follow-up plan](../../../plans/task-git-credential-policy/plan.md), plus
the
[executor clone transport repair plan](../../../plans/github-executor-clone-transport/plan.md), and
the [managed task terminal environment plan](../../../plans/task-terminal-git-environment/plan.md),
and the
[managed GitHub login-shell repair plan](../../../plans/github-managed-tools-login-shell/plan.md),
and the
[system-service identity guardrails repair plan](../../../plans/system-service-identity-guardrails/plan.md).
The new-workspace default repair is tracked in
[the new workspace GitHub access defaults plan](../../../plans/new-workspace-github-access-defaults/plan.md).
Managed credential admission and repository identity corrections are tracked in
[the managed Git credential admission repair plan](../../../plans/managed-git-credential-admission-repair/plan.md).
## Decision
See [ADR-2026-07-21-workspace-selectable-github-app-registrations](../../../decisions/2026-07-21-workspace-selectable-github-app-registrations.md)
and
[ADR-2026-07-27-task-git-credential-policy](../../../decisions/2026-07-27-task-git-credential-policy.md).
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).