249 lines
18 KiB
Markdown
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).
|