refactor: delegate auth flow to @doist/cli-core/auth#215
Merged
Conversation
Replaces the local OAuth coordination (pkce, oauth, oauth-server, login) with @doist/cli-core/auth's runOAuthFlow + attachLoginCommand. A new TwistAuthProvider handles the twist-specific bits — Dynamic Client Registration, client_secret_basic token exchange, and getSessionUser validation — while cli-core owns the PKCE primitives, callback server, browser open, and timeout. Branded success/error HTML preserved verbatim in src/lib/auth-pages.ts and passed through renderSuccess / renderError. `tw auth login` gains --callback-port, --json, and --ndjson for free from attachLoginCommand. Net: −146 LOC, 580/580 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
doistbot
reviewed
May 11, 2026
Member
doistbot
left a comment
There was a problem hiding this comment.
This PR successfully delegates the OAuth flow to @doist/cli-core/auth by introducing a custom Twist provider and token store while preserving the existing branded auth pages. The changes cleanly reduce local orchestration boilerplate and standardize the login command's behavior across the CLI. A few areas need adjustment, primarily restoring structured error handling for network failures, refining the token store's account metadata handling, updating the skill content for the newly added command flags, and addressing a couple of minor test wiring gaps.
- [P1] Rewrap raw fetch rejections + JSON-parse failures in `prepare()` and
`exchangeCode()` as `AUTH_FAILED` CliError with hints, restoring the
catch-and-convert behavior the old `oauth.ts` helpers had.
- [P2] Narrow `TwistAccount` to the fields that round-trip through the local
token store ({ id, label, authMode, authScope }). Persist `authUserId` /
`authUserName` alongside the token so `TokenStore.active()` rebuilds the
same identity that `validateToken()` and `set()` work with — no more
placeholder 'twist' account. `active()` returns null when the stored
token predates this adapter (env var or pre-upgrade config).
- [P2] Suppress `console.log` in `onSuccess` when `--json` or `--ndjson` is
active so the cli-core machine-output envelope on stdout stays clean.
- [P2] Document `--callback-port`, `--json`, `--ndjson` on `tw auth login`
in `SKILL_CONTENT` and regenerate the published skill file.
- [P2] Switch the provider test mock to `importOriginal` for the real
`NoTokenError` instead of a handcrafted stub.
- [P2] Add `attachLoginCommand` wiring assertions to `auth.test.ts` —
provider/store/preferredPort/renderers and scope resolution.
- [P2] Add rejected-fetch (network failure) cases to provider tests for
both `prepare()` and `exchangeCode()`, and consolidate the existing
error-path tests into single shared cases per method.
Tests: 579 pass; type-check, lint, and oxfmt all clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The local declarations in auth.ts (TokenStorageResult, SaveApiTokenOptions, AuthMetadata, AuthProbeMetadata, AuthProbeResult) and auth-provider.ts (TwistAccount, TwistHandshake, TwistTokenStore) are only used as types — no implements, no declaration merging — so type aliases express intent more directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
scottlovegrove
added a commit
to Doist/outline-cli
that referenced
this pull request
May 11, 2026
## Summary - Drops the bespoke OAuth stack (`src/lib/pkce.ts`, `oauth.ts`, `oauth-server.ts`, the entire login action in `commands/auth.ts`) and delegates the flow to `@doist/cli-core/auth`'s `runOAuthFlow` + `attachLoginCommand`. Mirrors [twist-cli#215](Doist/twist-cli#215). - New `OutlineAuthProvider` (`src/lib/auth-provider.ts`) owns the outline-specific behaviour: - `authorize()` — builds the `/oauth/authorize` URL with cli-core's `generateVerifier` / `deriveChallenge`. Resolves `--base-url` / `--client-id` from flags → env → config → interactive prompt. - `exchangeCode()` — form-urlencoded POST to `/oauth/token`. Public client — no `client_secret`, no `Authorization: Basic` header (unlike twist). - `validateToken()` — hits `auth.info` with the unsaved token via a new `apiRequest(path, body, { token, baseUrl })` override so we can identify the user before persisting. - New `OutlineTokenStore` adapter maps the cli-core account onto the existing config file (adds `auth_user_id` / `auth_user_name` to round-trip the identity through `store.active()`). - Branded success / error HTML preserved byte-for-byte in `src/lib/auth-pages.ts` and passed via `renderSuccess` / `renderError`. - `ol auth login` gains `--read-only`, `--callback-port`, `--json`, `--ndjson` for free from `attachLoginCommand`; `--base-url` / `--client-id` chained onto the returned command. - **Breaking:** `ol auth login --token <token>` flag is gone. Login is OAuth-only now. Set `OUTLINE_API_TOKEN` env var if you need to script with a personal token. - Net: 14 files changed, +625 / −688. 115 tests pass. ## Test plan - [x] `npm run type-check` - [x] `npm run lint:check` - [x] `npm test` (115 tests pass) - [x] `npm run build` - [x] `npm run check:skill-sync` - [x] `ol auth login --help` lists `--read-only`, `--callback-port`, `--json`, `--ndjson`, `--base-url`, `--client-id` - [ ] Smoke: `ol auth logout && ol auth login --base-url https://… --client-id …` against a real Outline workspace — branded success page renders, token persisted, terminal prints green "Authenticated to … as …" - [ ] `ol auth status` reports team + user - [ ] `ol auth login --json` emits machine-readable success envelope 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 11, 2026
Contributor
|
🎉 This PR is included in version 2.36.4 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/lib/pkce.ts,oauth.ts,oauth-server.ts,commands/auth/login.tsbody) and delegates the flow to@doist/cli-core/auth'srunOAuthFlow+attachLoginCommand.TwistAuthProvider(src/lib/auth-provider.ts) owns the twist-specific behaviour:prepare()— Dynamic Client Registration viaPOST /oauth/register.authorize()— builds the twist authorize URL using cli-core'sgenerateVerifier/deriveChallenge.exchangeCode()—client_secret_basictoken exchange with the PKCE verifier.validateToken()—users.getSessionUserto populate theTwistAccount.TwistTokenStoreadapter wraps the existingsaveApiToken/probeApiToken/clearApiTokenso cli-core writes the token through the same dual-storage (keyring + config fallback) twist already uses elsewhere.src/lib/auth-pages.tsand passed toattachLoginCommandviarenderSuccess/renderError.tw auth logingains--callback-port,--json, and--ndjsonfor free fromattachLoginCommand(was--read-onlyonly).src/lib/auth-provider.test.ts.Test plan
npm run type-checknpm run lint:check(oxlint + oxfmt)npm test(580 tests pass)npm run buildtw auth logout && tw auth loginagainst twist.com — branded success page renders, token persisted, green checkmark printedtw auth login --helplists--read-only,--callback-port,--json,--ndjson