Skip to content

Auto-pick v2 auth when split-host is configured#1290

Merged
Soph merged 3 commits into
mainfrom
soph/v2-default-on-split-host
May 28, 2026
Merged

Auto-pick v2 auth when split-host is configured#1290
Soph merged 3 commits into
mainfrom
soph/v2-default-on-split-host

Conversation

@Soph

@Soph Soph commented May 28, 2026

Copy link
Copy Markdown
Collaborator

https://entire.io/gh/entireio/cli/trails/447

Summary

Follow-up to #1258. Removes the need to set both ENTIRE_AUTH_BASE_URL and ENTIRE_AUTH_PROVIDER_VERSION=v2 when targeting a split-host deployment (e.g. partial.to + us.auth.partial.to). When ENTIRE_AUTH_BASE_URL is 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:

POST https://entire.io/device_authorization       → HTTP 405 Method Not Allowed
GET  https://entire.io/.well-known/openid-configuration → HTTP 200 returning the SPA HTML (no discovery doc)
POST https://entire.io/oauth/device/code          → HTTP 200, valid device code (v1 works)

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

  1. ENTIRE_AUTH_PROVIDER_VERSION explicit value wins (v1 / v2 / passthrough to resolveProvider's default for unrecognised values — typos don't silently auto-upgrade).
  2. AuthBaseURL() != BaseURL()v2. Canonicalisation in those helpers means a redundant ENTIRE_AUTH_BASE_URL=https://entire.io/ (trailing slash, same host) doesn't trigger v2.
  3. Otherwise → 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 force v1 the same way.

Test plan

  • TestEffectiveProviderVersion_ExplicitEnvWins — env var beats auto-detect for v1, v2, and unrecognised values
  • TestEffectiveProviderVersion_SplitHostPicksV2 — the user-facing change
  • TestEffectiveProviderVersion_SameHostPicksV1 — redundant env value doesn't trigger v2
  • TestEffectiveProviderVersion_UnsetDefaultsToV1 — entire.io path (most existing users) doesn't regress
  • mise run fmt && mise run lint && go test ./... clean

Follow-up (out of scope)

  • Bring v2 OIDC surface to entire.io, then a tiny PR can flip the default outright and the env-var dance disappears.
  • Optionally add OIDC discovery (/.well-known/openid-configuration) so split-host can be discovered from the data API alone, eliminating ENTIRE_AUTH_BASE_URL as 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_VERSION is 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_URL on a different origin than the data API (api.AuthBaseURL() != api.BaseURL())—automatically select v2, so operators no longer need both split-host URLs and ENTIRE_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_VERSION still wins (including forcing v1 during migration). Unrecognized env values are passed through to resolveProvider without triggering auto-detect, so typos do not silently upgrade.

Docs on Client / CurrentProvider and new unit tests document and lock in this resolution order.

Reviewed by Cursor Bugbot for commit 7789d17. Configure here.

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
Copilot AI review requested due to automatic review settings May 28, 2026 14:56
@Soph Soph requested a review from a team as a code owner May 28, 2026 14:56

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread cmd/entire/cli/auth/provider.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 effectiveProviderVersion to infer provider version from env + split-host shape, and route CurrentProvider through 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.

Comment thread cmd/entire/cli/auth/provider.go
Soph and others added 2 commits May 28, 2026 17:03
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
@Soph Soph merged commit 4bc40d9 into main May 28, 2026
9 checks passed
@Soph Soph deleted the soph/v2-default-on-split-host branch May 28, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants