From 6d6bdf3b84af5bca5f1eb24d68b1274e5362727a Mon Sep 17 00:00:00 2001 From: Lan_zhijiang Date: Thu, 27 Aug 2026 13:41:21 +0800 Subject: [PATCH] fix(desktop): isolate profile auth schemes --- apps/desktop/package.json | 2 +- .../main/__tests__/cloud-hosted-billing.test.ts | 15 +++++++++++++++ apps/desktop/src/main/constants.ts | 7 +++++-- apps/webview/package.json | 2 +- docs/DEVELOPMENT.md | 4 ++-- docs/ENVIRONMENT.md | 2 +- packages/vendor/linkcode-cloud-0.1.0.tgz | Bin 3869 -> 0 bytes packages/vendor/linkcode-cloud-0.1.1.tgz | Bin 0 -> 3927 bytes pnpm-lock.yaml | 16 ++++++++-------- 9 files changed, 33 insertions(+), 15 deletions(-) delete mode 100644 packages/vendor/linkcode-cloud-0.1.0.tgz create mode 100644 packages/vendor/linkcode-cloud-0.1.1.tgz diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 4f9d8e340..f30535044 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -34,7 +34,7 @@ "dependencies": { "@better-auth/api-key": "1.7.0-rc.2", "@better-auth/electron": "1.7.0-rc.2", - "@linkcode/cloud": "file:../../packages/vendor/linkcode-cloud-0.1.0.tgz", + "@linkcode/cloud": "file:../../packages/vendor/linkcode-cloud-0.1.1.tgz", "@linkcode/common": "workspace:*", "@linkcode/daemon": "workspace:*", "@linkcode/ipc": "workspace:*", diff --git a/apps/desktop/src/main/__tests__/cloud-hosted-billing.test.ts b/apps/desktop/src/main/__tests__/cloud-hosted-billing.test.ts index 31b66c1bc..45fc77ff8 100644 --- a/apps/desktop/src/main/__tests__/cloud-hosted-billing.test.ts +++ b/apps/desktop/src/main/__tests__/cloud-hosted-billing.test.ts @@ -52,7 +52,9 @@ vi.mock('../cloud-auth/storage', () => ({ describe('desktop hosted billing handoff', () => { beforeEach(() => { + vi.resetModules(); vi.clearAllMocks(); + delete process.env.LINKCODE_PROFILE; mocks.handlers.clear(); mocks.setAsDefaultProtocolClient.mockReturnValue(true); mocks.openExternal.mockResolvedValue(undefined); @@ -76,6 +78,19 @@ describe('desktop hosted billing handoff', () => { ); }); + it('isolates the native return target by profile', async () => { + process.env.LINKCODE_PROFILE = 'code-603'; + const { setupCloudAuth } = await import('../cloud-auth/client'); + const { CLOUD_OPEN_HOSTED_BILLING_CHANNEL } = await import('../../shared/cloud'); + setupCloudAuth(); + + await mocks.handlers.get(CLOUD_OPEN_HOSTED_BILLING_CHANNEL)?.(); + + expect(mocks.openExternal).toHaveBeenCalledWith( + 'https://console.linkcode.ai/billing?returnTarget=linkcode-dev-code-603%3A%2F%2Fbilling%2Freturn', + ); + }); + it('mints a Gateway key in the signed-in session organization', async () => { const { setupCloudAuth } = await import('../cloud-auth/client'); const { CLOUD_CREATE_GATEWAY_KEY_CHANNEL } = await import('../../shared/cloud'); diff --git a/apps/desktop/src/main/constants.ts b/apps/desktop/src/main/constants.ts index ecee91929..b73878cab 100644 --- a/apps/desktop/src/main/constants.ts +++ b/apps/desktop/src/main/constants.ts @@ -76,12 +76,15 @@ export const STORAGE_DIR_NAME = /** * OAuth deep-link protocol (see cloud-auth/client.ts): brand-owned when a brand identity is - * embedded, split per channel so a development build never fights the installed release over + * embedded, split per channel and profile so concurrently running identities never fight over * the OS-global scheme. */ -export const CLOUD_AUTH_SCHEME = +const CLOUD_AUTH_SCHEME_BASE = BRAND_BASE?.authScheme ?? (CHANNEL === 'development' ? 'linkcode-dev' : 'linkcode'); +export const CLOUD_AUTH_SCHEME = + PROFILE === undefined ? CLOUD_AUTH_SCHEME_BASE : `${CLOUD_AUTH_SCHEME_BASE}-${PROFILE}`; + /** The channel's workspace directory (`~/LinkCode`, `~/LinkCode Development`) — shared across * that channel's profiles on purpose, but never across channels (CODE-460). Must agree with the * daemon's `chatWorkspaceRoot()`, which derives the same name from its own resolved channel. */ diff --git a/apps/webview/package.json b/apps/webview/package.json index bfe924ac4..cf27e673e 100644 --- a/apps/webview/package.json +++ b/apps/webview/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@hookform/resolvers": "^5.5.7", - "@linkcode/cloud": "file:../../packages/vendor/linkcode-cloud-0.1.0.tgz", + "@linkcode/cloud": "file:../../packages/vendor/linkcode-cloud-0.1.1.tgz", "@linkcode/common": "workspace:*", "@linkcode/schema": "workspace:*", "@linkcode/sdk": "workspace:*", diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 73192f34b..a9445b562 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -322,7 +322,7 @@ git apply --3way "$(ls -t .devenv/state/prek/patches/*.patch | head -1)" The identity is two orthogonal axes (`apps/desktop/src/main/constants.ts`), and the desktop's app name, `userData` dir, single-instance lock, and OS keychain (safeStorage) all derive from them; `src/main/identity.ts` applies the identity as main's **first import**, and boot logs a `userData: ` line as self-evidence. Since CODE-460 the **daemon's** state follows the same two axes, so a local build and an installed release share nothing at all. - **channel** — `CHANNEL === 'development'` for any build that is not the released app: `MODE !== 'production' || !app.isPackaged` (a production bundle run by the dev Electron binary is still a dev shell). `APP_NAME` is `'LinkCode Development'` for dev, `'LinkCode'` for release. Skipping any isolation axis clobbers release settings, steals its instance lock (the second instance exits 0 silently), or writes a safeStorage key under the dev binary's code signature — after which the release app prompts for the keychain password on first launch (macOS keychain ACLs pin the creator cdhash). -- **profile** — an optional isolated universe *within* a channel: `--profile=` (or `LINKCODE_PROFILE`; `[a-z0-9-]`, ≤32 chars, invalid aborts boot). It suffixes the app name (`LinkCode Development (alpha)`) — forking the same four axes again — and is injected as `LINKCODE_PROFILE` into the supervised daemon, which forks its state dir and cloud device identity with it. Profiles run side by side: daemons hunt past each other's ports, and each desktop follows its own `runtime.json`. The devenv `daemon`/`desktop`/`app` scripts pass **no** profile — the development channel is already its own universe; pass one yourself only to fork a second universe within that channel. +- **profile** — an optional isolated universe *within* a channel: `--profile=` (or `LINKCODE_PROFILE`; `[a-z0-9-]`, ≤32 chars, invalid aborts boot). It suffixes the app name (`LinkCode Development (alpha)`) and OAuth scheme (`linkcode-dev-alpha://`) — forking the same identity surfaces again — and is injected as `LINKCODE_PROFILE` into the supervised daemon, which forks its state dir and cloud device identity with it. Profiles run side by side: daemons hunt past each other's ports, each desktop follows its own `runtime.json`, and OAuth callbacks return to the matching app. The devenv `daemon`/`desktop`/`app` scripts pass **no** profile — the development channel is already its own universe; pass one yourself only to fork a second universe within that channel. The daemon is a separate process and cannot see `app.isPackaged`, so it resolves its own channel (`apps/daemon/src/paths.ts`): the desktop supervisor's injected `LINKCODE_CHANNEL` wins, else the build-time stamp tsup bakes in (`process.env.LINKCODE_BUILD_CHANNEL` → `release`), else `development`. Running the TS source is therefore a development daemon with nothing to remember, while a packaged one is release — and the devshell pack, which ships a `release`-stamped bundle inside a development shell, is corrected by the injection. Resolution is per call, never cached at module load: `instrument.ts` derives a state path in its module body and `--import` runs it before `index.ts`. @@ -355,7 +355,7 @@ The daemon holds no credential in those files: `secrets.json` is AES-256-GCM cip A profile appends `-` to the **state** directory only (`~/.linkcode.development-alpha`); workspaces and the asset store fork by channel alone. The development suffix is dot-separated on purpose: profile names forbid dots, so `--profile=development` can never reach the development channel's directory. -Two things stay shared across channels by design: the agent CLIs' own homes (`~/.claude`, `~/.codex` — separating them would force a second agent login and cut you off from the CLI you use in a terminal), and the `linkcode://` scheme's OS-global nature, which is why the dev shell claims `linkcode-dev://` instead (CODE-182). +The agent CLIs' own homes (`~/.claude`, `~/.codex`) stay shared across channels by design; separating them would force a second agent login and cut you off from the CLI you use in a terminal. OAuth schemes are OS-global, so the dev shell claims `linkcode-dev://` and profiles append their name. Ports fork with the state: **release hunts 19523–19532, development 19533–19542**. The ranges are disjoint deliberately. The identity's `channel` field is the precise signal, but it cannot defend against a daemon shipped *before* that field existed — an old peer parses the newer identity through a schema without the key, zod strips it, and its profile-only comparison reads two default profiles as equal. Such a release would exit 3 against a development daemon sitting on 19523 and its supervisor would stand down, leaving the release shell to fall back to that same port and dial the wrong daemon. Never letting the channels reach one another's ports is the only fix that reaches binaries already in the wild. diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 05d58c9da..6e86e3479 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -17,7 +17,7 @@ Read by the daemon, desktop, webview, or mobile at run time. | --- | --- | --- | | `LINKCODE_CHANNEL` | `apps/daemon/src/paths.ts` | Picks the daemon's on-disk universe: `release` → `~/.linkcode` + `~/LinkCode` + `…/LinkCode/assets`; `development` → the `LinkCode Development` / `.linkcode.development` set (CODE-460). Outranks the build-time stamp, which is why the desktop supervisor always injects its own `CHANNEL` — the devshell pack's bundled daemon is stamped `release`. Any other value aborts boot. | | `LINKCODE_BUILD_CHANNEL` | `apps/daemon/tsup.config.ts` (`define`) | **Build-time stamp, not a runtime knob.** tsup replaces the literal with `release`, so a built daemon defaults to release and the TS source defaults to development. Setting it by hand in a shell works but is not the supported override — use `LINKCODE_CHANNEL`. | -| `LINKCODE_PROFILE` | `apps/daemon/src/config.ts` | Isolated state universe *within a channel*: forks the state dir to the `-` sibling (`~/.linkcode.development-alpha`), plus DB, `runtime.json`, and HQ device identity. `[a-z0-9-]`, ≤32 chars; invalid aborts boot. Workspaces and the asset store do not fork by profile. Desktop reads it too, where `--profile=` outranks it, and re-injects the resolved value into the supervised daemon. Unset = the channel's default universe. | +| `LINKCODE_PROFILE` | `apps/daemon/src/config.ts` | Isolated state universe *within a channel*: forks the state dir to the `-` sibling (`~/.linkcode.development-alpha`), plus DB, `runtime.json`, HQ device identity, and the desktop OAuth scheme (`linkcode-dev-alpha://`). `[a-z0-9-]`, ≤32 chars; invalid aborts boot. Workspaces and the asset store do not fork by profile. Desktop reads it too, where `--profile=` outranks it, and re-injects the resolved value into the supervised daemon. Unset = the channel's default universe. | | `LINKCODE_PORT` | `apps/daemon/src/config.ts` | Overrides every configured listener's port. Must parse as an integer in `1..65535`, otherwise the config value stands. | | `LINKCODE_HOST` | `apps/daemon/src/config.ts` | Overrides every listener's bind host. | | `LINKCODE_PTY_SIDECAR_PATH` | `apps/daemon/src/pty/sidecar.ts` | Absolute path to the `linkcode-pty` binary; always wins. Dev falls back to `target/release/linkcode-pty`; a bundled `dist/` daemon has no fallback and disables terminals. The packaged desktop supervisor sets it to `/sidecar/`. | diff --git a/packages/vendor/linkcode-cloud-0.1.0.tgz b/packages/vendor/linkcode-cloud-0.1.0.tgz deleted file mode 100644 index ab0d5e8238ed6cc63013473c3de16938930d66a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3869 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 diff --git a/packages/vendor/linkcode-cloud-0.1.1.tgz b/packages/vendor/linkcode-cloud-0.1.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..38de23986d9786a423c70ace418b038330a07da2 GIT binary patch literal 3927 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 literal 0 HcmV?d00001 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d717c5d1..e35a57be4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -293,8 +293,8 @@ importers: specifier: 1.7.0-rc.2 version: 1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(better-call@1.3.7(zod@4.4.3))(electron@43.2.0) '@linkcode/cloud': - specifier: file:../../packages/vendor/linkcode-cloud-0.1.0.tgz - version: file:packages/vendor/linkcode-cloud-0.1.0.tgz + specifier: file:../../packages/vendor/linkcode-cloud-0.1.1.tgz + version: file:packages/vendor/linkcode-cloud-0.1.1.tgz '@linkcode/common': specifier: workspace:* version: link:../../packages/foundation/common @@ -649,8 +649,8 @@ importers: specifier: ^5.5.7 version: 5.5.7(@sinclair/typebox@0.27.10)(@standard-schema/spec@1.1.0)(ajv@8.20.0)(react-hook-form@7.83.0(react@19.3.0-canary-96fcba90-20260728))(zod@4.4.3) '@linkcode/cloud': - specifier: file:../../packages/vendor/linkcode-cloud-0.1.0.tgz - version: file:packages/vendor/linkcode-cloud-0.1.0.tgz + specifier: file:../../packages/vendor/linkcode-cloud-0.1.1.tgz + version: file:packages/vendor/linkcode-cloud-0.1.1.tgz '@linkcode/common': specifier: workspace:* version: link:../../packages/foundation/common @@ -3490,9 +3490,9 @@ packages: typescript: optional: true - '@linkcode/cloud@file:packages/vendor/linkcode-cloud-0.1.0.tgz': - resolution: {integrity: sha512-i38bW7xCv8Us+iW3ZDKV64cB3riTvk2rbnbppvrdl+BLNL96VE484yiQ9sopunYaxrRWy7Qi8txFecGh2/s++w==, tarball: file:packages/vendor/linkcode-cloud-0.1.0.tgz} - version: 0.1.0 + '@linkcode/cloud@file:packages/vendor/linkcode-cloud-0.1.1.tgz': + resolution: {integrity: sha512-5qAPOLWs4CzHkhbjKctwMEYj35NxO9eVDo7P/g1fIEUWENA/ahrHtwA01IqZriJSHbPgE9OK0+28xZD2z+90zw==, tarball: file:packages/vendor/linkcode-cloud-0.1.1.tgz} + version: 0.1.1 '@linkcode/tunnel@0.1.0': resolution: {integrity: sha512-vRUQJApK4IDOicEOJ6B3PD5yBacFOL6Xr4Wel6UpG53TDSkkmv0W5uZw6vX7OMtWthI/S70yyVkvXtFOFho//w==} @@ -13960,7 +13960,7 @@ snapshots: optionalDependencies: typescript: '@typescript/typescript6@6.0.2' - '@linkcode/cloud@file:packages/vendor/linkcode-cloud-0.1.0.tgz': {} + '@linkcode/cloud@file:packages/vendor/linkcode-cloud-0.1.1.tgz': {} '@linkcode/tunnel@0.1.0': {}