feat: DEV/TEST environments + OAuth scope step-up (DEVEX-719)#57
Merged
Conversation
Consolidate environment->endpoint resolution into one module and let internal
developers target DEV/TEST at runtime without committing anything to this OSS
repo, and wire the CLI to cli-engine 0.2.1's OAuth scope step-up.
Environments (DEVEX-719):
- New `environments` module resolves an env to {api_url, client_id, auth_url,
token_url} from built-ins (ote/prod) -> ~/.config/gddy/environments.toml ->
per-env <ENV>_API_URL vars (built-ins overridable). Replaces the API-base-URL
logic previously duplicated across env, auth, and client. No internal
hostnames or client IDs are committed.
- `--env` validates against known envs; `env list/get/info/set` route through
the resolver.
Scope step-up (consumes cli-engine 0.2.1):
- GoDaddyAuthProvider forwards get_credential_for so the per-env PkceAuthProvider
performs scope step-up; SCOPES -> DEFAULT_OAUTH_SCOPES.
- `api call` merges the matched endpoint's scopes with --scope and requests them
via credential_with_scopes; --scope now requires a value.
Hardening from deep review: api_url_for_env never returns an empty base URL;
documented the built-in-override token-redirect trade-off; added unit tests for
the resolver, scope merge, and api_url_for_env.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a centralized environment-resolution layer and updates auth/API call flows to support runtime DEV/TEST targeting and OAuth scope “step-up” via cli-engine 0.2.1, without committing internal endpoints into the repo.
Changes:
- Introduces a new
environmentsmodule that resolves{api_url, client_id, auth_url, token_url}from built-ins → local TOML config → per-env*_API_URLoverrides. - Updates auth provider wiring to delegate
get_credential_forto env-specificPkceAuthProviderinstances, enabling scope step-up. - Enhances
api callto merge endpoint-declared scopes with--scopeflags and request credentials with those scopes; bumpscli-engineto0.2.1.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| rust/src/main.rs | Registers/validates global --env flag and wires new environment resolution. |
| rust/src/environments/mod.rs | New environment resolver with precedence rules, derived OAuth URLs, and unit tests. |
| rust/src/env/mod.rs | Routes env list/get/set/info through the resolver and updates output tests. |
| rust/src/auth.rs | Reworks auth provider to build per-env PKCE providers on demand and forward scope-aware credential requests. |
| rust/src/application/client.rs | Resolves API base URL via the new resolver with fallback behavior; adds unit tests. |
| rust/src/api_explorer/mod.rs | Adds scope-merging helper and updates api call to request scoped credentials and improve 403 messaging. |
| rust/Cargo.toml | Bumps cli-engine dependency to 0.2.1. |
| rust/Cargo.lock | Updates lockfile for cli-engine 0.2.1 and transitive dependency bumps (e.g., socket2). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- main.rs: validate --env only when explicitly passed, so a malformed ~/.config/gddy/environments.toml no longer fails every command (the default env comes from .gdenv/DEFAULT_ENV and is already filtered). - environments: normalize api_url (trim trailing slash) once during resolution so callers concatenating paths never produce '//'; update the test. - auth.rs: list_environments propagates a malformed-config error instead of silently reporting zero environments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- api call --scope: use ArgAction::Append (one value per occurrence) instead of num_args(1..), which could greedily consume the required ENDPOINT positional. - client.rs test: assert builtins resolve to a URL rather than exact hosts (built-ins are overridable; exact mapping covered in environments::tests). - env list test: accept any scheme (http/https) for apiUrl shape. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- merge_required_scopes de-dupes repeated --scope flag values too (not just
endpoint-vs-flags); added a test.
- environments::resolve falls back to built-ins + <PREFIX>_API_URL env vars when
the optional local config is malformed/unreadable, so a broken file no longer
bricks auth-required commands targeting prod/ote; the load error still surfaces
for envs that actually need the file.
- client.rs test asserts URL shape ('://') rather than the https scheme.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A blank api_url (from PROD_API_URL="" or a blank config entry) could clobber a built-in default and yield relative request/OAuth URLs, and made is_known accept an unusable env. Add clean_url (trim whitespace + trailing slash, None if empty); resolve ignores empty overrides; is_known (incl. the malformed-config fallback) requires a non-empty api_url. Added tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…(round 5) Consistency with the round-4 empty-api_url handling: known_names no longer advertises unusable entries, and listable_with skips them so one invalid entry can't fail env list / credential enumeration wholesale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
clean_url is now the single validity authority: it requires an http(s):// scheme with a non-empty host (reqwest needs absolute URLs). resolve, is_known, known_names, and listable_with all defer to it, so a present-but-schemeless api_url is treated as unusable consistently (rejected, not advertised, and never fails env list / enumeration wholesale). Added a test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- resolve runs auth_url/token_url config overrides through clean_url (scheme validation), so an invalid override falls back to the derived endpoints rather than failing later with an opaque reqwest error. - env list injects the active env when it's defined only via <ENV>_API_URL (and thus excluded from listable), so the list always has an active:true entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
environments_path() resolves per-OS (XDG/%APPDATA%/macOS); the EnvError already carries the resolved path, so the warning no longer bakes in ~/.config/... Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
auth login --scope is append-style (one value per flag), so the api call 403 hint now suggests `auth login --scope a --scope b` rather than space-joining. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
listable() falls back to built-ins (with a warning) on a malformed config; the comment no longer claims the error is surfaced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Module/schema/auth doc comments no longer hard-code ~/.config/gddy; they reference dirs::config_dir()/environments_path() (XDG/%APPDATA%/macOS). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
URL schemes are case-insensitive (RFC 3986), but clean_url used case-sensitive strip_prefix, so a valid override like HTTPS://host was silently dropped. Match the scheme case-insensitively while preserving host case. Added a test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ilot) - Module doc spells the cli-engine override vars in full (<PREFIX>_OAUTH_AUTH_URL / _OAUTH_TOKEN_URL), not the misleading _AUTH_URL. - get_env comment notes a config-only env is dropped if the config can't be read (is_known then falls back to built-ins + <ENV>_API_URL). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jgowdy-godaddy
approved these changes
Jun 11, 2026
axburgess-godaddy
approved these changes
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lets internal developers target DEV/TEST environments at runtime without committing anything to this OSS repo (DEVEX-719), and wires the CLI to cli-engine 0.2.1's OAuth scope step-up.
Environments (DEVEX-719)
environmentsmodule is the single source of truth: resolve an env name to{api_url, client_id, auth_url, token_url}from built-ins (ote/prod) →~/.config/gddy/environments.toml→ per-env<ENV>_API_URLenv vars (built-ins are overridable). This replaces the API-base-URL logic that was duplicated acrossenv,auth, andclient.--envis validated against known envs (clear error listing them);env list/get/info/setroute through the resolver.OAuth scope step-up (consumes cli-engine 0.2.1)
GoDaddyAuthProviderforwardsget_credential_for, so the per-envPkceAuthProviderperforms scope step-up when the cached token lacks a command's required scopes.api callmerges the matched catalog endpoint's scopes with repeatable--scopeand requests them viactx.credential_with_scopes(...);--scopenow requires a value.SCOPES→DEFAULT_OAUTH_SCOPES; engine dependency bumped to0.2.1.Hardening (from a deep review pass)
api_url_for_envnever returns an empty base URL (falls back to the built-in default).listable/is_known),merge_required_scopes,api_url_for_env, andenv listoutput-shape.Verification
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test(132 pass) against publishedcli-engine 0.2.1.🤖 Generated with Claude Code