From 924ac6dd35dc491115a61191ff3070c814d49780 Mon Sep 17 00:00:00 2001 From: skulidropek <66840575+skulidropek@users.noreply.github.com> Date: Wed, 18 Feb 2026 08:08:14 +0000 Subject: [PATCH 01/15] feat(auth): multi-profile .orch auth + GH OAuth TUI + state auto-sync (#61) --- AGENTS.md | 6 +- README.md | 11 +- package.json | 4 + .../app/src/docker-git/cli/parser-auth.ts | 24 +- .../docker-git/cli/parser-mcp-playwright.ts | 1 - packages/app/src/docker-git/cli/parser.ts | 2 +- packages/app/src/docker-git/cli/usage.ts | 4 +- packages/app/src/docker-git/menu-actions.ts | 49 ++- packages/app/src/docker-git/menu-auth-data.ts | 179 ++++++++++ packages/app/src/docker-git/menu-auth.ts | 312 +++++++++++++++++ .../app/src/docker-git/menu-buffer-input.ts | 18 + packages/app/src/docker-git/menu-create.ts | 16 +- .../app/src/docker-git/menu-input-handler.ts | 132 +++++-- .../app/src/docker-git/menu-input-utils.ts | 85 +++++ .../app/src/docker-git/menu-labeled-env.ts | 37 ++ .../src/docker-git/menu-project-auth-data.ts | 252 ++++++++++++++ .../app/src/docker-git/menu-project-auth.ts | 271 +++++++++++++++ .../app/src/docker-git/menu-render-auth.ts | 54 +++ .../app/src/docker-git/menu-render-common.ts | 67 ++++ .../app/src/docker-git/menu-render-layout.ts | 30 ++ .../docker-git/menu-render-project-auth.ts | 69 ++++ .../app/src/docker-git/menu-render-select.ts | 12 +- packages/app/src/docker-git/menu-render.ts | 34 +- .../app/src/docker-git/menu-select-load.ts | 2 +- packages/app/src/docker-git/menu-select.ts | 55 ++- packages/app/src/docker-git/menu-shared.ts | 88 +++-- packages/app/src/docker-git/menu-types.ts | 69 +++- packages/app/src/docker-git/menu.ts | 27 +- packages/docker-git/src/server/claude.ts | 111 ++++++ packages/docker-git/src/server/core/domain.ts | 27 +- .../docker-git/src/server/git-credentials.ts | 131 +++++++ packages/docker-git/src/server/github.ts | 28 +- packages/docker-git/src/server/http.ts | 323 ++++++++++++++---- packages/docker-git/src/server/labeled-env.ts | 121 +++++++ packages/docker-git/src/server/view.ts | 202 ++++++----- .../docker-git/tests/core/templates.test.ts | 4 + .../docker-git/tests/server/claude.test.ts | 56 +++ .../docker-git/tests/server/domain.test.ts | 12 +- .../tests/server/git-credentials.test.ts | 63 ++++ packages/lib/src/core/command-builders.ts | 16 +- packages/lib/src/core/menu.ts | 23 +- .../lib/src/usecases/actions/prepare-files.ts | 6 +- packages/lib/src/usecases/auth-codex.ts | 9 +- packages/lib/src/usecases/auth-github.ts | 23 +- packages/lib/src/usecases/env-file.ts | 25 ++ .../src/usecases/state-repo/github-auth.ts | 24 +- packages/lib/tests/core/menu.test.ts | 34 ++ scripts/e2e/_lib.sh | 74 ++++ scripts/e2e/clone-cache.sh | 18 +- scripts/e2e/login-context.sh | 40 +-- scripts/e2e/opencode-autoconnect.sh | 68 ++-- scripts/e2e/run-all.sh | 23 ++ 52 files changed, 2949 insertions(+), 422 deletions(-) create mode 100644 packages/app/src/docker-git/menu-auth-data.ts create mode 100644 packages/app/src/docker-git/menu-auth.ts create mode 100644 packages/app/src/docker-git/menu-buffer-input.ts create mode 100644 packages/app/src/docker-git/menu-input-utils.ts create mode 100644 packages/app/src/docker-git/menu-labeled-env.ts create mode 100644 packages/app/src/docker-git/menu-project-auth-data.ts create mode 100644 packages/app/src/docker-git/menu-project-auth.ts create mode 100644 packages/app/src/docker-git/menu-render-auth.ts create mode 100644 packages/app/src/docker-git/menu-render-common.ts create mode 100644 packages/app/src/docker-git/menu-render-layout.ts create mode 100644 packages/app/src/docker-git/menu-render-project-auth.ts create mode 100644 packages/docker-git/src/server/claude.ts create mode 100644 packages/docker-git/src/server/git-credentials.ts create mode 100644 packages/docker-git/src/server/labeled-env.ts create mode 100644 packages/docker-git/tests/server/claude.test.ts create mode 100644 packages/docker-git/tests/server/git-credentials.test.ts create mode 100644 packages/lib/tests/core/menu.test.ts create mode 100644 scripts/e2e/_lib.sh create mode 100755 scripts/e2e/run-all.sh diff --git a/AGENTS.md b/AGENTS.md index 4b74344f..71f7e871 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -375,9 +375,9 @@ describe("Message invariants", () => { ПРИНЦИП: Сначала формализуем, потом программируем. -Issue workspace: #39 -Issue URL: https://github.com/ProverCoderAI/docker-git/issues/39 -Workspace path: /home/dev/provercoderai/docker-git/issue-39 +Issue workspace: #61 +Issue URL: https://github.com/ProverCoderAI/docker-git/issues/61 +Workspace path: /home/dev/provercoderai/docker-git/issue-61 Работай только над этим issue, если пользователь не попросил другое. Если нужен первоисточник требований, открой Issue URL. diff --git a/README.md b/README.md index 9ed4a275..372defa1 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,10 @@ Structure (simplified): authorized_keys .orch/ env/ - global.env + global.env # shared tokens/keys (GitHub, Git, Claude) with labels auth/ - codex/ # shared Codex auth cache (credentials) - gh/ # shared GitHub auth (optional) + codex/ # shared Codex auth/config (when CODEX_SHARE_AUTH=1) + gh/ # GH CLI auth cache for OAuth login container // docker-compose.yml Dockerfile @@ -70,7 +70,6 @@ Structure (simplified): docker-git.json .orch/ env/ - global.env # copied/synced from root .orch/env/global.env project.env # per-project env knobs (see below) auth/ codex/ # project-local Codex state (sessions/logs/tmp/etc) @@ -79,7 +78,7 @@ Structure (simplified): ## Codex Auth: Shared Credentials, Per-Project Sessions Default behavior: -- Shared credentials live in `/home/dev/.codex-shared/auth.json` (mounted from projects root). +- Shared credentials live in `/home/dev/.codex-shared/auth.json` (mounted from `/.orch/auth/codex`). - Each project keeps its own Codex state under `/home/dev/.codex/` (mounted from project `.orch/auth/codex`). - The entrypoint links `/home/dev/.codex/auth.json -> /home/dev/.codex-shared/auth.json`. @@ -160,7 +159,7 @@ Clone auth error (`Invalid username or token`): ```bash pnpm run docker-git auth github status pnpm run docker-git auth github logout - pnpm run docker-git auth github login --token '' + pnpm run docker-git auth github login --web pnpm run docker-git auth github status ``` - Token requirements: diff --git a/package.json b/package.json index f365c6f4..60a00d95 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,10 @@ "changeset-version": "changeset version", "clone": "pnpm --filter ./packages/app build && node packages/app/dist/main.js clone", "docker-git": "pnpm --filter ./packages/app build:docker-git && node packages/app/dist/src/docker-git/main.js", + "e2e": "bash scripts/e2e/run-all.sh", + "e2e:clone-cache": "bash scripts/e2e/clone-cache.sh", + "e2e:login-context": "bash scripts/e2e/login-context.sh", + "e2e:opencode-autoconnect": "bash scripts/e2e/opencode-autoconnect.sh", "list": "pnpm --filter ./packages/app build && node packages/app/dist/main.js list", "dev": "pnpm --filter ./packages/app dev", "lint": "pnpm --filter ./packages/app lint && pnpm --filter ./packages/lib lint", diff --git a/packages/app/src/docker-git/cli/parser-auth.ts b/packages/app/src/docker-git/cli/parser-auth.ts index edc1ac00..28df20a9 100644 --- a/packages/app/src/docker-git/cli/parser-auth.ts +++ b/packages/app/src/docker-git/cli/parser-auth.ts @@ -1,12 +1,7 @@ import { Either, Match } from "effect" import type { RawOptions } from "@effect-template/lib/core/command-options" -import { - type AuthCommand, - type Command, - defaultTemplateConfig, - type ParseError -} from "@effect-template/lib/core/domain" +import { type AuthCommand, type Command, type ParseError } from "@effect-template/lib/core/domain" import { parseRawOptions } from "./parser-options.js" @@ -16,6 +11,7 @@ type AuthOptions = { readonly label: string | null readonly token: string | null readonly scopes: string | null + readonly authWeb: boolean } const missingArgument = (name: string): ParseError => ({ @@ -34,21 +30,27 @@ const normalizeLabel = (value: string | undefined): string | null => { return trimmed.length === 0 ? null : trimmed } +const defaultEnvGlobalPath = ".docker-git/.orch/env/global.env" +const defaultCodexAuthPath = ".docker-git/.orch/auth/codex" + const resolveAuthOptions = (raw: RawOptions): AuthOptions => ({ - envGlobalPath: raw.envGlobalPath ?? defaultTemplateConfig.envGlobalPath, - codexAuthPath: raw.codexAuthPath ?? defaultTemplateConfig.codexAuthPath, + envGlobalPath: raw.envGlobalPath ?? defaultEnvGlobalPath, + codexAuthPath: raw.codexAuthPath ?? defaultCodexAuthPath, label: normalizeLabel(raw.label), token: normalizeLabel(raw.token), - scopes: normalizeLabel(raw.scopes) + scopes: normalizeLabel(raw.scopes), + authWeb: raw.authWeb === true }) const buildGithubCommand = (action: string, options: AuthOptions): Either.Either => Match.value(action).pipe( Match.when("login", () => - Either.right({ + options.authWeb && options.token !== null + ? Either.left(invalidArgument("--token", "cannot be combined with --web")) + : Either.right({ _tag: "AuthGithubLogin", label: options.label, - token: options.token, + token: options.authWeb ? null : options.token, scopes: options.scopes, envGlobalPath: options.envGlobalPath })), diff --git a/packages/app/src/docker-git/cli/parser-mcp-playwright.ts b/packages/app/src/docker-git/cli/parser-mcp-playwright.ts index 2a4179c8..42abcd5f 100644 --- a/packages/app/src/docker-git/cli/parser-mcp-playwright.ts +++ b/packages/app/src/docker-git/cli/parser-mcp-playwright.ts @@ -22,4 +22,3 @@ export const parseMcpPlaywright = ( projectDir, runUp: raw.up ?? true })) - diff --git a/packages/app/src/docker-git/cli/parser.ts b/packages/app/src/docker-git/cli/parser.ts index 829f4da9..8824f5ca 100644 --- a/packages/app/src/docker-git/cli/parser.ts +++ b/packages/app/src/docker-git/cli/parser.ts @@ -22,7 +22,7 @@ const statusCommand: Command = { _tag: "Status" } const downAllCommand: Command = { _tag: "DownAll" } const parseCreate = (args: ReadonlyArray): Either.Either => - Either.flatMap(parseRawOptions(args), buildCreateCommand) + Either.flatMap(parseRawOptions(args), (raw) => buildCreateCommand(raw)) // CHANGE: parse CLI arguments into a typed command // WHY: enforce deterministic, pure parsing before any effects run diff --git a/packages/app/src/docker-git/cli/usage.ts b/packages/app/src/docker-git/cli/usage.ts index 630c3915..af05e044 100644 --- a/packages/app/src/docker-git/cli/usage.ts +++ b/packages/app/src/docker-git/cli/usage.ts @@ -40,7 +40,6 @@ Options: --container-name Docker container name (default: dg-) --service-name Compose service name (default: dg-) --volume-name Docker volume name (default: dg--home) - --secrets-root Host root for shared secrets (default: n/a) --authorized-keys Host path to authorized_keys (default: /authorized_keys) --env-global Host path to shared env file (default: /.orch/env/global.env) --env-project Host path to project env file (default: ./.orch/env/project.env) @@ -80,7 +79,8 @@ Auth actions: Auth options: --label