193 lines
11 KiB
Markdown
193 lines
11 KiB
Markdown
---
|
|
spec: docs/specs/integrations/requirements/github-authentication.md
|
|
created: 2026-08-02
|
|
status: completed
|
|
---
|
|
|
|
# Implementation Plan: New Workspace GitHub Access Defaults
|
|
|
|
## Overview
|
|
|
|
The confirmed root cause is that `github_workspace_settings` resolves a missing task policy to
|
|
`managed`, while a new workspace has no `github_workspace_connections` row. Task launch therefore
|
|
requests a broker lease that fails with `ErrGitHubNotConfigured` before the agent starts. The fix
|
|
will persist executor task access for each new workspace, optionally snapshot an operator-authorized
|
|
active host `gh` account as a named CLI connection, and leave every existing installation unchanged.
|
|
|
|
The implementation begins with failing backend and browser regressions, then adds the smallest
|
|
workspace-initialization seam and GitHub persistence behavior required to make them pass. Public
|
|
documentation follows after the behavior is green.
|
|
|
|
---
|
|
|
|
## Backend
|
|
|
|
### GitHub workspace default initializer
|
|
|
|
- Add a focused workspace-default initialization path under
|
|
`apps/backend/internal/github/` (prefer a new `workspace_defaults.go` with sibling tests rather
|
|
than growing `service_connections.go`).
|
|
- Persist `TaskGitCredentialsModeExecutor` for a workspace created after this feature is active.
|
|
Keep `defaultWorkspaceSettings`, `normalizeTaskGitCredentialsMode`, existing schema defaults, and
|
|
upgrade fallbacks on `managed`; those are the backward-compatibility path for existing missing or
|
|
invalid state.
|
|
- Discover the currently active account through the service's injectable CLI account source. Only
|
|
an internal caller, synthetic administrator, or real administrator may receive the host account;
|
|
reuse the existing `requireGHCLIOperator` boundary for member denial.
|
|
- Validate and store the exact `github.com` host/login as a `gh_cli` connection without persisting a
|
|
bearer token. No active/valid CLI account is a soft condition: executor settings are still saved
|
|
and workspace creation succeeds disconnected.
|
|
- Record whether the GitHub schema belongs to a brand-new database before `NewStore` initializes
|
|
its tables. Expose a one-shot startup method that initializes the already-seeded default
|
|
workspace only in that fresh-database case. Existing databases, including workspaces with no
|
|
settings row, are not backfilled or rebound.
|
|
|
|
### Workspace creation seam
|
|
|
|
- Add a narrow `WorkspaceDefaultsInitializer` interface and setter in
|
|
`apps/backend/internal/task/service/service.go`.
|
|
- Call it in `CreateWorkspace` after the workspace transaction succeeds and before
|
|
`workspace.created` is published, so an immediately created task observes executor mode rather
|
|
than racing an event subscriber. The initializer owns optional-CLI degradation; a returned
|
|
persistence error is logged as a workspace-default initialization failure.
|
|
- Wire the GitHub service into this seam in `apps/backend/internal/backendapp/services.go` after
|
|
workspace authorization and connection-secret infrastructure are installed. Invoke the
|
|
fresh-database bootstrap at the same composition point for the repository-seeded initial
|
|
workspace.
|
|
- Do not use a `workspace.created` subscription as the correctness boundary: the NATS-backed bus
|
|
need not finish a subscriber before the create request can be followed by task launch.
|
|
|
|
### Upgrade and security boundaries
|
|
|
|
- Do not modify existing `github_workspace_connections` or
|
|
`github_workspace_settings.task_git_credentials_mode` rows.
|
|
- Do not change the current `managed` normalization for legacy missing/invalid values.
|
|
- Do not auto-bind host `gh` for a non-admin member context.
|
|
- Do not copy or persist the resolved CLI token, and do not follow later host active-account
|
|
changes for an already-created workspace.
|
|
|
|
---
|
|
|
|
## Frontend
|
|
|
|
No React component, route, API client, state slice, copy, or responsive composition changes are
|
|
required. The existing Workspace GitHub access summary and connection dialog already render the
|
|
backend's saved `executor` and `gh_cli` values.
|
|
|
|
### Mobile parity contract
|
|
|
|
The nearest shipped mobile exemplar remains
|
|
`apps/web/e2e/tests/integrations/mobile-github-workspace-settings.spec.ts`: the existing full-height,
|
|
single-scroll-owner connection drawer and 44px task-access controls are unchanged. Update that
|
|
scenario to prove the initial summary reads **Inherit executor Git credentials**. Because this is a
|
|
persisted backend-default change with no layout, navigation, scroll, touch, or composition change,
|
|
the focused existing mobile scenario satisfies mobile parity without a new mobile surface.
|
|
|
|
---
|
|
|
|
## Tests
|
|
|
|
- **What:** a new workspace always receives persisted executor task access; an internal/admin
|
|
creator with a valid active CLI account also receives an exact named CLI connection.
|
|
**File:** `apps/backend/internal/github/workspace_defaults_test.go`.
|
|
**How:** SQLite-backed service tests with injectable CLI account/token validation boundaries.
|
|
- **What:** member creation never receives the server operator's CLI identity; unavailable,
|
|
unauthenticated, or invalid CLI discovery degrades to disconnected automation without losing
|
|
executor task access.
|
|
**File:** `apps/backend/internal/github/workspace_defaults_test.go`.
|
|
**How:** table-driven service tests using real store reads and synthetic/admin/member contexts.
|
|
- **What:** a database with pre-existing GitHub schema/settings is not treated as fresh and its
|
|
missing or managed behavior is not rewritten, while a genuinely fresh schema initializes the
|
|
seeded workspace once.
|
|
**Files:** `apps/backend/internal/github/workspace_defaults_test.go`,
|
|
`apps/backend/internal/github/workspace_settings_test.go`.
|
|
**How:** fresh and replayed SQLite store setup with row-level assertions.
|
|
- **What:** task-service workspace creation runs default initialization before publishing the
|
|
created event.
|
|
**File:** `apps/backend/internal/task/service/service_resources_test.go`.
|
|
**How:** a recording initializer and event bus assert call order and error handling.
|
|
- **What:** backend composition wires runtime workspace creation and fresh-install startup to the
|
|
GitHub initializer.
|
|
**File:** `apps/backend/internal/backendapp/services_github_defaults_test.go` (or the nearest
|
|
existing service-composition test if a smaller harness is available during RED).
|
|
**How:** real SQLite repositories with injected GitHub account resolution and stored-state
|
|
assertions.
|
|
- **What:** executor policy skips broker lease injection.
|
|
**File:** `apps/backend/internal/orchestrator/executor/executor_credentials_test.go`.
|
|
**How:** retain the existing `executor inheritance` regression as downstream contract evidence;
|
|
add no duplicate test unless the new integration test cannot prove the no-lease outcome.
|
|
|
|
Targeted backend verification:
|
|
|
|
```bash
|
|
cd apps/backend && go test -tags fts5 ./internal/github ./internal/task/service ./internal/backendapp ./internal/orchestrator/executor -run 'Test.*Workspace.*Defaults|Test.*Workspace.*Initializ|TestTaskGitCredentialModeDefaultsManaged|TestApplyGitCredentialSnapshotUsesExecutorSources' -count=1
|
|
```
|
|
|
|
## E2E Tests
|
|
|
|
- **Scenario:** GIVEN a new workspace and an active mock CLI account, WHEN an administrator creates
|
|
the workspace and opens Workspace GitHub access, THEN the UI shows that exact CLI automation
|
|
identity and **Inherit executor Git credentials**.
|
|
**File:** `apps/web/e2e/tests/integrations/github-authentication.spec.ts`.
|
|
**What to verify:** automation source/login and task-access summary through the rendered settings
|
|
page, with backend seeding only for the CLI-account precondition.
|
|
- **Scenario:** GIVEN the initial fresh E2E workspace, WHEN desktop and mobile users open Workspace
|
|
GitHub access, THEN the existing summary and dialog/drawer show executor inheritance as the
|
|
initial task policy.
|
|
**Files:** `apps/web/e2e/tests/integrations/github-workspace-settings.spec.ts`,
|
|
`apps/web/e2e/tests/integrations/mobile-github-workspace-settings.spec.ts`.
|
|
**What to verify:** desktop and mobile report the same saved policy; existing mobile geometry,
|
|
scroll ownership, safe-area containment, and touch targets remain green.
|
|
|
|
Targeted browser verification after the fresh-worktree install:
|
|
|
|
```bash
|
|
cd apps && pnpm install --frozen-lockfile
|
|
cd apps && pnpm --filter @kandev/web run e2e:run -- tests/integrations/github-authentication.spec.ts tests/integrations/github-workspace-settings.spec.ts
|
|
cd apps && pnpm --filter @kandev/web run e2e:run -- --project mobile-chrome tests/integrations/mobile-github-workspace-settings.spec.ts
|
|
```
|
|
|
|
---
|
|
|
|
## Public Documentation
|
|
|
|
Update `docs/public/integrations.md` so **Inherit executor Git credentials** is documented as the
|
|
new-workspace default, managed credentials are described as an opt-in workspace policy, active host
|
|
`gh` auto-binding is limited to operator-authorized creation, remote executors remain responsible
|
|
for their own credentials, and upgrades are unchanged.
|
|
|
|
Validate with:
|
|
|
|
```bash
|
|
node --test scripts/validate-public-docs.test.mjs
|
|
node scripts/validate-public-docs.mjs
|
|
```
|
|
|
|
---
|
|
|
|
## Verification Results
|
|
|
|
- `cd apps/backend && go test -tags fts5 ./internal/github ./internal/task/service ./internal/backendapp ./internal/orchestrator/executor -run 'Test.*Workspace.*Defaults|Test.*Workspace.*Initializ|TestTaskGitCredentialModeDefaultsManaged|TestApplyGitCredentialSnapshotUsesExecutorSources' -count=1` — 12 passed in 4 packages.
|
|
- `cd apps/backend && go test -tags fts5 ./internal/github ./internal/task/service ./internal/backendapp ./internal/orchestrator/executor -count=1` — 2402 passed in 4 packages.
|
|
- `cd apps && pnpm --filter @kandev/web run e2e:run -- tests/integrations/github-authentication.spec.ts tests/integrations/github-workspace-settings.spec.ts` — 9 passed.
|
|
- `cd apps && pnpm --filter @kandev/web run e2e:run -- --project mobile-chrome tests/integrations/mobile-github-workspace-settings.spec.ts` — 2 passed.
|
|
- `cd apps/backend && make lint` — 0 issues.
|
|
- `cd apps && pnpm --filter @kandev/web run typecheck` — passed.
|
|
- `cd apps && pnpm --filter @kandev/web run lint` — passed.
|
|
- `cd apps && pnpm --filter @kandev/web run i18n:check && pnpm --filter @kandev/web run i18n:ratchet` — passed.
|
|
- `node --test scripts/validate-public-docs.test.mjs` — 58 passed.
|
|
- `node scripts/validate-public-docs.mjs` — 41 published docs pages validated.
|
|
- `cd apps && pnpm run format:check` and `git diff --check` — passed.
|
|
|
|
---
|
|
|
|
## Implementation Waves And Parallel Candidates
|
|
|
|
Execution is sequential in the primary conversation; no task is marked parallel-safe because the
|
|
RED tests define the contracts consumed by the backend implementation and documentation must match
|
|
the final green behavior.
|
|
|
|
- [x] [Task 01: Add failing default-behavior regressions](task-01-default-behavior-regressions.md)
|
|
- [x] [Task 02: Implement workspace GitHub defaults](task-02-workspace-github-defaults.md)
|
|
- [x] [Task 03: Update public integration documentation](task-03-public-integration-documentation.md)
|