Skip to content

feat: stored credential profiles with OS keyring - #1

Merged
paymog merged 1 commit into
mainfrom
feat/auth-profiles
Jun 5, 2026
Merged

paymog merged 1 commit into
mainfrom
feat/auth-profiles

Conversation

@paymog

@paymog paymog commented Jun 5, 2026

Copy link
Copy Markdown
Owner

What

Adds a groundcover auth command group for managing named credential profiles, as an alternative to exporting GROUNDCOVER_API_KEY every session.

  • API keys live in the OS keyring (macOS Keychain / Linux libsecret / Windows Credential Manager).
  • Only non-secret metadata (backend ID, base URL, tenant UUID) is written to ~/.config/groundcover/profiles.yaml (XDG-aware; %AppData% on Windows). The file never contains a key.
groundcover auth login [name]   # prompts for key (or --key); validates vs API before saving
groundcover auth list           # * marks default
groundcover auth default <name>
groundcover auth logout <name> [-f]
groundcover auth token          # print resolved key
groundcover auth status         # show which source resolved
groundcover --profile <name> <command>

Credential precedence

  1. --api-key flag / GROUNDCOVER_API_KEY env
  2. --profile <name> → stored profile
  3. default profile → stored profile

Explicit key + --profile is rejected as ambiguous. Env-var auth stays the simple/CI path and takes precedence. First profile added becomes the default.

Design

Mirrors schpet/linear-cli (on-disk file holds no secrets) adapted to Go:

  • go-keyring behind a Backend interface so tests inject an in-memory fake.
  • YAML to match the existing yaml.v3 dep (no new TOML lib).
  • New internal/credstore package; config.Resolve centralizes the precedence chain.

Testing

  • Unit tests for the store (default assignment, persistence-without-secrets, removal reassignment) and the resolver (all precedence branches + ambiguity guard).
  • Verified live end-to-end against the API: login validates + stores, auth token reads back from the keychain, --profile and default-profile both resolve real monitors list calls, auth logout removes the keychain entry (confirmed via security find-generic-password).

🤖 Generated with Claude Code

Add `groundcover auth` commands for managing named credential profiles.
API keys are stored in the OS keyring (Keychain / libsecret / Credential
Manager); only non-secret metadata (backend ID, base URL, tenant UUID) is
written to ~/.config/groundcover/profiles.yaml.

Credential precedence: explicit --api-key/GROUNDCOVER_API_KEY env, then
--profile <name>, then the default profile. Combining an explicit key with
--profile is rejected as ambiguous. Env-var auth remains the simple/CI path
and takes precedence over stored profiles.

Commands: auth login/list/default/logout/token/status. login validates the
key against the API before persisting. First profile added becomes default.

Design mirrors schpet/linear-cli (file holds no secrets) adapted to Go:
go-keyring backend behind a Backend interface for test injection, YAML to
match the existing yaml.v3 dep.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@paymog
paymog merged commit 63d1409 into main Jun 5, 2026
1 check passed
@paymog
paymog deleted the feat/auth-profiles branch June 5, 2026 19:00
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.

1 participant