Skip to content

Commit 7eca6f3

Browse files
mjudeikisclaude
andauthored
revert(app-studio): restore /clusters/<path> tenant addressing (#358)
PR #357's bare-path change routed tenant traffic to the user's DefaultCluster, which is NOT the selected workspace when the user is in any non-default workspace — silently reading/writing the wrong workspace's projects instead of erroring. Restore the original /clusters/<tenantPath> addressing (an honest 403 from the hub proxy) until the GraphQL migration lands proper per-workspace access. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5b8c48b commit 7eca6f3

1 file changed

Lines changed: 4 additions & 14 deletions

File tree

providers/app-studio/tenant/client.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ You may obtain a copy of the License at
1616
// The base kubeconfig (the provider's own kcp connection) supplies only the
1717
// front-proxy host + TLS; its credential is dropped so the factory can never
1818
// authenticate as the provider. Per request we build a config with that host
19-
// (no /clusters/ segment) and the caller's bearer token: the kedge hub proxy
20-
// scopes bare paths to the caller's own DefaultCluster, which is the only
21-
// workspace this factory ever talks to. Addressing by the tenant's workspace
22-
// *path* instead would be rejected — the proxy's cluster gate accepts only the
23-
// caller's DefaultCluster *ID* (or ID:mount), not a path.
19+
// (cluster segment swapped for the tenant's path) and the caller's bearer token.
2420
package tenant
2521

2622
import (
@@ -74,14 +70,8 @@ func NewClientFactory(base *rest.Config) *ClientFactory {
7470
}
7571
}
7672

77-
// For returns a dynamic client scoped to the caller's own workspace,
78-
// authenticating as the caller via token. Cached per (tenant, token).
79-
//
80-
// The host carries no /clusters/ segment: the hub proxy scopes bare paths to
81-
// the token's DefaultCluster. tenantPath is retained only as a cache key — the
82-
// caller always acts within its own default workspace, so a request must never
83-
// be addressed by the workspace path (the proxy's gate rejects paths, accepting
84-
// only the DefaultCluster ID).
73+
// For returns a dynamic client scoped to tenantPath, authenticating as the
74+
// caller via token. Cached per (tenant, token).
8575
func (f *ClientFactory) For(tenantPath, token string) (dynamic.Interface, error) {
8676
if token == "" {
8777
return nil, fmt.Errorf("no bearer token on request — cannot act on the tenant's behalf")
@@ -93,7 +83,7 @@ func (f *ClientFactory) For(tenantPath, token string) (dynamic.Interface, error)
9383
}
9484

9585
cfg := &rest.Config{
96-
Host: f.baseHost,
86+
Host: f.baseHost + "/clusters/" + tenantPath,
9787
BearerToken: token,
9888
TLSClientConfig: f.baseTLS,
9989
}

0 commit comments

Comments
 (0)