feat(auth): add token command group (save + view)#80
Conversation
`ol auth token [token]` saves a personal Outline API token: it validates the token via `auth.info`, resolves the real account identity (user id, name, team), and persists a full account record so `--user`, `account list`, and `auth status` all work. Reuses the same base-URL cascade as `auth login` (`--base-url` -> $OUTLINE_URL -> saved default -> prompt) and prompts for the token with masked input when no argument is given. `ol auth token view` delegates to cli-core's `attachTokenViewCommand` to print the bare stored token to stdout for scripts, with a newline only on a TTY and a refusal when the token comes from $OUTLINE_API_TOKEN. Any `auth.info` failure on save (bad token, wrong instance, unreachable host) is wrapped as a single AUTH_VERIFICATION_FAILED error with a base-URL hint, rather than leaking the raw API string. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
doistbot
left a comment
There was a problem hiding this comment.
This PR introduces the new auth token command group for saving and viewing Outline API tokens, along with helpful account identity resolution and base-URL cascading. These additions are a solid step toward completing the authentication roadmap and nicely expand the CLI's utility for CI workflows and AI agents. There are a few areas to refine, primarily concerning the removal of the positional token argument to comply with secrets management standards, fixing the interactive masked prompt rendering, and consolidating duplicated authentication and prompt helpers. Some additional polish around test coverage, preventing global state leakage in tests, and ensuring error messages consistently hide raw API details will round out the implementation.
- Fix masked prompt: it dropped readline's ANSI line-clear codes, so the
label repeated on every keystroke. Consolidate into a shared
`prompt(question, { hidden })` in auth-provider (mute-after-prompt
pattern) and drop the duplicate `promptHiddenToken`.
- Collapse any `auth.info` verification failure into a single stable
`AUTH_VERIFICATION_FAILED` with base-URL hints, never interpolating the
raw API/network string.
- Extract `identifyAccount(token, baseUrl, oauthClientId?)` and reuse it
from the OAuth `validate` hook and `auth token` so identity resolution
lives in one place.
- `resolveBaseUrl`: explicit `{ baseUrl?: unknown }` input shape and a
non-TTY fast path that returns the configured default instead of
blocking a CI shell on a prompt.
- Fix the SKILL doc: `--user` is a root flag (`ol --user <ref> auth token
view`), not a subcommand option.
- Tests: assert the wrapped error contract (message hidden, hints
present), snapshot/restore `process.stdin.isTTY`, and cover the masked
prompt save path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@doistbot /review |
doistbot
left a comment
There was a problem hiding this comment.
This PR successfully implements the new auth token command group, enabling users to save and view personal Outline API tokens. The addition is highly valuable and integrates well with the existing authentication workflows. To fully align with security standards and ensure long-term maintainability, a few updates are needed, such as strictly enforcing interactive-only token input to prevent shell history leaks, refactoring duplicated reporting logic, and avoiding private Node internals in the custom prompt. Addressing these alongside a few test scoping and coverage gaps will help completely solidify this excellent feature.
- Masked prompt no longer pokes readline's private `_writeToOutput`; it
routes echo through a muted `Writable` passed as `output` (public API).
- Extract `logSaveResult` in auth-output.ts and reuse it from both the
`auth login` success hook and `auth token`, so the two save flows share
one machine-output/warning path (mirrors `logClearResult`).
- Fix the `NO_TOKEN` hint: it no longer implies `auth token` reads
`OUTLINE_API_TOKEN` as input — it's framed as an alternative auth method.
- `stringFlag` now takes a value (`stringFlag(options.baseUrl)`); callers
updated.
- Tests: use `.mock*Once` to stop hoisted-mock bleed, capture the rejection
with `.catch`, add an isolated `prompt({ hidden })` masking test (mocked
`node:readline/promises`) and a non-TTY `resolveBaseUrl` fallback test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## [1.10.0](v1.9.0...v1.10.0) (2026-05-24) ### Features * **auth:** add `token` command group (save + view) ([#80](#80)) ([99789cc](99789cc))
|
🎉 This PR is included in version 1.10.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
Implements the
auth tokencommand group.ol auth token [token]— saves a personal Outline API token. Validates viaauth.info, resolves the real account identity (user id, name, team), and persists a full account record so--user,account list, andauth statusall work. Reusesauth login's base-URL cascade (--base-url→$OUTLINE_URL→ saved default → prompt). With no argument it prompts for the token with masked input; in a non-interactive shell it errors withNO_TOKEN.ol auth token view— delegates to cli-core'sattachTokenViewCommand: prints the bare stored token to stdout for scripts (newline only on a TTY), honours--user, and refuses (TOKEN_FROM_ENV) when the token comes from$OUTLINE_API_TOKEN.auth.infofailure on save is wrapped as a singleAUTH_VERIFICATION_FAILEDerror with a base-URL hint, instead of leaking the raw API string.Test plan
npm run type-check— cleannpm run test— 218 + 7 new tests passnpm run check:skill-sync— in syncview(bare token, no trailing newline when piped),$OUTLINE_API_TOKENrefusal,NO_TOKENin non-TTY, bad-token + wrong-base-url →AUTH_VERIFICATION_FAILEDol auth tokenin a TTY) — not automatable here🤖 Generated with Claude Code