Skip to content

fix(repo mirror): route cluster-addressed commands to the cluster's core - #1475

Merged
toothbrush merged 4 commits into
mainfrom
fix/control-plane-cluster-routing
Jun 19, 2026
Merged

fix(repo mirror): route cluster-addressed commands to the cluster's core#1475
toothbrush merged 4 commits into
mainfrom
fix/control-plane-cluster-routing

Conversation

@toothbrush

@toothbrush toothbrush commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

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

Failure mode

entire repo mirror collaborators list github.com/… aws-us-east-2.entire.io (and create/remove, collaborators add/remove) 400'd with unknown cluster_host whenever the active context's core didn't front that cluster — e.g. addressing a prod entire.io cluster while logged into partial.to.

Insight

The mirror verbs added in #1458 are the first cluster-anchored core calls: the user supplies a <cluster-host> and an upstream, and the owning project is the per-cell, system-managed gh:mirrors:* project derived server-side from the cluster. So the core to dial is a property of the cluster, not the user.

Every other core call is anchored to an identity-owned resource and correctly dials the active context. repo create, for instance, takes a required --project; the repo's project and its target cluster must be co-located on one core, so the project (which lives in your federation) is the anchor and --cluster-host is just an in-federation placement — routing it by cluster would be wrong.

So the mirror verbs now resolve the core from the cluster's /.well-known/entire-cluster.json and authenticate with the matching local context (active-wins-if-eligible → sole eligible → login hint) — the same discovery the git/data-API paths already use. Project/identity-anchored commands (repo create/list, mirror list/get) are unchanged.


Note

Medium Risk
Changes which core and credentials mirror mutations use in multi-federation setups; behavior is localized to cluster-scoped mirror commands with tests, but mis-discovery could still send requests to the wrong federation.

Overview
Fixes unknown cluster_host on mirror verbs when the active login’s core does not front the target cluster (e.g. prod entire.io cluster with a partial.to active context).

Cluster-scoped mirror commands (create/remove, collaborators add/remove/list) now resolve the control-plane core from the cluster’s /.well-known/entire-cluster.json and authenticate with the matching local context (same rules as git/data-API), via ResolveControlPlaneTargetForCluster, coreapi.NewForCluster, and runCoreForCluster / runCoreListForCluster. Identity-scoped mirror calls (list/get) still use the active context.

ResolveControlPlaneTarget is refactored to share targetForContext; coreapi.New pulls ENTIRE_TOKEN handling into clientFromEnvToken / clientForTarget. Tests cover cluster vs active context selection and empty cluster host.

Reviewed by Cursor Bugbot for commit 7c3e161. Configure here.

toothbrush and others added 2 commits June 19, 2026 13:01
`entire repo mirror create/remove` and `collaborators add/remove/list` took
the active context's core, so addressing a cluster in another federation
(e.g. a prod aws-us-east-2.entire.io cluster while logged into partial.to)
400'd with "unknown cluster_host".

These commands are resource-providers: the cluster-host names where the
mirror lives. They now resolve the core from the cluster's
/.well-known/entire-cluster.json and authenticate with the matching local
context (active-wins-if-eligible, else sole eligible, else a login hint) —
the same discovery the git/data-API paths already use. Account-scoped
commands (repo create/list, mirror list/get) still use the active context.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removes the duplicated context→ControlPlaneTarget tail between
ResolveControlPlaneTarget and ResolveControlPlaneTargetForCluster.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 19, 2026 03:35
@toothbrush
toothbrush requested a review from a team as a code owner June 19, 2026 03:35

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

Fixes cluster-scoped repo mirror mutations failing with unknown cluster_host when the active login’s core doesn’t front the target cluster, by routing those commands to the cluster’s own control-plane core discovered via /.well-known/entire-cluster.json and selecting an eligible local context for auth (active if eligible → sole eligible → login hint).

Changes:

  • Add cluster-aware control-plane client creation (coreapi.NewForCluster) and wire cluster-scoped mirror commands to use it.
  • Refactor control-plane command runners to share a common preamble (runCoreClient) and add cluster-scoped list helper (runCoreListForCluster).
  • Introduce auth.ResolveControlPlaneTargetForCluster (cluster discovery + context selection) and add unit tests covering cluster-vs-active selection and empty cluster host.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
internal/coreapi/client.go Adds NewForCluster and factors ENTIRE_TOKEN handling into clientFromEnvToken + shared clientForTarget.
cmd/entire/cli/repo_mirror.go Routes mirror create/remove through runCoreForCluster so the correct federation core is dialed.
cmd/entire/cli/repo_mirror_collaborators.go Routes collaborators add/remove/list through cluster-aware runners (runCoreForCluster / runCoreListForCluster).
cmd/entire/cli/corecmd.go Refactors core runner plumbing (runCoreClient) and shares list rendering via renderCoreList.
cmd/entire/cli/auth/control_plane.go Adds ResolveControlPlaneTargetForCluster and refactors shared targetForContext.
cmd/entire/cli/auth/control_plane_test.go Adds tests asserting cluster-scoped resolution uses the cluster’s core, not the active context, plus empty-host validation.

toothbrush and others added 2 commits June 19, 2026 13:58
`mirror list` is identity-scoped (active context), so its visible set is
whatever the active login's federation can see. Print "Listing mirrors on
<login server>" (stderr, skipped for --json) so a surprising empty result —
e.g. mirrors that live in another deployment — is legible rather than looking
like data loss.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eader

Drop the bespoke activeLoginServer helper (and its tests) — the active
context's core URL is already what auth.ResolveControlPlaneTarget returns,
which is the same target coreapi.New dials. Header now reuses it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@toothbrush
toothbrush merged commit 9ca510c into main Jun 19, 2026
9 checks passed
@toothbrush
toothbrush deleted the fix/control-plane-cluster-routing branch June 19, 2026 06:16
SnowingFox pushed a commit to SnowingFox/cli that referenced this pull request Jul 8, 2026
`entire repo mirror get entire://<cluster>/gh/<owner>/<repo>` listed
mirrors on the active context's core, so a clone URL for a cluster in a
different federation failed with "no mirror matching" until the user
manually switched contexts with `entire auth use`. The clone URL already
names its cluster; dial the core fronting it — discovered from the
cluster's /.well-known/entire-cluster.json and authenticated with the
matching local context — the same routing `mirror create`/`remove`
(PR entireio#1475) and `repo clone --cluster` (PR entireio#1529) already use. A ULID
ref carries no cluster coordinate and stays on the active context.

Adds runCoreObjectForCluster (mirroring runCoreListForCluster) and a
clusterCoreClient test seam alongside activeCoreClient so the routing
decision is pinned by command-level tests without live discovery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 01KX0ENQ9M4C5P85G431G5YR2E
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