Auto-pick v2 auth when split-host is configured#1290
Conversation
When ENTIRE_AUTH_BASE_URL is set to a different origin than the data
API, the operator has explicitly pointed the CLI at a dedicated auth
host. Only the v2 surface knows how to talk to a dedicated auth host
(OIDC-standard /device_authorization + RFC 8693 STS exchange at
/oauth/token), so the version no longer needs to be set separately.
Resolution order (effectiveProviderVersion):
1. ENTIRE_AUTH_PROVIDER_VERSION explicit value wins. "v1"/"v2"
route directly; anything unrecognised falls through to
resolveProvider's default (v1) — typos don't silently
auto-upgrade.
2. Split-host detected (AuthBaseURL != BaseURL) → "v2". An
ENTIRE_AUTH_BASE_URL redundantly set to the same origin as the
data API doesn't trigger v2 (canonicalisation inside
AuthBaseURL/BaseURL handles cosmetic differences like a trailing
slash).
3. Otherwise → "v1". Single-host deployments stay on whatever
surface their backend currently exposes. Verified that entire.io
does NOT yet serve v2 endpoints (POST /device_authorization
returns 405, /.well-known/openid-configuration returns the SPA
HTML rather than a JSON discovery doc), so the unset-env default
must not auto-pick v2 — that would break login for every
existing CLI user.
Users on a v2-capable single-host server can still opt in with
ENTIRE_AUTH_PROVIDER_VERSION=v2. Users mid-migration who want to
suppress the auto-upgrade can force v1 the same way.
Coverage:
- TestEffectiveProviderVersion_ExplicitEnvWins pins the override
priority for v1, v2, and unrecognised values.
- TestEffectiveProviderVersion_SplitHostPicksV2 is the user-facing
change.
- TestEffectiveProviderVersion_SameHostPicksV1 covers the
redundant-env-value case so the auto-detect isn't fooled.
- TestEffectiveProviderVersion_UnsetDefaultsToV1 pins the entire.io
default — the path most existing users hit and the one that must
not regress.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 541762dc7d9d
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7789d17. Configure here.
There was a problem hiding this comment.
Pull request overview
Updates auth provider selection so split-host deployments automatically use the v2 OAuth/OIDC surface when ENTIRE_AUTH_BASE_URL is configured to a different origin than the data API, while keeping the default v1 behavior for single-host (including entire.io) unless explicitly overridden.
Changes:
- Add
effectiveProviderVersionto infer provider version from env + split-host shape, and routeCurrentProviderthrough it. - Expand inline docs to describe the resolution order and split-host rationale.
- Add unit tests covering explicit env override, split-host auto-pick, same-host no-op, and unset defaults.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| cmd/entire/cli/auth/provider.go | Adds effectiveProviderVersion and updates provider resolution/docs to auto-pick v2 for split-host. |
| cmd/entire/cli/auth/provider_test.go | Adds unit tests to lock in provider-version resolution behavior. |
| cmd/entire/cli/auth/client.go | Updates Client comment to reference the new resolution rules. |
Code-review cleanup of the prior commit: - api.IsSplitHost() names the AuthBaseURL != BaseURL comparison and lives next to the canonicalisation rules it depends on, instead of inlining the cross-package comparison in auth/. - Docstrings in provider.go trimmed: the original ~20-line comment on effectiveProviderVersion was narrating the resolution order the code already shows. Kept the one load-bearing WHY (entire.io doesn't serve v2 yet, so an unconditional default-flip would break login) and dropped the rest. Same treatment for the ProviderVersionEnvVar and CurrentProvider docstrings. - Test comments tightened: per-test docstrings restating the test name are gone; only kept the WHY callouts (canonicalisation dependence in SameHostPicksV1, entire.io-default risk in UnsetDefaultsToV1, typo passthrough rationale in ExplicitEnvWins). - Added TestIsSplitHost covering the empty/missing/same/cosmetic-match/ different cases for the new helper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: e00cb97f7768
BaseURL only trims whitespace + trailing slash; AuthBaseURL applies full NormalizeOriginURL canonicalisation (lowercase scheme/host, default port stripped, path/query dropped). When ENTIRE_AUTH_BASE_URL is unset, AuthBaseURL falls back to BaseURL's lightly-trimmed value and then canonicalises it, while the IsSplitHost comparison was using the un-canonicalised BaseURL on the other side. Net effect: any cosmetic difference in ENTIRE_API_BASE_URL — uppercase host, explicit :443, a path suffix, a trailing slash — made the two sides diverge and falsely registered as split-host. Through effectiveProviderVersion that auto-selected v2, which then broke login because entire.io doesn't yet serve the v2 surface. A user with ENTIRE_API_BASE_URL=https://entire.io/ would be unable to log in. Fix: canonicalise both sides at the comparison point. Regression tests cover the four cosmetic-difference shapes (uppercase, default port, path suffix, trailing slash) with auth unset. Verified each test fails on HEAD without the fix and passes with it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 7a4e08f62055

https://entire.io/gh/entireio/cli/trails/447
Summary
Follow-up to #1258. Removes the need to set both
ENTIRE_AUTH_BASE_URLandENTIRE_AUTH_PROVIDER_VERSION=v2when targeting a split-host deployment (e.g. partial.to + us.auth.partial.to). WhenENTIRE_AUTH_BASE_URLis set to a different origin than the data API, the CLI auto-picks v2.Why not flip the default outright
Probed entire.io directly before deciding:
So v2 isn't live on entire.io yet. An unconditional default flip would break login for every existing CLI user. The auto-detect approach makes "split-host config = v2" the actual UX (without requiring a second env var) while leaving the entire.io path on v1 until the backend ships the v2 OIDC surface.
Resolution order
ENTIRE_AUTH_PROVIDER_VERSIONexplicit value wins (v1/v2/ passthrough toresolveProvider's default for unrecognised values — typos don't silently auto-upgrade).AuthBaseURL() != BaseURL()→v2. Canonicalisation in those helpers means a redundantENTIRE_AUTH_BASE_URL=https://entire.io/(trailing slash, same host) doesn't trigger v2.v1.Users on a v2-capable single-host server can still opt in with
ENTIRE_AUTH_PROVIDER_VERSION=v2. Users mid-migration who want to suppress the auto-upgrade can forcev1the same way.Test plan
TestEffectiveProviderVersion_ExplicitEnvWins— env var beats auto-detect for v1, v2, and unrecognised valuesTestEffectiveProviderVersion_SplitHostPicksV2— the user-facing changeTestEffectiveProviderVersion_SameHostPicksV1— redundant env value doesn't trigger v2TestEffectiveProviderVersion_UnsetDefaultsToV1— entire.io path (most existing users) doesn't regressmise run fmt && mise run lint && go test ./...cleanFollow-up (out of scope)
/.well-known/openid-configuration) so split-host can be discovered from the data API alone, eliminatingENTIRE_AUTH_BASE_URLas a manual config step.🤖 Generated with Claude Code
Note
Medium Risk
Changes login routing for auth provider selection; mitigated by defaulting unchanged single-host users to v1 and letting the env var override auto-detect.
Overview
When
ENTIRE_AUTH_PROVIDER_VERSIONis unset, the CLI now infers the OAuth provider version from deployment shape instead of defaulting only via that env var.Split-host setups—
ENTIRE_AUTH_BASE_URLon a different origin than the data API (api.AuthBaseURL() != api.BaseURL())—automatically select v2, so operators no longer need both split-host URLs andENTIRE_AUTH_PROVIDER_VERSION=v2. Same-origin configs (including redundant auth URL with trailing slash) still resolve to v1, preserving existing entire.io single-host behavior where v2 is not live yet.Explicit
ENTIRE_AUTH_PROVIDER_VERSIONstill wins (including forcing v1 during migration). Unrecognized env values are passed through toresolveProviderwithout triggering auto-detect, so typos do not silently upgrade.Docs on
Client/CurrentProviderand new unit tests document and lock in this resolution order.Reviewed by Cursor Bugbot for commit 7789d17. Configure here.