@doist/cli-core 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [0.16.1](https://github.com/Doist/cli-core/compare/v0.16.0...v0.16.1) (2026-05-16)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **auth:** open browser on WSL via cmd.exe; always surface URL ([#29](https://github.com/Doist/cli-core/issues/29)) ([4ac2824](https://github.com/Doist/cli-core/commit/4ac282474ca8a5f5cde1fe690b1a2bca7fcd5be1))
6
+
7
+ ## [0.16.0](https://github.com/Doist/cli-core/compare/v0.15.0...v0.16.0) (2026-05-16)
8
+
9
+ ### Features
10
+
11
+ * **auth:** add migrateLegacyAuth helper ([#28](https://github.com/Doist/cli-core/issues/28)) ([cd7baee](https://github.com/Doist/cli-core/commit/cd7baeebdb9b3dfc5909862a0af7ae5bfee17723))
12
+
1
13
  ## [0.15.0](https://github.com/Doist/cli-core/compare/v0.14.0...v0.15.0) (2026-05-16)
2
14
 
3
15
  ### Features
package/README.md CHANGED
@@ -12,20 +12,20 @@ npm install @doist/cli-core
12
12
 
13
13
  ## What's in it
14
14
 
15
- | Module | Key exports | Purpose |
16
- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
- | `auth` (subpath) | `attachLoginCommand`, `attachLogoutCommand`, `attachStatusCommand`, `attachTokenViewCommand`, `runOAuthFlow`, `createPkceProvider`, `createSecureStore`, `createKeyringTokenStore`, PKCE helpers, `AuthProvider` / `TokenStore` / `AccountRef` / `SecureStore` / `UserRecordStore` types, `AttachLogoutRevokeContext` | OAuth runtime plus the Commander attachers for `<cli> [auth] login` / `logout` / `status` / `token`. `attachLogoutCommand` accepts an optional `revokeToken` hook for best-effort server-side token revocation. Ships the standard public-client PKCE flow (`createPkceProvider`), a thin cross-platform OS-keyring wrapper (`createSecureStore`), and a multi-account keyring-backed `TokenStore` (`createKeyringTokenStore`) that stores secrets in the OS credential manager and degrades to plaintext in the consumer's config when the keyring is unavailable (WSL/headless Linux/containers). `AuthProvider` and `TokenStore` remain the escape hatches for DCR or fully bespoke backends. `logout` / `status` / `token` always attach `--user <ref>` and thread the parsed ref to `store.active(ref)` (and `store.clear(ref)` on `logout`). `commander` (when using the attachers), `open` (browser launch), and `@napi-rs/keyring` (when using `createSecureStore` or the keyring `TokenStore`) are optional peer/optional deps. |
18
- | `commands` (subpath) | `registerChangelogCommand`, `registerUpdateCommand` (+ semver helpers) | Commander wiring for cli-core's standard commands (e.g. `<cli> changelog`, `<cli> update`, `<cli> update switch`). **Requires** `commander` as an optional peer-dep. |
19
- | `config` | `getConfigPath`, `readConfig`, `readConfigStrict`, `writeConfig`, `updateConfig`, `CoreConfig`, `UpdateChannel` | Read / write a per-CLI JSON config file with typed error codes; `CoreConfig` is the shape of fields cli-core itself owns (extend it for per-CLI fields). |
20
- | `empty` | `printEmpty` | Print an empty-state message gated on `--json` / `--ndjson` so machine consumers never see human strings on stdout. |
21
- | `errors` | `CliError` | Typed CLI error class with `code` and exit-code mapping. |
22
- | `global-args` | `parseGlobalArgs`, `stripUserFlag`, `createGlobalArgsStore`, `createAccessibleGate`, `createSpinnerGate`, `getProgressJsonlPath`, `isProgressJsonlEnabled` | Parse well-known global flags (`--json`, `--ndjson`, `--quiet`, `--verbose`, `--accessible`, `--no-spinner`, `--progress-jsonl`, `--user <ref>`) and derive predicates from them. `stripUserFlag` removes `--user` tokens from argv so the cleaned array can be forwarded to Commander when the flag has no root-program attachment. |
23
- | `json` | `formatJson`, `formatNdjson` | Stable JSON / newline-delimited JSON formatting for stdout. |
24
- | `markdown` (subpath) | `preloadMarkdown`, `renderMarkdown`, `TerminalRendererOptions` | Lazy-init terminal markdown renderer. **Requires** `marked` and `marked-terminal-renderer` as peer-deps — install only if your CLI uses this subpath. |
25
- | `options` | `ViewOptions` | Type contract for `{ json?, ndjson? }` per-command options that machine-output gates derive from. |
26
- | `spinner` | `createSpinner` | Loading spinner factory wrapping `yocto-spinner` with disable gates. |
27
- | `terminal` | `isCI`, `isStderrTTY`, `isStdinTTY`, `isStdoutTTY` | TTY / CI detection helpers. |
28
- | `testing` (subpath) | `describeEmptyMachineOutput` | Vitest helpers reusable by consuming CLIs (e.g. parametrised empty-state suite covering `--json` / `--ndjson` / human modes). |
15
+ | Module | Key exports | Purpose |
16
+ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
+ | `auth` (subpath) | `attachLoginCommand`, `attachLogoutCommand`, `attachStatusCommand`, `attachTokenViewCommand`, `runOAuthFlow`, `createPkceProvider`, `createSecureStore`, `createKeyringTokenStore`, `migrateLegacyAuth`, PKCE helpers, `AuthProvider` / `TokenStore` / `AccountRef` / `SecureStore` / `UserRecordStore` types, `AttachLogoutRevokeContext` | OAuth runtime plus the Commander attachers for `<cli> [auth] login` / `logout` / `status` / `token`. `attachLogoutCommand` accepts an optional `revokeToken` hook for best-effort server-side token revocation. Ships the standard public-client PKCE flow (`createPkceProvider`), a thin cross-platform OS-keyring wrapper (`createSecureStore`), and a multi-account keyring-backed `TokenStore` (`createKeyringTokenStore`) that stores secrets in the OS credential manager and degrades to plaintext in the consumer's config when the keyring is unavailable (WSL/headless Linux/containers). `AuthProvider` and `TokenStore` remain the escape hatches for DCR or fully bespoke backends. `logout` / `status` / `token` always attach `--user <ref>` and thread the parsed ref to `store.active(ref)` (and `store.clear(ref)` on `logout`). `commander` (when using the attachers), `open` (browser launch), and `@napi-rs/keyring` (when using `createSecureStore` or the keyring `TokenStore`) are optional peer/optional deps. |
18
+ | `commands` (subpath) | `registerChangelogCommand`, `registerUpdateCommand` (+ semver helpers) | Commander wiring for cli-core's standard commands (e.g. `<cli> changelog`, `<cli> update`, `<cli> update switch`). **Requires** `commander` as an optional peer-dep. |
19
+ | `config` | `getConfigPath`, `readConfig`, `readConfigStrict`, `writeConfig`, `updateConfig`, `CoreConfig`, `UpdateChannel` | Read / write a per-CLI JSON config file with typed error codes; `CoreConfig` is the shape of fields cli-core itself owns (extend it for per-CLI fields). |
20
+ | `empty` | `printEmpty` | Print an empty-state message gated on `--json` / `--ndjson` so machine consumers never see human strings on stdout. |
21
+ | `errors` | `CliError` | Typed CLI error class with `code` and exit-code mapping. |
22
+ | `global-args` | `parseGlobalArgs`, `stripUserFlag`, `createGlobalArgsStore`, `createAccessibleGate`, `createSpinnerGate`, `getProgressJsonlPath`, `isProgressJsonlEnabled` | Parse well-known global flags (`--json`, `--ndjson`, `--quiet`, `--verbose`, `--accessible`, `--no-spinner`, `--progress-jsonl`, `--user <ref>`) and derive predicates from them. `stripUserFlag` removes `--user` tokens from argv so the cleaned array can be forwarded to Commander when the flag has no root-program attachment. |
23
+ | `json` | `formatJson`, `formatNdjson` | Stable JSON / newline-delimited JSON formatting for stdout. |
24
+ | `markdown` (subpath) | `preloadMarkdown`, `renderMarkdown`, `TerminalRendererOptions` | Lazy-init terminal markdown renderer. **Requires** `marked` and `marked-terminal-renderer` as peer-deps — install only if your CLI uses this subpath. |
25
+ | `options` | `ViewOptions` | Type contract for `{ json?, ndjson? }` per-command options that machine-output gates derive from. |
26
+ | `spinner` | `createSpinner` | Loading spinner factory wrapping `yocto-spinner` with disable gates. |
27
+ | `terminal` | `isCI`, `isStderrTTY`, `isStdinTTY`, `isStdoutTTY` | TTY / CI detection helpers. |
28
+ | `testing` (subpath) | `describeEmptyMachineOutput` | Vitest helpers reusable by consuming CLIs (e.g. parametrised empty-state suite covering `--json` / `--ndjson` / human modes). |
29
29
 
30
30
  ## Usage
31
31
 
@@ -132,7 +132,7 @@ Wire `<cli> [auth] login` and the supporting OAuth runtime. cli-core ships the s
132
132
  npm install commander open
133
133
  ```
134
134
 
135
- `commander` is required when using `attachLoginCommand`. `open` is optional when it's missing or `open()` throws, the authorize URL is surfaced via `onAuthorizeUrl` (or printed to stdout in human mode, stderr in `--json` / `--ndjson` mode) so the user can complete the flow manually.
135
+ `commander` is required when using `attachLoginCommand`. `open` is optional. The authorize URL is **always** surfaced via `onAuthorizeUrl` (or printed to stdout in human mode, stderr in `--json` / `--ndjson` mode) — even when the browser launch succeeds — because the launch can resolve cleanly yet open no actual browser (WSL silent no-op, headless Linux, locked-down corporate envs). WSL hosts get routed through `cmd.exe` directly so the user's real Windows browser opens. Headless Linux skips the launch entirely and relies on the URL print.
136
136
 
137
137
  #### Quick start (PKCE)
138
138
 
@@ -229,10 +229,10 @@ Both attachers strip the standard `--json` / `--ndjson` / `--user` registrar fla
229
229
  | ------------------------ | -------------------------------------------------------------------------------------- |
230
230
  | `--read-only` | Threaded through to `resolveScopes` and the provider hooks via `readOnly`. |
231
231
  | `--callback-port <port>` | Override `preferredPort` per invocation. Validated as `[0..65535]`; `0` = OS-assigned. |
232
- | `--json` | Machine-output mode. Authorize-URL fallback is routed to stderr. |
233
- | `--ndjson` | Machine-output mode. Same fallback routing. |
232
+ | `--json` | Machine-output mode. Authorize-URL print is routed to stderr. |
233
+ | `--ndjson` | Machine-output mode. Same print routing. |
234
234
 
235
- Under `--json` / `--ndjson`, the authorize-URL fallback (printed when `open` is missing or `open()` throws) goes to stderr so the JSON / NDJSON envelope on stdout stays clean. Pass `onAuthorizeUrl` to override the destination. The success / error HTML returned by `renderSuccess` / `renderError` is a render hook — every CLI brings its own template (no shared layout enforced).
235
+ Under `--json` / `--ndjson`, the always-printed authorize URL goes to stderr so the JSON / NDJSON envelope on stdout stays clean. Pass `onAuthorizeUrl` to override the destination. The success / error HTML returned by `renderSuccess` / `renderError` is a render hook — every CLI brings its own template (no shared layout enforced).
236
236
 
237
237
  #### Implementing `TokenStore`
238
238
 
@@ -362,6 +362,42 @@ When a matching record exists but the keyring read fails, `active(ref)` throws `
362
362
 
363
363
  For sync/lazy-decrypt or fully bespoke backends, implement `TokenStore` directly.
364
364
 
365
+ For one-time migration of a v1 single-user token into the v2 multi-user shape, use `migrateLegacyAuth` from a postinstall hook. The helper requires a durable **migration marker** the consumer owns — a boolean persisted in their config — so the migration is genuinely one-way: a later `logout` (which empties `userRecords`) followed by a reinstall won't re-migrate a stale legacy token.
366
+
367
+ ```ts
368
+ import { getConfigPath, readConfig, updateConfig } from '@doist/cli-core'
369
+ import { migrateLegacyAuth } from '@doist/cli-core/auth'
370
+
371
+ const configPath = getConfigPath('todoist-cli')
372
+
373
+ const result = await migrateLegacyAuth<Account>({
374
+ serviceName: 'todoist-cli',
375
+ legacyAccount: 'api-token',
376
+ userRecords,
377
+ // Durable one-way gate. Persist `migrated_v2: true` in your config
378
+ // after a successful migration; check it on every run.
379
+ hasMigrated: async () =>
380
+ (await readConfig<{ migrated_v2?: boolean }>(configPath)).migrated_v2 === true,
381
+ markMigrated: async () =>
382
+ updateConfig<{ migrated_v2: boolean }>(configPath, { migrated_v2: true }),
383
+ loadLegacyPlaintextToken: async () =>
384
+ (await readConfig<{ api_token?: string }>(configPath)).api_token ?? null,
385
+ identifyAccount: async (token) => fetchUser(token),
386
+ cleanupLegacyConfig: async () => clearLegacyAuthFields(configPath),
387
+ silent: true,
388
+ logPrefix: 'todoist-cli',
389
+ })
390
+
391
+ if (result.status === 'skipped' && result.reason === 'legacy-keyring-unreachable') {
392
+ // Retryable — the next postinstall run with the keyring online will
393
+ // pick up where this one left off.
394
+ }
395
+ ```
396
+
397
+ `MigrateAuthResult` is a discriminated union on `status` (`'already-migrated' | 'no-legacy-state' | 'migrated' | 'skipped'`). `migrated` carries the resolved `account`; `skipped` carries a stable `reason` (`'identify-failed' | 'legacy-keyring-unreachable' | 'user-record-write-failed' | 'marker-write-failed'`) plus a free-form `detail`.
398
+
399
+ The helper is best-effort throughout: any failure (offline keyring, network error fetching the user, upsert blip) leaves the v1 state untouched so the consumer's runtime fallback can keep serving the legacy token until the next attempt. `markMigrated()` is called **before** the legacy keyring delete + `cleanupLegacyConfig`, so cleanup failures can't cause re-migration on the next run — the marker is the one-way gate, not cleanup success. The legacy delete and `cleanupLegacyConfig` run concurrently via `Promise.allSettled`. stderr output uses fixed phrases keyed off `MigrateSkipReason` and the success log omits the account identifier entirely so consumer-supplied error text (and PII-shaped `account.id` values like emails) can't leak into logs.
400
+
365
401
  #### `--user <ref>` and multi-user wiring
366
402
 
367
403
  The three account-touching attachers (`attachLogoutCommand` / `attachStatusCommand` / `attachTokenViewCommand`) always attach `--user <ref>` on their subcommand. `attachLogoutCommand` threads the parsed ref to both `store.active(ref)` and `store.clear(ref)`; `attachStatusCommand` and `attachTokenViewCommand` only call `store.active(ref)`. When `--user` is supplied but `store.active(ref)` returns `null`, each attacher throws `CliError('ACCOUNT_NOT_FOUND', …)` so the user sees a typed miss rather than `NOT_AUTHENTICATED` or a silent `✓ Logged out`. Single-user stores returning `null` for a non-matching ref is the supported way to feed this guard.
@@ -22,8 +22,15 @@ export type RunOAuthFlowOptions<TAccount extends AuthAccount = AuthAccount> = {
22
22
  renderError: (message: string) => string;
23
23
  /** Override the browser opener (tests). When omitted, dynamically imports `open`. */
24
24
  openBrowser?: (url: string) => Promise<void>;
25
- /** Print the authorize URL to stdout as a fallback when the browser can't open it. */
26
- onAuthorizeUrl?: (url: string) => void;
25
+ /**
26
+ * Receives the authorize URL on every login attempt — not only when the
27
+ * browser launch fails — because the launch can resolve cleanly yet
28
+ * open no browser (WSL no-op, headless Linux, locked-down hosts).
29
+ * Treat as a fire-and-forget output channel: a sync hook is awaited,
30
+ * an async hook is awaited too, and any throw / rejection is swallowed
31
+ * so a buggy logger can never abort an otherwise-working login.
32
+ */
33
+ onAuthorizeUrl?: (url: string) => void | Promise<void>;
27
34
  /** Callback timeout in ms. Default 3 minutes. */
28
35
  timeoutMs?: number;
29
36
  /** Cancellation signal (Ctrl-C wiring). */
@@ -1 +1 @@
1
- {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAChC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,sCAAsC;IACtC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAA;IACjB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,MAAM,CAAA;IAC3B,qFAAqF;IACrF,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,sFAAsF;IACtF,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACzE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,QAAQ,CAAA;CACpB,CAAA;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAAC,QAAQ,SAAS,WAAW,EAC3D,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACvC,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CA0GvC"}
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AA4BvE,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAChC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,sCAAsC;IACtC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAA;IACjB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,MAAM,CAAA;IAC3B,qFAAqF;IACrF,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACzE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,QAAQ,CAAA;CACpB,CAAA;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAAC,QAAQ,SAAS,WAAW,EAC3D,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACvC,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CA0GvC"}
package/dist/auth/flow.js CHANGED
@@ -1,7 +1,38 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { readFileSync } from 'node:fs';
1
3
  import { createServer } from 'node:http';
4
+ import { promisify } from 'node:util';
2
5
  import { CliError, getErrorMessage } from '../errors.js';
3
6
  import { isStdoutTTY } from '../terminal.js';
4
7
  import { generateState } from './pkce.js';
8
+ // WSL's `open` package routes through `xdg-open` / `wslview`, both of which
9
+ // silently no-op on headless WSL installs — the spawn resolves cleanly but no
10
+ // browser ever appears, so the OAuth callback wait runs to its 3-minute
11
+ // timeout. Detect at call time and route WSL through `cmd.exe` directly.
12
+ // Non-Linux platforms short-circuit before the fs read.
13
+ function isWsl() {
14
+ if (process.platform !== 'linux')
15
+ return false;
16
+ try {
17
+ return /microsoft/i.test(readFileSync('/proc/version', 'utf8'));
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ // SSH sessions, containers, CI runners, headless servers — same failure mode
24
+ // as WSL but with no Windows side to bounce through. With no DISPLAY /
25
+ // WAYLAND_DISPLAY (and no $BROWSER override for Codespaces-style setups
26
+ // that route through a remote bridge), `xdg-open` will either error or
27
+ // no-op, so the spawn is pure noise — skip it and let the URL print do the
28
+ // work.
29
+ function isHeadlessLinux() {
30
+ if (process.platform !== 'linux')
31
+ return false;
32
+ if (process.env.BROWSER)
33
+ return false;
34
+ return !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY;
35
+ }
5
36
  const DEFAULT_PORT_FALLBACK_COUNT = 5;
6
37
  const DEFAULT_CALLBACK_TIMEOUT_MS = 3 * 60 * 1000;
7
38
  const DEFAULT_CALLBACK_PATH = '/callback';
@@ -294,24 +325,41 @@ function assertValidPort(port, label) {
294
325
  }
295
326
  }
296
327
  async function openOrFallback(url, options) {
297
- const opener = options.openBrowser ?? (await loadDefaultOpener());
298
- if (opener) {
328
+ // Surface the URL up-front, before attempting the browser spawn. The
329
+ // spawn can succeed yet open no browser (WSL without working interop,
330
+ // headless Linux, locked-down corporate envs, missing `open` peer), and
331
+ // we have no reliable signal that the user actually landed on the page
332
+ // — so printing here guarantees a copy-pasteable path on every platform.
333
+ // The hook is purely an output channel: isolate its failures so a buggy
334
+ // logger can't abort the login that the user is actually here to do.
335
+ if (options.onAuthorizeUrl) {
299
336
  try {
300
- await opener(url);
301
- return;
337
+ await options.onAuthorizeUrl(url);
302
338
  }
303
339
  catch {
304
- // Fall through to the URL print below.
340
+ // Hook errors don't propagate.
305
341
  }
306
342
  }
307
- // No opener available, or the opener threw. Surface the URL so the user
308
- // can finish the flow manually.
309
- if (options.onAuthorizeUrl)
310
- options.onAuthorizeUrl(url);
311
343
  else if (isStdoutTTY())
312
344
  console.log(`Open this URL in your browser:\n ${url}`);
345
+ const opener = options.openBrowser ?? (await loadDefaultOpener());
346
+ if (!opener)
347
+ return;
348
+ try {
349
+ await opener(url);
350
+ }
351
+ catch {
352
+ // URL is already surfaced above.
353
+ }
313
354
  }
314
355
  async function loadDefaultOpener() {
356
+ // WSL check must run before the headless check: WSL is `platform === 'linux'`
357
+ // and often has no DISPLAY, but `cmd.exe` does work and reaches the user's
358
+ // real Windows browser, so it's worth the spawn.
359
+ if (isWsl())
360
+ return openViaCmdExe;
361
+ if (isHeadlessLinux())
362
+ return null;
315
363
  try {
316
364
  const mod = (await import('open'));
317
365
  return async (url) => {
@@ -322,4 +370,22 @@ async function loadDefaultOpener() {
322
370
  return null;
323
371
  }
324
372
  }
373
+ const execFileAsync = promisify(execFile);
374
+ // Two layers of escaping are needed because `cmd.exe /c` is a shell:
375
+ // 1. Wrap the URL in literal double quotes. WSL interop only auto-quotes
376
+ // args that contain spaces; an OAuth URL (no spaces, plenty of `&`s)
377
+ // would otherwise be re-parsed by cmd.exe with `&` acting as a
378
+ // statement separator, so only the prefix up to the first `&` would
379
+ // reach `start`.
380
+ // 2. Double every `%` to `%%`. cmd.exe expands `%NAME%` even inside
381
+ // quoted strings; OAuth URLs are full of percent-encoded bytes
382
+ // (`%3A`, `%2F`, …) and a chance match against a defined env var
383
+ // (`%PATH%`, `%TEMP%`, …) would silently mangle the URL.
384
+ // `start ""` — the empty title arg is mandatory; otherwise `start` consumes
385
+ // the URL as a window title and never launches a browser. (`execFile`'s
386
+ // no-shell guarantee doesn't apply when the target is itself a shell.)
387
+ async function openViaCmdExe(url) {
388
+ const escaped = url.replaceAll('%', '%%');
389
+ await execFileAsync('cmd.exe', ['/c', 'start', '""', `"${escaped}"`], { windowsHide: true });
390
+ }
325
391
  //# sourceMappingURL=flow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,6 @@ export type { GenerateVerifierOptions } from './pkce.js';
14
14
  export { createPkceProvider } from './providers/pkce.js';
15
15
  export type { PkceLazyString, PkceProviderOptions } from './providers/pkce.js';
16
16
  export type { AccountRef, AuthAccount, AuthorizeInput, AuthorizeResult, AuthProvider, ExchangeInput, ExchangeResult, PrepareInput, PrepareResult, TokenStore, ValidateInput, } from './types.js';
17
- export { SecureStoreUnavailableError, createKeyringTokenStore, createSecureStore, } from './keyring/index.js';
18
- export type { CreateKeyringTokenStoreOptions, CreateSecureStoreOptions, KeyringTokenStore, SecureStore, TokenStorageLocation, TokenStorageResult, UserRecord, UserRecordStore, } from './keyring/index.js';
17
+ export { SecureStoreUnavailableError, createKeyringTokenStore, createSecureStore, migrateLegacyAuth, } from './keyring/index.js';
18
+ export type { CreateKeyringTokenStoreOptions, CreateSecureStoreOptions, KeyringTokenStore, MigrateAuthResult, MigrateLegacyAuthOptions, MigrateSkipReason, SecureStore, TokenStorageLocation, TokenStorageResult, UserRecord, UserRecordStore, } from './keyring/index.js';
19
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,YAAY,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EACR,0BAA0B,EAC1B,mBAAmB,EACnB,yBAAyB,GAC5B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,YAAY,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAA;AACpE,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9E,YAAY,EACR,UAAU,EACV,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,GACpB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACR,8BAA8B,EAC9B,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,eAAe,GAClB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,YAAY,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EACR,0BAA0B,EAC1B,mBAAmB,EACnB,yBAAyB,GAC5B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,YAAY,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAA;AACpE,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9E,YAAY,EACR,UAAU,EACV,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,GACpB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACR,8BAA8B,EAC9B,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,eAAe,GAClB,MAAM,oBAAoB,CAAA"}
@@ -5,5 +5,5 @@ export { attachStatusCommand } from './status.js';
5
5
  export { attachTokenViewCommand } from './token-view.js';
6
6
  export { DEFAULT_VERIFIER_ALPHABET, deriveChallenge, generateState, generateVerifier, } from './pkce.js';
7
7
  export { createPkceProvider } from './providers/pkce.js';
8
- export { SecureStoreUnavailableError, createKeyringTokenStore, createSecureStore, } from './keyring/index.js';
8
+ export { SecureStoreUnavailableError, createKeyringTokenStore, createSecureStore, migrateLegacyAuth, } from './keyring/index.js';
9
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAMjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAExD,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAexD,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,GACpB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAMjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAExD,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAexD,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,GACpB,MAAM,oBAAoB,CAAA"}
@@ -2,5 +2,7 @@ export { SecureStoreUnavailableError, createSecureStore } from './secure-store.j
2
2
  export type { CreateSecureStoreOptions, SecureStore } from './secure-store.js';
3
3
  export { createKeyringTokenStore } from './token-store.js';
4
4
  export type { CreateKeyringTokenStoreOptions, KeyringTokenStore } from './token-store.js';
5
+ export { migrateLegacyAuth } from './migrate.js';
6
+ export type { MigrateAuthResult, MigrateLegacyAuthOptions, MigrateSkipReason } from './migrate.js';
5
7
  export type { TokenStorageLocation, TokenStorageResult, UserRecord, UserRecordStore, } from './types.js';
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAClF,YAAY,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,YAAY,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzF,YAAY,EACR,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,eAAe,GAClB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAClF,YAAY,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,YAAY,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAElG,YAAY,EACR,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,eAAe,GAClB,MAAM,YAAY,CAAA"}
@@ -1,3 +1,4 @@
1
1
  export { SecureStoreUnavailableError, createSecureStore } from './secure-store.js';
2
2
  export { createKeyringTokenStore } from './token-store.js';
3
+ export { migrateLegacyAuth } from './migrate.js';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/keyring/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGlF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/keyring/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGlF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAG1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,93 @@
1
+ import type { AuthAccount } from '../types.js';
2
+ import type { UserRecordStore } from './types.js';
3
+ export type MigrateLegacyAuthOptions<TAccount extends AuthAccount> = {
4
+ serviceName: string;
5
+ /** Legacy single-user keyring account slug, e.g. `'api-token'`. */
6
+ legacyAccount: string;
7
+ /** v2 user-record store the migrated record is written into. */
8
+ userRecords: UserRecordStore<TAccount>;
9
+ /** Per-user keyring slug for the new entry. Defaults to `user-${id}`. */
10
+ accountForUser?: (id: string) => string;
11
+ /**
12
+ * Reads the durable "migration already ran" marker the consumer owns
13
+ * (typically a flag in their config). When this returns `true`, the
14
+ * helper short-circuits with `already-migrated` and never touches the
15
+ * legacy state. This is the **one-way gate** — without it, a later
16
+ * `logout` (which empties `userRecords`) followed by a reinstall would
17
+ * cause the helper to re-migrate a stale legacy token.
18
+ */
19
+ hasMigrated: () => Promise<boolean>;
20
+ /**
21
+ * Persists the durable migration marker. Called **after** the v2 record
22
+ * write succeeds and **before** legacy cleanup so the gate is set before
23
+ * any best-effort follow-up runs. If this throws, the helper returns a
24
+ * `skipped` result with reason `marker-write-failed` — the v2 record is
25
+ * already on disk, but the marker isn't, so the caller should retry.
26
+ */
27
+ markMigrated: () => Promise<void>;
28
+ /**
29
+ * Returns the v1 token from the consumer's *plaintext* config slot, or
30
+ * `null` if absent. cli-core handles the legacy keyring slot itself.
31
+ */
32
+ loadLegacyPlaintextToken: () => Promise<string | null>;
33
+ /**
34
+ * Identifies the user behind the v1 token. Implementations typically hit
35
+ * the product API with the token to fetch the canonical `id` / `email`
36
+ * for the new account record.
37
+ */
38
+ identifyAccount: (token: string) => Promise<TAccount>;
39
+ /**
40
+ * Optional best-effort cleanup of v1-only config fields after a
41
+ * successful migration (e.g. unset legacy `api_token` / `auth_mode`).
42
+ * Runs concurrently with the legacy keyring delete; failures are
43
+ * swallowed because the marker (above) is what gates re-migration.
44
+ */
45
+ cleanupLegacyConfig?: () => Promise<void>;
46
+ /** Suppress stderr output (postinstall hooks set this). */
47
+ silent?: boolean;
48
+ /** Label used in the stderr log line. Defaults to `'cli'`. */
49
+ logPrefix?: string;
50
+ };
51
+ /**
52
+ * Stable skip reasons. `legacy-keyring-unreachable` is retryable (a later
53
+ * run with the keyring online would succeed); the others are diagnostic.
54
+ */
55
+ export type MigrateSkipReason = 'identify-failed' | 'legacy-keyring-unreachable' | 'user-record-write-failed' | 'marker-write-failed';
56
+ /**
57
+ * Discriminated by `status`. Narrowing on `status === 'skipped'` exposes
58
+ * the structured `reason` + free-form `detail`; `migrated` carries the
59
+ * resolved account.
60
+ */
61
+ export type MigrateAuthResult<TAccount extends AuthAccount = AuthAccount> = {
62
+ status: 'already-migrated';
63
+ } | {
64
+ status: 'no-legacy-state';
65
+ } | {
66
+ status: 'migrated';
67
+ account: TAccount;
68
+ } | {
69
+ status: 'skipped';
70
+ reason: MigrateSkipReason;
71
+ detail: string;
72
+ };
73
+ /**
74
+ * One-time migration of a v1 single-user auth state into a v2 multi-user
75
+ * shape. Best-effort: any failure (offline keyring, network error fetching
76
+ * the user, …) leaves the v1 state untouched so the consumer's runtime
77
+ * fallback can keep serving the legacy token until the next attempt.
78
+ *
79
+ * Order of operations is deliberate so the migration is genuinely one-way:
80
+ *
81
+ * 1. `hasMigrated()` short-circuits if the durable marker is already set.
82
+ * 2. Read the v1 token (legacy keyring slot first, then plaintext).
83
+ * 3. `identifyAccount(token)` resolves the v2 `account` shape.
84
+ * 4. `writeRecordWithKeyringFallback` writes the v2 record.
85
+ * 5. Best-effort `setDefaultId(account.id)` so the new record is active.
86
+ * 6. `markMigrated()` persists the marker. **If this fails, we return
87
+ * `skipped` even though the v2 record is on disk** — the marker is
88
+ * what prevents re-migration on the next run.
89
+ * 7. Best-effort legacy keyring delete + `cleanupLegacyConfig()` run
90
+ * concurrently. Failures here are harmless because the marker is set.
91
+ */
92
+ export declare function migrateLegacyAuth<TAccount extends AuthAccount>(options: MigrateLegacyAuthOptions<TAccount>): Promise<MigrateAuthResult<TAccount>>;
93
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAQ9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,MAAM,MAAM,wBAAwB,CAAC,QAAQ,SAAS,WAAW,IAAI;IACjE,WAAW,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,WAAW,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;IACtC,yEAAyE;IACzE,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IACnC;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC;;;OAGG;IACH,wBAAwB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtD;;;;OAIG;IACH,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACrD;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GACvB,iBAAiB,GACjB,4BAA4B,GAC5B,0BAA0B,GAC1B,qBAAqB,CAAA;AAS3B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAClE;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAC9B;IAAE,MAAM,EAAE,iBAAiB,CAAA;CAAE,GAC7B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAOtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,SAAS,WAAW,EAChE,OAAO,EAAE,wBAAwB,CAAC,QAAQ,CAAC,GAC5C,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAuGtC"}
@@ -0,0 +1,143 @@
1
+ import { getErrorMessage } from '../../errors.js';
2
+ import { writeRecordWithKeyringFallback } from './record-write.js';
3
+ import { createSecureStore, DEFAULT_ACCOUNT_FOR_USER, SecureStoreUnavailableError, } from './secure-store.js';
4
+ const SKIP_REASON_MESSAGES = {
5
+ 'identify-failed': 'could not identify user',
6
+ 'legacy-keyring-unreachable': 'legacy credential is unreachable (keyring offline)',
7
+ 'user-record-write-failed': 'failed to update user records',
8
+ 'marker-write-failed': 'failed to persist migration marker',
9
+ };
10
+ /**
11
+ * One-time migration of a v1 single-user auth state into a v2 multi-user
12
+ * shape. Best-effort: any failure (offline keyring, network error fetching
13
+ * the user, …) leaves the v1 state untouched so the consumer's runtime
14
+ * fallback can keep serving the legacy token until the next attempt.
15
+ *
16
+ * Order of operations is deliberate so the migration is genuinely one-way:
17
+ *
18
+ * 1. `hasMigrated()` short-circuits if the durable marker is already set.
19
+ * 2. Read the v1 token (legacy keyring slot first, then plaintext).
20
+ * 3. `identifyAccount(token)` resolves the v2 `account` shape.
21
+ * 4. `writeRecordWithKeyringFallback` writes the v2 record.
22
+ * 5. Best-effort `setDefaultId(account.id)` so the new record is active.
23
+ * 6. `markMigrated()` persists the marker. **If this fails, we return
24
+ * `skipped` even though the v2 record is on disk** — the marker is
25
+ * what prevents re-migration on the next run.
26
+ * 7. Best-effort legacy keyring delete + `cleanupLegacyConfig()` run
27
+ * concurrently. Failures here are harmless because the marker is set.
28
+ */
29
+ export async function migrateLegacyAuth(options) {
30
+ const { serviceName, legacyAccount, userRecords, hasMigrated, markMigrated, loadLegacyPlaintextToken, identifyAccount, cleanupLegacyConfig, silent, } = options;
31
+ const accountForUser = options.accountForUser ?? DEFAULT_ACCOUNT_FOR_USER;
32
+ const logPrefix = options.logPrefix ?? 'cli';
33
+ if (await hasMigrated()) {
34
+ return { status: 'already-migrated' };
35
+ }
36
+ // One legacy-keyring handle covers both the initial read and the
37
+ // post-success cleanup delete.
38
+ const legacyStore = createSecureStore({ serviceName, account: legacyAccount });
39
+ const legacyToken = await readLegacyToken(legacyStore, loadLegacyPlaintextToken);
40
+ if (legacyToken.kind === 'none')
41
+ return { status: 'no-legacy-state' };
42
+ if (legacyToken.kind === 'keyring-unavailable') {
43
+ return skipped(silent, logPrefix, 'legacy-keyring-unreachable', 'OS keyring unreachable while reading legacy slot');
44
+ }
45
+ let account;
46
+ try {
47
+ account = await identifyAccount(legacyToken.token);
48
+ }
49
+ catch (error) {
50
+ return skipped(silent, logPrefix, 'identify-failed', getErrorMessage(error));
51
+ }
52
+ // `writeRecordWithKeyringFallback` swallows `SecureStoreUnavailableError`
53
+ // internally (writing to `fallbackToken` instead), so any error here is
54
+ // a non-keyring failure — typically a `userRecords.upsert` rejection.
55
+ try {
56
+ await writeRecordWithKeyringFallback({
57
+ secureStore: createSecureStore({
58
+ serviceName,
59
+ account: accountForUser(account.id),
60
+ }),
61
+ userRecords,
62
+ account,
63
+ token: legacyToken.token,
64
+ });
65
+ }
66
+ catch (error) {
67
+ return skipped(silent, logPrefix, 'user-record-write-failed', getErrorMessage(error));
68
+ }
69
+ // Default promotion is best-effort and **only fires when nothing is
70
+ // already pinned**. A retry after a previous `markMigrated()` failure
71
+ // can land on a store where the user has since logged in to a different
72
+ // account and picked it as default — blindly setting the legacy account
73
+ // back as default would silently switch the user.
74
+ try {
75
+ const existingDefault = await userRecords.getDefaultId();
76
+ if (!existingDefault) {
77
+ await userRecords.setDefaultId(account.id);
78
+ }
79
+ }
80
+ catch {
81
+ // best-effort
82
+ }
83
+ // Persist the one-way marker BEFORE legacy cleanup. If this fails, the
84
+ // v2 record is already written but the gate is unset — surface as
85
+ // `skipped` so the caller retries. Without this ordering, a later
86
+ // `logout` could let the next run re-migrate the stale v1 token.
87
+ try {
88
+ await markMigrated();
89
+ }
90
+ catch (error) {
91
+ return skipped(silent, logPrefix, 'marker-write-failed', getErrorMessage(error));
92
+ }
93
+ // Best-effort legacy cleanup — runs concurrently so we don't pay
94
+ // keyring latency followed by config-write latency on every install.
95
+ // The marker is already set, so a failure here can't cause
96
+ // re-migration on the next run. The `Promise.resolve().then(...)`
97
+ // wrappers convert any *synchronous* throw from a consumer-supplied
98
+ // `cleanupLegacyConfig` (or an oddly-implemented `SecureStore`) into
99
+ // a rejected promise that `Promise.allSettled` can swallow.
100
+ await Promise.allSettled([
101
+ Promise.resolve().then(() => legacyStore.deleteSecret()),
102
+ Promise.resolve().then(() => cleanupLegacyConfig?.()),
103
+ ]);
104
+ if (!silent) {
105
+ // No identifier in the log line — `account.id` is typed as `string`
106
+ // but consumers can legitimately use an email or other PII there.
107
+ // Callers that need richer telemetry can compose it from the
108
+ // returned `account`.
109
+ console.error(`${logPrefix}: migrated existing token to multi-user store.`);
110
+ }
111
+ return { status: 'migrated', account };
112
+ }
113
+ async function readLegacyToken(legacyStore, loadLegacyPlaintextToken) {
114
+ let keyringUnavailable = false;
115
+ try {
116
+ const stored = await legacyStore.getSecret();
117
+ if (stored?.trim())
118
+ return { kind: 'found', token: stored.trim() };
119
+ }
120
+ catch (error) {
121
+ if (!(error instanceof SecureStoreUnavailableError))
122
+ throw error;
123
+ keyringUnavailable = true;
124
+ }
125
+ const plaintext = await loadLegacyPlaintextToken();
126
+ if (plaintext?.trim())
127
+ return { kind: 'found', token: plaintext.trim() };
128
+ return keyringUnavailable ? { kind: 'keyring-unavailable' } : { kind: 'none' };
129
+ }
130
+ /**
131
+ * Emit the migration skip line. The stderr text is a fixed phrase keyed off
132
+ * `MigrateSkipReason` so consumer-supplied callbacks (`identifyAccount`,
133
+ * the `UserRecordStore`, …) can't leak emails, paths, or auth diagnostics
134
+ * into logs. The raw error message is still attached to the returned
135
+ * `MigrateAuthResult.detail` for in-process callers that need it.
136
+ */
137
+ function skipped(silent, logPrefix, reason, detail) {
138
+ if (!silent) {
139
+ console.error(`${logPrefix}: skipped legacy auth migration — ${SKIP_REASON_MESSAGES[reason]}.`);
140
+ }
141
+ return { status: 'skipped', reason, detail };
142
+ }
143
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/auth/keyring/migrate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/cli-core",
3
- "version": "0.15.0",
3
+ "version": "0.16.1",
4
4
  "description": "Shared core utilities for Doist CLI projects",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",