4.3 KiB
task-05: Backend GitHub carry-over on Improve Kandev workspace creation
Spec: docs/specs/improve-kandev/spec.md — "Workspace creation semantics"
Plan: docs/plans/improve-kandev-workspace/plan.md — Phase 2, Wave 5.
Depends on: task-04.
Goal
When bootstrap creates the Improve Kandev workspace for the first time
only, copy the GitHub workspace connection (and its PAT secret where
applicable) from the user's default workspace. Copy nothing else: no other
integration configs, no automations, no extra workflows/repos.
Target
apps/backend/internal/github/service_connections.go(or a newcopy_connection.go) — newCopyWorkspaceConnectionToWorkspace.apps/backend/internal/github/store.go— any needed read/write helper.apps/backend/internal/improvekandev/handler.go— creation-path hook.apps/backend/internal/backendapp— wire the copier + default-workspace resolver into the improvekandev handler.
Change
- GitHub service: add
CopyWorkspaceConnectionToWorkspace(ctx, srcWorkspaceID, dstWorkspaceID) error:- Read the source
github_workspace_connectionsrow; if none, return nil (no-op). - For
patsources: also copy the PAT secret (stored under the workspace-scoped secret keyWorkspacePATSecretKey(src)→ write underWorkspacePATSecretKey(dst)); increment/recompute nothing — the copied row keeps itscredential_generation/status as-is. - For
gh_clisources: the CLI account is host-global; copy the row (source/login/host) without a secret. - For app-installation sources: copy the row (installation id/account/app registration reference).
- Upsert into
github_workspace_connectionsfor the destination (ON CONFLICT(workspace_id) — same asSetWorkspaceConnection). - Use the store's transaction surface if one exists; keep it best-effort: a copy failure must not fail bootstrap (log + continue) — decide and document.
- Read the source
- Default workspace resolution: reuse
integrations/workspacescope.DefaultResolver.Resolve(ctx)(active workspace in user settings → first by created_at → literaldefault). Wire it inbackendappwhere the improvekandev handler is constructed. - Improve handler: add a small interface to the handler (mirroring the
Clonerpattern), e.g.GitHubWorkspaceCopier interface { CopyWorkspaceConnectionToWorkspace(ctx, src, dst string) error }, and aDefaultWorkspaceResolver func(ctx) (string, error)(or interface). InensureImproveWorkspace, after a successful create (miss path only), resolve the default workspace and copy the GitHub connection into the new workspace. The reuse path must NOT copy. NewHandlersignature grows by the copier + resolver; updatecmd/kandevwiring and the test constructors (handler_test.go,internal/integration/improve_kandev_test.go) with fakes.
Acceptance
- Unit test (
internal/github): copying apatconnection duplicates the row and the secret under the destination key;gh_cli/app rows copy without a secret; no source row → nil. - Integration test: bootstrap on a fresh DB where the default workspace has a GitHub connection (seed via the github service or store) → the new Improve Kandev workspace has the same connection; a second bootstrap does not change it. Bootstrap with no source connection → no connection row.
- Existing improve-kandev integration tests stay green (constructors updated with fakes).
go test -tags fts5 ./internal/github/... ./internal/improvekandev/... ./internal/integration/...andgolangci-lint run ./...pass.
Results
Shipped in 37597867d (PR #2347). github.Service.CopyWorkspaceConnectionToWorkspace
copies the default workspace's GitHub connection row + PAT secret at workspace
creation only; gh_cli/app rows without secrets are copied as rows.
Wired via improvekandev.GitHubWorkspaceCopier / DefaultWorkspaceResolver
(uses workspacescope.ResolveMigrationTarget); dbPool threaded through
buildHTTPServer + routeParams. Best-effort — failures are logged and never
fail bootstrap. Verified by integration tests and on the ubu4 demo instance
(workspace 0dfe5db8-... received the Default workspace's mock GitHub
connection; re-seed needed after restart since mock connections are in-memory:
PUT /api/v1/github/mock/workspace-connections/<ws-id>).