Repository navigation
Adopt profile package for multi-account auth - #78
Conversation
|
Potential breaking changes detected:
Review carefully before merging. Consider a major version bump. |
There was a problem hiding this comment.
3 issues found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="internal/commands/root.go">
<violation number="1" location="internal/commands/root.go:639">
P1: Bug: legacy token is silently dropped when migration save fails. If `credsSaveAccountToken` returns an error, `cfg.Token` is never set and the function returns early, leaving the user unauthenticated despite having a valid token in the legacy store. The token should be used regardless of whether migration succeeds.</violation>
</file>
<file name="internal/commands/auth.go">
<violation number="1" location="internal/commands/auth.go:38">
P2: Missing `globalCfg.AddAccount(account)` call — switching to an account doesn't register it in the known accounts list, so `auth list` and `auth logout --all` won't see it.</violation>
<violation number="2" location="internal/commands/auth.go:43">
P2: Config save error silently discarded — if `globalCfg.Save()` fails here, the user sees "Token saved" but account/active-account config is lost. The YAML-only branch handles this error; this branch should too.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Pull request overview
This PR introduces multi-account authentication support for the Fizzy CLI. Instead of storing a single credential, tokens are now stored per-account under token:<account> keys in the credential store. The PR also includes commands for listing, switching between, and logging out of multiple accounts, along with backward-compatible migration of existing single-key tokens.
Changes:
- Account-scoped credential storage (
token:<account>keys) with legacy migration and downgrade compatibility - New
auth list,auth switch, andauth logout --allcommands for multi-account management - Config
Accountsfield to track known accounts (workaround for keyring not supporting key enumeration)
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
internal/config/config.go |
Added Accounts field and AddAccount/RemoveAccount helpers to Config struct |
internal/commands/root.go |
Account-scoped credential functions, updated resolveToken with account lookup and legacy migration |
internal/commands/auth.go |
Updated login/logout for per-account storage, added list and switch commands, --all logout flag |
internal/commands/signup.go |
Uses credsSaveAccountToken and registers account on signup |
internal/commands/setup.go |
Uses credsSaveAccountToken and registers account on setup |
internal/commands/auth_test.go |
Comprehensive tests for new key scheme, list, switch, migration, YAML-only mode, and --account flag |
skills/fizzy/SKILL.md |
Documentation for new auth subcommands |
internal/skills/SKILL.md |
Mirror documentation update |
SURFACE.txt |
Surface manifest updated with new commands and flags |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace custom Config.Accounts/AddAccount/RemoveAccount with profile.Store backed by ~/.config/fizzy/config.json. Credential keys change from "token:<account>" to "profile:<name>" via credstore. Key changes in root.go: - Add profile.Store initialization and --profile global flag - resolveProfile() uses profile.Resolve() 6-step chain - Profile settings (layer 3) outrank local/global YAML config (4-5) but yield to env vars (layer 2) and flags (layer 1) - Credential helpers: credsSaveProfileToken, credsLoadProfileToken, credsDeleteProfileToken with legacy key migration - ensureProfile() does delete-then-create for upsert semantics Config precedence: flags > env vars > profiles > local config > global > defaults
All auth subcommands now operate on profiles instead of accounts:
- auth login: saves to "profile:<name>" credstore key, creates profile
- auth logout: deletes profile and "profile:<name>" key
- auth logout --all: cleans all three legacy key formats
("profile:<name>", "token:<account>", bare "token")
- auth list: reads from profile.Store.List()
- auth switch: calls profiles.SetDefault(), updates YAML config
- auth status: shows profile key in output
Tests rewritten with profile.Store injection via SetTestProfiles().
Covers: invalid --profile flag errors, env var precedence over profile
settings, ensureProfile upsert, logout --all legacy key cleanup.
setup: create profile via ensureProfile() + profiles.SetDefault() signup: saveSignupConfig() creates profile instead of AddAccount() Both use credsSaveProfileToken for credential storage.
23adaf0 to
8b4246a
Compare
- README/AGENTS: 5-level precedence, --profile flag, FIZZY_ACCOUNT deprecation - SKILL.md: --account → --profile, precedence includes profile layer - SURFACE.txt: regenerated with --profile replacing --account globally
TestPrecedenceChainIntegration wires up real config files, credstore, and profile store, then runs config.Load() → resolveProfile() → resolveToken() → flag override — the same sequence as PersistentPreRunE. Three cases lock the contract: - profile outranks YAML config for APIURL and board - env vars beat profile for all fields - --api-url flag beats env and profile
8b4246a to
f41b529
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- ensureProfile: use json.Marshal for board value instead of manual quoting - auth switch: fall back to credsLoadLegacyToken when profile key missing
Replace remaining "account" references in auth command examples and troubleshooting sections with "profile" terminology.
Summary
Replace custom account-scoped credential storage with the
profilepackage frombasecamp/cli. Each Fizzy account becomes a named profile backed by~/.config/fizzy/config.json, with tokens stored underprofile:<name>in the credential store.--profileflag andFIZZY_PROFILEenv var select the active profile (FIZZY_ACCOUNTaccepted as deprecated alias)auth login/logout/status/list/switchoperate on profilestoken,token:<account>) auto-migrate toprofile:<name>on first run;logout --allcleans all formatsConfig precedence
--token,--profile,--api-url,--board)FIZZY_TOKEN,FIZZY_PROFILE,FIZZY_API_URL,FIZZY_BOARD)config.json).fizzy.yaml)config.yaml)Changed files
Accounts/AddAccount/RemoveAccount; update Load() docs for 6-layer precedenceresolveProfile()withprofile.Resolve(), profile-scoped credential helpers,ensureProfile()upsert,--profileflaglogout --allcleans three legacy key formatsensureProfile()+SetDefault()--profile, 5-level precedence, path-agnostic config referencesTest plan
makepasses (fmt, vet, build, unit tests)make test-e2ewith credentialsfizzy setup→ profile created inconfig.jsonfizzy auth login <token> --profile <name>→fizzy auth list→fizzy auth switchFIZZY_PROFILE=staging fizzy auth status→ verify env var resolution