Fix scope selection misleading Launchpad users#232
Conversation
Review carefully before merging. Consider a major version bump. |
There was a problem hiding this comment.
2 issues found across 12 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/profile.go">
<violation number="1" location="internal/commands/profile.go:303">
P2: Silently discarding the `atomicWriteJSON` error here means a config-write failure goes unnoticed — the user sees the scope in the success output, but it won't survive a restart. Every other `atomicWriteJSON` call site in this file returns the error. At minimum, log a warning or return an error to stay consistent.</violation>
</file>
<file name="internal/auth/auth_test.go">
<violation number="1" location="internal/auth/auth_test.go:1180">
P2: Data race on `tokenCalled`: written in the `httptest` handler goroutine and read on the main goroutine without synchronization. Use `atomic.Bool` (or protect with a mutex) to avoid a `-race` failure.</violation>
</file>
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82e8d9866d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
This PR makes OAuth scope handling provider-aware so Launchpad logins no longer present or persist misleading “read-only” scope information (since Launchpad doesn’t support scopes), while keeping BC3 scope support with a BC3 default of "read".
Changes:
- Updated auth login flow to return a
LoginResultcontaining the effective scope determined by the OAuth provider (BC3 vs Launchpad), and to clear/ignore scope for Launchpad. - Removed scope selection from the setup wizard and suppressed scope display in user-facing outputs for Launchpad credentials (status/doctor/profile show).
- Updated defaults, tests, and docs to reflect provider-specific scope behavior.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| skills/basecamp/SKILL.md | Updates troubleshooting guidance to reflect BC3-only --scope behavior. |
| internal/config/config.go | Removes default pre-login scope from config defaults. |
| internal/config/config_test.go | Adjusts config default scope expectation to empty. |
| internal/commands/wizard.go | Removes scope picker and displays effective access only when applicable. |
| internal/commands/profile.go | Stops pre-setting scope; patches profile scope post-login based on effective provider scope. |
| internal/commands/profile_test.go | Updates profile defaults expectation; removes scope validation test in favor of auth-layer validation. |
| internal/commands/doctor.go | Hides scope in verbose doctor output for Launchpad credentials. |
| internal/commands/auth.go | Suppresses Launchpad scope in status output; prints effective access after login when available. |
| internal/auth/auth.go | Introduces LoginResult; implements provider-aware scope rules (Launchpad clears, BC3 defaults to read). |
| internal/auth/auth_test.go | Updates tests for new Login() return type; adds coverage for Launchpad clearing scope and BC3 defaulting to read. |
| install.md | Updates install verification output expectations. |
| README.md | Updates quick-start auth examples to avoid implying Launchpad supports read-only scoping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
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/profile.go">
<violation number="1" location="internal/commands/profile.go:252">
P2: Incomplete in-memory cleanup on login failure: `app.Config.BaseURL` is not restored to its previous value, while the other two modified fields (`Profiles`, `ActiveProfile`) are cleaned up. If the caller continues after this error (e.g. a TUI wizard retrying with a different profile), `BaseURL` will still point at the failed profile's URL.</violation>
</file>
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
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
64429a2 to
cbfd640
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Launchpad OAuth doesn't support scopes, so exposing scope selection to all users creates a false sense of security — selecting "read-only" still grants a full read+write token. This makes scope provider-aware: - Add LoginResult return type carrying effective scope and OAuth type - Validate scope in Login() (single source of truth) - Clear scope for Launchpad; default to "read" for BC3 - Remove scope picker from setup wizard - Suppress scope display for Launchpad in auth status, doctor, profile - Remove misleading "read" default from config Fixes #220
- Update 5 Login() callers for new (*LoginResult, error) return type - Add TestLoginLaunchpadClearsScope: scope cleared for Launchpad - Add TestLoginBC3DefaultsToRead: BC3 defaults to "read" scope - Add TestLoginRejectsInvalidScope: validation without network calls - Update TestProfileCreateDefaultValues: no scope in default profile - Remove TestProfileCreateRejectsInvalidScope: validation moved to Login() - Update config default assertion from "read" to ""
- Note --scope flag is BC3 OAuth only - Remove implied read-only default from auth examples - Update troubleshooting to clarify --scope full requires BC3
Profile create wrote the profile to config.json before calling Login(), so --scope admin would fail validation but leave a dangling profile entry (and potentially set it as default). Move config persistence after Login() succeeds. Also add command-level tests for display-side scope sanitization: auth status, doctor --verbose, and profile show all suppress scope for Launchpad credentials.
- Use atomic.Bool for tokenCalled in TestLoginLaunchpadClearsScope to avoid race between httptest handler and test goroutine - Add --scope full example to README auth section - Clarify install.md expected output for BC3 vs Launchpad
Snapshot ActiveProfile and BaseURL before mutation so all three fields are restored if Login() fails, not just Profiles and ActiveProfile.
cbfd640 to
3f551e4
Compare
Summary
Login()now returns aLoginResultwith the effective scope determined by the OAuth provider, not user input--scopewas passed); BC3: defaults to"read", respects explicit--scopeFixes #220
Test plan
make checkpasses (fmt, vet, lint, unit tests, 263 e2e tests, surface snapshot)basecamp auth loginagainst Launchpad — no scope prompt, no scope in output,auth statusshows no scopebasecamp auth login --scope readagainst Launchpad — warning logged, scope not storedbasecamp auth login --scope readagainst BC3 — scope sent, displayed, stored correctlybasecamp profile show <launchpad-profile>— no scope displayed even if legacy "read" storedbasecamp doctor --verbose— no scope for Launchpad credentialsSummary by cubic
Scope is now a BC3-only concept. Launchpad logins no longer show or store scope;
--scopeis ignored with a warning, and profile create defers config writes and restores in-memory config on login failure to prevent dangling profiles (fixes #220).Bug Fixes
auth.Login()validates scope (single source of truth) and returns*LoginResultwith effectiveScopeandOAuthType.--scopeignored with warning.readwhen no scope is provided; scope is stored and displayed.Login()and fully restore in-memory state on failure.--scopeis BC3-only, add--scope fullexample, and note BC3 vs Launchpad expected output.TestLoginLaunchpadClearsScopeusingatomic.Bool.Migration
(*LoginResult, error)fromauth.Login()and readresult.Scopefor messages/persistence.LoginResult(BC3 only).Written for commit 3f551e4. Summary will update on new commits.