Skip to content

feat(dashboard): add dashboard auth, app management, and first-time setup wizard#36

Merged
AaronDDM merged 20 commits intomainfrom
adm/add-dashboard-registration-login
Mar 25, 2026
Merged

feat(dashboard): add dashboard auth, app management, and first-time setup wizard#36
AaronDDM merged 20 commits intomainfrom
adm/add-dashboard-registration-login

Conversation

@AaronDDM
Copy link
Copy Markdown
Collaborator

@AaronDDM AaronDDM commented Mar 23, 2026

Summary

  • Dashboard auth: Register and login via SSO (Google, Microsoft, GitHub) with device-code flow, MFA support, and DPoP-protected tokens
  • Application management: List, create, and select active applications via the Dashboard GraphQL API
  • API key management: Create API keys and activate them directly into the CLI keyring (keys are never printed to stdout)
  • nylas init wizard: Guided first-time setup that takes a new user from zero to working CLI in one command — account creation, app setup, API key generation, and grant sync
  • nylas config reset: Full CLI reset (credentials, dashboard session, grants, config) with confirmation prompt
  • Redesigned first-run welcome screen: Branded, visually polished experience with box-drawing UI

First-Run Welcome Screen

When a new user runs nylas with no configuration, they see this:

  ╭──────────────────────────────────────────╮
  │                                          │
  │   ◈  N Y L A S   C L I                  │
  │                                          │
  │   Email, calendar, and contacts          │
  │   from your terminal.                    │
  │                                          │
  ╰──────────────────────────────────────────╯

  Get started in under a minute:

    ❯ nylas init                Guided setup
      nylas init --api-key      Quick setup with existing key

  ╭─ What you can do ────────────────────────╮
  │                                          │
  │  email       Send, search, and read      │
  │  calendar    Events and availability     │
  │  contacts    People and groups           │
  │  webhook     Real-time notifications     │
  │  ai          Chat with your data         │
  │                                          │
  ╰──────────────────────────────────────────╯

  nylas --help              All commands
  https://cli.nylas.com     Documentation

With terminal colors: ◈ N Y L A S C L I in bold cyan, box borders dim, capability names cyan, ❯ nylas init bold cyan, secondary options dim. No new dependencies — uses existing fatih/color + Unicode box-drawing characters.

To test: nylas config reset --force && nylas

nylas init — First-Time User Experience

The wizard walks through 4 steps:

  1. Account — Register, login via SSO, or paste an existing API key
  2. Application — Auto-create or select from existing apps
  3. API Key — Generate and activate into the keyring
  4. Grants — Sync existing email accounts from the Nylas API

Key design decisions:

  • Re-entrant: running nylas init again skips completed steps
  • Non-interactive: nylas init --api-key <key> for CI/scripts
  • Graceful recovery: each step prints manual commands on failure
  • Errors propagate: wizard no longer reports success when steps 2/3 fail

nylas config reset

Full CLI reset that clears all stored state:

  • API credentials (API key, client ID, client secret)
  • Dashboard session (login tokens, selected app)
  • Grants (authenticated email accounts)
  • Config file (reset to defaults)

Requires confirmation by default, --force to skip. Individual resets (nylas auth config --reset, nylas dashboard logout) remain scoped to their own domains.

Bug Fixes

  • Wizard false success: Steps 2 (application) and 3 (API key) now return errors instead of swallowing them and printing "Setup complete"
  • SSO ignores --org: orgPublicID is now threaded through the full SSO flow (poll + MFA) so multi-org users can target the correct organization
  • Dashboard logout stale app: clearTokens() now also clears dashboard_app_id and dashboard_app_region to prevent reusing a previous account's app context
  • Wizard grant sync: User's default grant selection from the multi-grant prompt is now persisted to config.yaml (was only written to keyring)
  • DPoP redirect bug: HTTP clients for DPoP-protected requests no longer follow redirects, preventing htu mismatch errors when staging URLs redirect to production

New Files

File Purpose
internal/cli/setup/setup.go nylas init Cobra command
internal/cli/setup/wizard.go 4-step interactive wizard
internal/cli/setup/wizard_helpers.go Menus, display, verification helpers
internal/cli/setup/detect.go IsFirstRun() and GetSetupStatus()
internal/cli/setup/grants.go Shared SyncGrants() (extracted from auth/config)
internal/cli/setup/setup_test.go Table-driven unit tests
internal/cli/dashboard/exports.go Exported wrappers for dashboard services
internal/cli/config/reset.go nylas config reset command
internal/cli/config/reset_test.go Tests for reset command
internal/app/auth/config_test.go Tests for ResetConfig scope

Test plan

  • go build ./... compiles
  • go vet ./... passes
  • Unit tests pass (go test ./internal/cli/setup/...)
  • Config/reset tests pass (go test ./internal/cli/config/...)
  • Auth config tests pass (go test ./internal/app/auth/...)
  • Full unit test suite passes (make test-unit)
  • Linter passes (golangci-lint run)
  • Security scan passes (make security)
  • Manual: nylas config reset --force && nylas shows new welcome
  • Manual: nylas init interactive wizard with SSO
  • Manual: nylas init --api-key <key> non-interactive
  • Manual: nylas init re-run skips completed steps
  • Manual: nylas dashboard login --google --org <org> targets correct org
  • Manual: nylas dashboard logout clears app selection

🤖 Generated with Claude Code

AaronDDM and others added 2 commits March 23, 2026 11:16
Add `nylas dashboard` command group for authenticating with the Nylas
Dashboard and managing applications via the API gateway.

Auth flows:
- Email/password registration with email verification
- Email/password login with MFA support
- SSO device flow (Google, Microsoft, GitHub)
- Session refresh and logout
- DPoP proof-of-possession (Ed25519) on all requests

Application management:
- `nylas dashboard apps list` — queries both US and EU gateways
- `nylas dashboard apps create` — creates apps in a specified region

UX:
- Interactive auth method picker (SSO first, recommended)
- Direct flags for non-interactive use (--google, --email, --user, etc.)
- Spinners on all network operations
- User-friendly errors with hints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- `nylas dashboard apps apikeys create` — creates API keys with interactive
  delivery options (activate in CLI keyring, copy to clipboard, or print)
- `nylas dashboard apps apikeys list` — lists API keys for an application
- `nylas dashboard apps use <app-id> --region <region>` — sets active app
  so --app/--region flags aren't needed on every command
- `nylas dashboard status` now shows the active app
- Improved GraphQL error messages to surface UAS error details from extensions
- Auto-generated unique key names (CLI-<timestamp>) to avoid name conflicts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@AaronDDM AaronDDM requested a review from qasim-nylas March 23, 2026 15:34
qasim-nylas
qasim-nylas previously approved these changes Mar 23, 2026
Copy link
Copy Markdown
Collaborator

@qasim-nylas qasim-nylas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the "print to terminal" option from API key delivery to prevent
keys from leaking in terminal scrollback, shell history, or CI logs.

Replace with "save to file" which writes to a temp file with 0600
permissions. The three options are now:
  1. Activate in CLI keyring (key never leaves the process)
  2. Copy to clipboard (key never appears in terminal output)
  3. Save to temp file (restrictive permissions, user deletes after)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AaronDDM AaronDDM self-assigned this Mar 23, 2026
Email/password registration is disabled for the CLI. Users must use
SSO (Google, Microsoft, or GitHub) to register. Login via email/password
remains available.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AaronDDM AaronDDM requested a review from qasim-nylas March 24, 2026 02:32
qasim-nylas
qasim-nylas previously approved these changes Mar 24, 2026
Copy link
Copy Markdown
Collaborator

@qasim-nylas qasim-nylas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Introduce a guided onboarding experience for new CLI users. Running
`nylas` with no args now detects first-run state and shows a welcome
message pointing to `nylas init`. The wizard walks through four steps:

1. Account — register or login via SSO, or paste an existing API key
2. Application — auto-create or select from existing apps
3. API Key — generate and activate into the keyring
4. Grants — sync existing email accounts from the Nylas API

Key design decisions:
- Re-entrant: running `nylas init` again skips completed steps
- Non-interactive: `nylas init --api-key <key>` for CI/scripts
- Graceful recovery: each step prints manual commands on failure
- Shared grant sync: extracted from auth/config.go for reuse

New files: internal/cli/setup/ (detect, wizard, grants, helpers, tests)
           internal/cli/dashboard/exports.go (exported service wrappers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AaronDDM AaronDDM changed the title feat(dashboard): add dashboard auth, app management, and API key commands feat(dashboard): add dashboard auth, app management, and first-time setup wizard Mar 24, 2026
AaronDDM and others added 6 commits March 24, 2026 11:39
Adds the full Dashboard section covering account management (register,
login, SSO), application management (list, create, set active), and
API key management (list, create with delivery options).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a global reset subcommand under `nylas config` that clears all
stored data (API credentials, dashboard session, grants, config file)
with a confirmation prompt. This ensures `IsFirstRun()` returns true
afterward so first-time setup guidance is shown.

Individual resets (`nylas auth config --reset`, `nylas dashboard logout`)
remain unchanged and scoped to their own domains.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the plain-text welcome message with a visually polished
first-run experience using Unicode box-drawing characters, color
hierarchy, and a capabilities overview. No new dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…quests

DPoP proofs are bound to the request URL via the htu claim. When the
server redirects (e.g., staging → production), Go's http.Client silently
follows the redirect but the DPoP proof still contains the original URL,
causing "Invalid DPoP htu" errors on the destination server.

Fix by disabling automatic redirect following and returning a clear
error message when a redirect is received.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Wizard reports success on failure: steps 2 (application) and 3
   (API key) now return errors instead of silently continuing to
   "Setup complete".

2. SSO flow ignores --org flag: orgPublicID is now threaded through
   runSSO → pollSSO → SSOPoll and CompleteMFA so multi-org users
   can target the correct organization.

3. Dashboard logout leaves stale app selection: clearTokens() now
   also deletes dashboard_app_id and dashboard_app_region to prevent
   reusing a previous account's app context after re-login.

4. Wizard default grant not persisted to config.yaml: the user's
   grant selection is now written back to result.DefaultGrantID so
   updateConfigGrants persists it correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AaronDDM AaronDDM requested a review from qasim-nylas March 24, 2026 19:59
qasim-nylas
qasim-nylas previously approved these changes Mar 24, 2026
Copy link
Copy Markdown
Collaborator

@qasim-nylas qasim-nylas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Client secret was printed via fmt.Printf on app creation, leaking it
to terminal scrollback, CI logs, and screen captures. Apply the same
secure delivery pattern used for API keys: clipboard or temp file with
0600 permissions. The secret is never written to stdout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AaronDDM and others added 4 commits March 24, 2026 22:25
Replace all numbered-menu prompts with huh Select widgets that support
arrow-key navigation, and replace raw readLine/readPassword calls with
huh Input/Password fields.

Converted prompts:
- Account path selection (wizard)
- SSO provider selection (wizard + dashboard)
- Application selection (wizard)
- Region selection (wizard)
- Auth method selection (dashboard login/register)
- Organization selection (dashboard)
- API key delivery (dashboard)
- Client secret delivery (dashboard)
- Default grant selection (setup)
- Privacy policy confirmation (dashboard)
- Email/password/MFA inputs (dashboard login)

New shared helpers in common/prompt.go:
- Select[T]() — generic arrow-key select menu
- ConfirmPrompt() — yes/no with arrow keys
- InputPrompt() — text input with placeholder
- PasswordPrompt() — masked input

All prompts fall back gracefully in non-TTY environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Long description duplicated every subcommand above Cobra's
auto-generated Available Commands list. Replace with a 4-line
quick start guide and let Cobra handle the command listing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows a compact "Nylas - CLI" banner in box-drawing characters when
running `nylas` with no args. Only renders on the root command, not
on subcommand help.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create a consistent visual identity across all CLI prompts using a
custom huh theme with the Nylas brand color palette:

  - Primary (Cyan #00BCD4): titles, selectors, cursors, active buttons
  - Success (Green #4CAF50): selected options, checkmarks
  - Warning (Amber #FFC107): caution messages
  - Error (Red #F44336): error indicators
  - Muted (Gray #6B7280): descriptions, placeholders, navigation hints

The theme is applied to all Select, Confirm, Input, and Password
prompts via the shared helpers in common/prompt.go.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AaronDDM and others added 3 commits March 24, 2026 22:43
Replace the formal box-drawing ASCII art with a more casual
ANSI shadow block style for the help header.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ASCII art and welcome screen were using hardcoded fatih/color Cyan
instead of the theme's ColorPrimary. Add a lipgloss Brand style derived
from ColorPrimary and use it for all branded elements so changing the
theme color in one place updates everything.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AaronDDM AaronDDM requested a review from qasim-nylas March 25, 2026 11:32
Copy link
Copy Markdown
Collaborator

@qasim-nylas qasim-nylas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@AaronDDM AaronDDM merged commit 40211e8 into main Mar 25, 2026
6 checks passed
@AaronDDM AaronDDM deleted the adm/add-dashboard-registration-login branch March 25, 2026 11:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants