fix(workspace-server): provider-matched byok credential injection (internal#728 Bug 1) [BEHAVIOR-AFFECTING — CTO merge-go] #2000

Merged
hongming merged 1 commits from fix/internal-728-provider-matched-cred-injection into main 2026-05-29 00:29:08 +00:00
4 changed files with 248 additions and 30 deletions
@@ -67,8 +67,10 @@ func TestApplyPlatformManagedLLMEnv_ReProvisionUsesStoredModel(t *testing.T) {
"CLAUDE_CODE_OAUTH_TOKEN": "RENO-OWN-OAUTH", // workspace_secrets origin
"ANTHROPIC_BASE_URL": "https://api.moleculesai.app/api/v1/internal/llm/anthropic",
}
// payload.Model == "" — exactly the re-provision shape.
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "")
// payload.Model == "" — exactly the re-provision shape. The oauth is
// workspace_secrets-origin (NOT in globalKeys) → exempt from the #728
// provider-matched strip regardless of provider match.
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "", nil)
if res.ResolvedMode != LLMBillingModeBYOK {
t.Fatalf("re-provision with stored MODEL=opus must resolve byok, got %q (source=%s) — the #1994 divergence", res.ResolvedMode, res.Source)
@@ -149,7 +151,7 @@ func TestApplyPlatformManagedLLMEnv_ReadProvisionParity(t *testing.T) {
"MODEL": "opus",
"CLAUDE_CODE_OAUTH_TOKEN": "RENO-OWN-OAUTH",
}
provRes := applyPlatformManagedLLMEnv(ctx, provEnv, wsID, "claude-code", "")
provRes := applyPlatformManagedLLMEnv(ctx, provEnv, wsID, "claude-code", "", nil)
if err := provMock.ExpectationsWereMet(); err != nil {
t.Errorf("provision-path sqlmock expectations: %v", err)
}
@@ -179,7 +181,7 @@ func TestApplyPlatformManagedLLMEnv_DefaultPreservation(t *testing.T) {
// No MODEL anywhere, no auth env — nothing to derive.
envVars := map[string]string{}
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "", nil)
if res.ResolvedMode != LLMBillingModePlatformManaged {
t.Fatalf("no model + no cred must default platform_managed (CTO: default stays platform), got %q (source=%s)", res.ResolvedMode, res.Source)
@@ -219,8 +221,13 @@ func TestApplyPlatformManagedLLMEnv_ByokGlobalScopeOAuthSurvives(t *testing.T) {
"MODEL": "opus",
"CLAUDE_CODE_OAUTH_TOKEN": "TENANT-OWN-GLOBAL-OAUTH",
}
// Provenance: the oauth is GLOBAL-origin (internal#728). It must STILL
// survive — opus derives anthropic-oauth, whose auth_env IS
// CLAUDE_CODE_OAUTH_TOKEN, so the provider-matched strip keeps it. This is
// the PM/reno opus-byok regression guard against #728's strip.
globalKeys := map[string]struct{}{"CLAUDE_CODE_OAUTH_TOKEN": {}}
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "", globalKeys)
if res.ResolvedMode != LLMBillingModeBYOK {
t.Fatalf("opus derives byok; got %q", res.ResolvedMode)
@@ -255,3 +262,113 @@ func TestReProvisionPayloadOmitsModel(t *testing.T) {
t.Fatalf("re-provision payload model expected empty (the #1994 trigger), got %q", p.Model)
}
}
// --- internal#728 Bug 1: provider-matched credential injection ---------------
// TestApplyPlatformManagedLLMEnv_MinimaxStripsStrayGlobalOAuth is the direct
// repro of DevB (Dev Engineer B, MiniMax-M2.7, claude-code; live-confirmed
// 2026-05-28). config.yaml correctly resolves provider=minimax, but the
// container inherits the tenant-GLOBAL CLAUDE_CODE_OAUTH_TOKEN; the claude-code
// runtime greedily prefers it (`llm-auth: detected oauth`) and routes
// MiniMax-M2.7 → api.anthropic.com → `Claude Code returned an error result`.
//
// The #728 provider-matched strip must REMOVE the stray global-origin oauth
// (minimax's auth_env is MINIMAX_API_KEY/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_API_KEY
// — NOT CLAUDE_CODE_OAUTH_TOKEN) while KEEPING the minimax routing key.
//
// Mutation (load-bearing): remove the stripNonMatchingGlobalOriginLLMCreds
// call (revert to #1994's blanket keep) → the oauth survives → this test RED on
// the oauth-absent assertion. Make the strip provider-UNAWARE (strip all
// global bypass keys) → MINIMAX_API_KEY also vanishes → RED on the
// minimax-routing assertion. Make it provenance-UNAWARE (strip by name
// regardless of origin) → the workspace-origin exemption test below goes RED.
func TestApplyPlatformManagedLLMEnv_MinimaxStripsStrayGlobalOAuth(t *testing.T) {
ctx := context.Background()
const wsID = "22222222-3333-4444-5555-666666666666" // agents-team Dev Engineer B
mock := setupTestDB(t)
expectOverrideQuery(mock, wsID, "")
// The container env on a re-provision: the MiniMax routing key + the stray
// tenant-global oauth (both global_secrets origin) + the stored model.
envVars := map[string]string{
"MODEL": "MiniMax-M2.7",
"MINIMAX_API_KEY": "MINIMAX-TENANT-KEY",
"CLAUDE_CODE_OAUTH_TOKEN": "STRAY-TENANT-GLOBAL-OAUTH",
}
// Both creds are global_secrets origin (the tenant configured them at org
// scope; no per-workspace override re-set them).
globalKeys := map[string]struct{}{
"MINIMAX_API_KEY": {},
"CLAUDE_CODE_OAUTH_TOKEN": {},
}
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "", globalKeys)
if res.ResolvedMode != LLMBillingModeBYOK {
t.Fatalf("MiniMax-M2.7 must derive minimax → byok, got %q (source=%s)", res.ResolvedMode, res.Source)
}
if res.Source != BillingModeSourceDerivedProvider {
t.Errorf("source: got %q want derived_provider (MiniMax-M2.7 → minimax)", res.Source)
}
// THE FIX: the stray global oauth that does NOT match minimax's auth_env
// must be gone, so the runtime cannot prefer it and mis-route to Anthropic.
if v, present := envVars["CLAUDE_CODE_OAUTH_TOKEN"]; present {
t.Errorf("stray global-origin CLAUDE_CODE_OAUTH_TOKEN must be STRIPPED for a minimax-resolving workspace (the DevB bug); still present=%q", v)
}
// The minimax routing key (IS in minimax's auth_env) must remain.
if envVars["MINIMAX_API_KEY"] != "MINIMAX-TENANT-KEY" {
t.Errorf("minimax routing key must SURVIVE (it matches the resolved provider's auth_env); got %q", envVars["MINIMAX_API_KEY"])
}
if !res.HasUsableLLMCred {
t.Errorf("MINIMAX_API_KEY is a usable credential → HasUsableLLMCred must stay true (not failed-closed)")
}
if _, present := envVars["MOLECULE_LLM_USAGE_TOKEN"]; present {
t.Errorf("byok must not inject the platform usage token")
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("sqlmock expectations: %v", err)
}
}
// TestApplyPlatformManagedLLMEnv_WorkspaceOriginCredExemptFromStrip pins the
// provenance guard: a CLAUDE_CODE_OAUTH_TOKEN the USER set via the canvas
// Secrets tab (workspace_secrets origin → NOT in globalKeys) must NEVER be
// stripped, even on a minimax-resolving workspace where it doesn't match the
// derived provider's auth_env. The user authored it deliberately; the #728
// strip is scoped to the inherited operator-store channel only.
//
// Mutation: drop the `if _, isBypass...; continue` / globalKeys gate (strip by
// name regardless of origin) → the user's oauth vanishes → RED.
func TestApplyPlatformManagedLLMEnv_WorkspaceOriginCredExemptFromStrip(t *testing.T) {
ctx := context.Background()
const wsID = "33333333-4444-5555-6666-777777777777"
mock := setupTestDB(t)
expectOverrideQuery(mock, wsID, "")
envVars := map[string]string{
"MODEL": "MiniMax-M2.7",
"MINIMAX_API_KEY": "MINIMAX-TENANT-KEY",
"CLAUDE_CODE_OAUTH_TOKEN": "USER-AUTHORED-OAUTH",
}
// MINIMAX_API_KEY is global-origin; the oauth is WORKSPACE-origin (the user
// re-set it via the Secrets tab, so loadWorkspaceSecrets cleared its
// global-origin flag) → exempt.
globalKeys := map[string]struct{}{"MINIMAX_API_KEY": {}}
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "", globalKeys)
if res.ResolvedMode != LLMBillingModeBYOK {
t.Fatalf("MiniMax-M2.7 derives byok; got %q", res.ResolvedMode)
}
if envVars["CLAUDE_CODE_OAUTH_TOKEN"] != "USER-AUTHORED-OAUTH" {
t.Errorf("workspace-origin (user-authored) oauth must NOT be stripped even when it doesn't match the provider; got %q", envVars["CLAUDE_CODE_OAUTH_TOKEN"])
}
if envVars["MINIMAX_API_KEY"] != "MINIMAX-TENANT-KEY" {
t.Errorf("matching minimax key must survive; got %q", envVars["MINIMAX_API_KEY"])
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("sqlmock expectations: %v", err)
}
}
@@ -900,7 +900,17 @@ type platformLLMEnvResult struct {
Source BillingModeSource
}
func applyPlatformManagedLLMEnv(ctx context.Context, envVars map[string]string, workspaceID, runtime, model string) platformLLMEnvResult {
// globalKeys is the provenance side-channel from loadWorkspaceSecrets: the set
// of env keys that originated from the operator-controlled global_secrets table
// (a workspace_secrets row of the same name overrides and clears the flag). It
// is consumed ONLY on the byok/disabled branch's provider-matched strip
// (internal#728 Bug 1): a global-origin LLM bypass cred that does NOT match the
// resolved provider's auth_env is stripped so a greedy runtime (claude-code
// prefers CLAUDE_CODE_OAUTH_TOKEN) cannot route a non-anthropic model to the
// wrong upstream. May be nil (no global-origin keys / unknown provenance) — a
// nil set strips nothing, preserving the pre-#728 behavior for callers that do
// not thread provenance.
func applyPlatformManagedLLMEnv(ctx context.Context, envVars map[string]string, workspaceID, runtime, model string, globalKeys map[string]struct{}) platformLLMEnvResult {
// internal#718 P2-B: the platform-vs-byok decision now DERIVES the provider
// from (runtime, model) via the registry and keys off IsPlatform(derived) —
// NOT a stored LLM_PROVIDER and NOT the org rung. This path already carries
@@ -945,19 +955,43 @@ func applyPlatformManagedLLMEnv(ctx context.Context, envVars map[string]string,
envVars["MOLECULE_LLM_BILLING_MODE_RESOLVED"] = res.ResolvedMode
if res.ResolvedMode != LLMBillingModePlatformManaged {
// byok or disabled — DO NOT force-route to CP, DO NOT override the
// workspace's own ANTHROPIC_BASE_URL / OAuth token, and DO NOT strip
// the tenant's own LLM credentials.
// workspace's own ANTHROPIC_BASE_URL, and DO NOT strip the tenant's own
// (provider-matching) LLM credentials.
//
// molecule-core#1994 (corrected model): `global_secrets` is the
// TENANT's store, not the platform's. The tenant's own credential —
// at global OR workspace scope — is exactly what byok runs on, direct.
// We leave envVars untouched here and report whether a usable LLM
// credential survived so the caller can fail closed when there is
// genuinely none (no platform-managed-shaped key at any scope). The
// platform's own credential is never in a tenant's global_secrets
// The platform's own credential is never in a tenant's global_secrets
// (guarded at the SetGlobal write boundary + the proxy token is
// server-env-only), so leaving the tenant's globals in place cannot
// re-open the platform-credit drain.
//
// internal#728 Bug 1 (provider-matched credential injection): #1994
// removed the BLANKET strip, which was correct for the platform-key
// co-mingling it targeted but left EVERY claude-code workspace
// inheriting the tenant-global CLAUDE_CODE_OAUTH_TOKEN. A claude-code
// runtime greedily prefers that oauth (`llm-auth: detected oauth` →
// api.anthropic.com), so a workspace whose RESOLVED provider is NOT
// anthropic-oauth (minimax, kimi-byok, …) routes its non-Anthropic
// model to Anthropic and errors (`Claude Code returned an error
// result`; DevB MiniMax-M2.7 live-confirmed 2026-05-28).
//
// The precise, provider-AWARE replacement for the over-removed strip:
// keep ONLY the global-origin bypass creds whose env-var name is in the
// RESOLVED provider's auth_env; strip the rest. This is NOT a return to
// the blanket strip — it is keyed off the derived provider:
// - minimax (auth_env: MINIMAX_API_KEY, ANTHROPIC_AUTH_TOKEN,
// ANTHROPIC_API_KEY) → global-origin CLAUDE_CODE_OAUTH_TOKEN is
// NOT a match → stripped (fixes DevB).
// - anthropic-oauth (auth_env: CLAUDE_CODE_OAUTH_TOKEN) → the
// global-origin oauth IS a match → kept (PM/reno opus byok NOT
// regressed — the #1994 ByokGlobalScopeOAuthSurvives guard holds).
// WORKSPACE-origin creds (the user explicitly set them via the canvas
// Secrets tab → NOT in globalKeys) are NEVER stripped here, even when
// they don't match: the user authored them deliberately (JRS kimi
// workspace-key, reno's own oauth). Only the inherited operator-store
// channel is provider-gated.
stripNonMatchingGlobalOriginLLMCreds(envVars, globalKeys, runtime, effectiveModel, availableAuthEnv)
return platformLLMEnvResult{
ResolvedMode: res.ResolvedMode,
HasUsableLLMCred: hasAnyPlatformManagedLLMKey(envVars),
@@ -1028,6 +1062,66 @@ func hasAnyPlatformManagedLLMKey(envVars map[string]string) bool {
return false
}
// stripNonMatchingGlobalOriginLLMCreds is the byok-branch provider-matched
// credential injection (internal#728 Bug 1). It removes from envVars every
// platform-managed LLM bypass key that:
//
// 1. originated from the operator-controlled global_secrets store
// (present in globalKeys — a workspace_secrets row of the same name
// overrides + clears the flag, so user-authored creds are exempt), AND
// 2. is NOT in the RESOLVED provider's auth_env set.
//
// The motivating regression: #1994 dropped the blanket strip, so a claude-code
// workspace resolving to `minimax` still inherited the tenant-global
// CLAUDE_CODE_OAUTH_TOKEN; the runtime prefers that oauth and routes the
// MiniMax model to api.anthropic.com → error. Keeping only the resolved
// provider's own auth_env keys (minimax: MINIMAX_API_KEY/ANTHROPIC_AUTH_TOKEN/
// ANTHROPIC_API_KEY — not the oauth) removes the stray oauth while preserving
// anthropic-oauth's CLAUDE_CODE_OAUTH_TOKEN for an opus byok workspace.
//
// Fail-OPEN by design: if the provider cannot be derived (empty model /
// unknown runtime / ambiguous) or the registry is unavailable, we strip
// NOTHING — we never strip a credential we cannot prove is non-matching, so a
// derive miss can never fail-close a legitimate byok workspace (mirrors the
// resolver's own default-closed-to-platform contract: the worst case is we
// keep a stray cred, never that we remove the only usable one). The earlier
// internal#711 blanket strip's fail-direction (remove first) was the bug;
// this strip's fail-direction is keep-first.
func stripNonMatchingGlobalOriginLLMCreds(envVars map[string]string, globalKeys map[string]struct{}, runtime, model string, availableAuthEnv []string) {
if len(globalKeys) == 0 {
return // no operator-store-origin keys to consider — nothing to strip.
}
manifest, err := providerRegistry()
if err != nil || manifest == nil {
return // registry unavailable — fail open, strip nothing.
}
provider, dErr := manifest.DeriveProvider(runtime, model, availableAuthEnv)
if dErr != nil {
return // underivable provider — fail open, strip nothing.
}
// The resolved provider's accepted auth-env-var NAMES (case-insensitive
// for parity with isPlatformManagedDirectLLMBypassKey, which upper-cases).
keep := make(map[string]struct{}, len(provider.AuthEnv))
for _, e := range provider.AuthEnv {
keep[strings.ToUpper(strings.TrimSpace(e))] = struct{}{}
}
for key := range globalKeys {
upper := strings.ToUpper(strings.TrimSpace(key))
if _, isBypass := platformManagedDirectLLMBypassKeys[upper]; !isBypass {
continue // not an LLM bypass cred (e.g. a non-LLM operator secret) — leave it.
}
if _, matches := keep[upper]; matches {
continue // matches the resolved provider's auth_env — this is what byok runs on.
}
// Global-origin LLM bypass cred that does NOT match the resolved
// provider — the stray that a greedy runtime would mis-prefer. Strip.
if _, present := envVars[key]; present {
log.Printf("workspace_provision: byok provider-matched strip — removing global-origin LLM cred %s (resolved provider=%s does not accept it)", key, provider.Name)
delete(envVars, key)
}
}
}
func runtimeUsesAnthropicNativeProxy(runtime string) bool {
return strings.EqualFold(strings.TrimSpace(runtime), "claude-code")
}
@@ -195,9 +195,16 @@ func (h *WorkspaceHandler) prepareProvisionContext(
applyAgentGitHTTPCreds(envVars, payload.Role)
// molecule-core#1994: per-workspace LLM billing-mode resolution + env wiring.
// On platform_managed it forces the CP proxy usage token; on byok/disabled
// it leaves the tenant's own creds (global OR workspace scope) untouched and
// reports whether a usable LLM credential is present.
llmRes := applyPlatformManagedLLMEnv(ctx, envVars, workspaceID, payload.Runtime, payload.Model)
// it keeps the tenant's own provider-MATCHING creds (global OR workspace
// scope) and reports whether a usable LLM credential is present.
//
// internal#728 Bug 1: globalSecretKeys (loadWorkspaceSecrets provenance)
// lets the byok branch strip ONLY operator-store-origin LLM creds that do
// NOT match the resolved provider's auth_env — so a non-anthropic-oauth
// claude-code workspace no longer inherits the stray tenant-global
// CLAUDE_CODE_OAUTH_TOKEN the runtime would greedily prefer. User-authored
// workspace_secrets (provenance flag cleared) are exempt.
llmRes := applyPlatformManagedLLMEnv(ctx, envVars, workspaceID, payload.Runtime, payload.Model, globalSecretKeys)
// Fail closed for a BYOK workspace with no usable LLM credential at ANY
// scope: do NOT start it credential-less. Mirror the "model+provider+
// credential REQUIRED at create" spirit with an actionable error surfaced
@@ -968,7 +968,7 @@ func TestApplyPlatformManagedLLMEnv_NonClaudeRuntimeDefaultsOpenAIProxyWhenNoWor
t.Setenv("MOLECULE_LLM_DEFAULT_MODEL", "moonshot/kimi-k2.6")
envVars := map[string]string{}
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "codex", "")
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "codex", "", nil)
applyRuntimeModelEnv(envVars, "codex", "")
if got := envVars["OPENAI_BASE_URL"]; got != "https://api.example.test/api/v1/internal/llm/openai/v1" {
@@ -998,7 +998,7 @@ func TestApplyPlatformManagedLLMEnv_StripsWorkspaceOpenAIKeyForClaudeCode(t *tes
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"MODEL": "openai/gpt-5.5",
}
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "")
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "", nil)
if _, ok := envVars["OPENAI_API_KEY"]; ok {
t.Fatalf("OPENAI_API_KEY should be stripped for claude-code platform-managed mode")
@@ -1024,7 +1024,7 @@ func TestApplyPlatformManagedLLMEnv_ClaudeCodeUsesAnthropicProxyOverOAuth(t *tes
"CLAUDE_CODE_OAUTH_TOKEN": "user-oauth-token",
"MODEL": "sonnet",
}
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "")
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "", nil)
if _, ok := envVars["CLAUDE_CODE_OAUTH_TOKEN"]; ok {
t.Fatalf("CLAUDE_CODE_OAUTH_TOKEN should be stripped in platform-managed mode")
@@ -1047,7 +1047,7 @@ func TestApplyPlatformManagedLLMEnv_ClaudeCodeInjectsAnthropicProxyWhenNoWorkspa
t.Setenv("MOLECULE_LLM_USAGE_TOKEN", "tenant-admin-token")
envVars := map[string]string{}
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "minimax/MiniMax-M2.7")
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "minimax/MiniMax-M2.7", nil)
if got := envVars["ANTHROPIC_BASE_URL"]; got != "https://api.example.test/api/v1/internal/llm/anthropic/v1" {
t.Fatalf("ANTHROPIC_BASE_URL = %q", got)
@@ -1070,7 +1070,7 @@ func TestApplyPlatformManagedLLMEnv_ClaudeCodeStripsVendorBYOK(t *testing.T) {
"MINIMAX_API_KEY": "user-minimax-key",
"MODEL": "MiniMax-M2.7",
}
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "")
applyPlatformManagedLLMEnv(context.Background(), envVars, "", "claude-code", "", nil)
if _, ok := envVars["MINIMAX_API_KEY"]; ok {
t.Fatalf("MINIMAX_API_KEY should be stripped in platform-managed mode")
@@ -1104,7 +1104,7 @@ func TestApplyPlatformManagedLLMEnv_NoopsOutsidePlatformManaged(t *testing.T) {
t.Setenv("MOLECULE_LLM_USAGE_TOKEN", "tenant-admin-token")
envVars := map[string]string{}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "kimi-for-coding")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "kimi-for-coding", nil)
if res.ResolvedMode != LLMBillingModeBYOK {
t.Fatalf("resolved mode = %q, want byok (derived from non-platform model)", res.ResolvedMode)
@@ -1151,7 +1151,7 @@ func TestApplyPlatformManagedLLMEnv_ClaudeCodeByokKeepsOwnProviderEnv(t *testing
"CLAUDE_CODE_OAUTH_TOKEN": "user-oauth-token",
"MODEL": "sonnet",
}
applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
// 1. OAuth token intact — not stripped.
if got := envVars["CLAUDE_CODE_OAUTH_TOKEN"]; got != "user-oauth-token" {
@@ -1213,7 +1213,7 @@ func TestApplyPlatformManagedLLMEnv_ByokGlobalScopeOAuthSurvivesAndRunsDirect(t
"MODEL": "opus",
}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
// 1. The tenant's own global-scope oauth SURVIVES — byok runs on it.
if envVars["CLAUDE_CODE_OAUTH_TOKEN"] != "TENANT-OWN-GLOBAL-OAUTH" {
@@ -1266,7 +1266,7 @@ func TestApplyPlatformManagedLLMEnv_DERIVED_PlatformModelKeepsPlatformCreds(t *t
t.Setenv("MOLECULE_LLM_USAGE_TOKEN", "tenant-admin-token")
envVars := map[string]string{}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "anthropic/claude-opus-4-7")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "anthropic/claude-opus-4-7", nil)
if res.ResolvedMode != LLMBillingModePlatformManaged {
t.Fatalf("platform-derived model must resolve platform_managed, got %q (source=%s)", res.ResolvedMode, res.Source)
@@ -1308,7 +1308,7 @@ func TestApplyPlatformManagedLLMEnv_DERIVED_ByokNoCredentialFailsClosed(t *testi
// No LLM credential at all — neither global nor workspace scope.
envVars := map[string]string{}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "kimi-for-coding")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "kimi-for-coding", nil)
// 1. DERIVED byok (NOT the old platform_managed default).
if res.ResolvedMode != LLMBillingModeBYOK {
@@ -1346,7 +1346,7 @@ func TestApplyPlatformManagedLLMEnv_DERIVED_UnsetModelPlatformDefault(t *testing
t.Setenv("MOLECULE_LLM_USAGE_TOKEN", "tenant-admin-token")
envVars := map[string]string{}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
if res.ResolvedMode != LLMBillingModePlatformManaged {
t.Fatalf("unset model must default platform_managed, got %q (source=%s)", res.ResolvedMode, res.Source)
@@ -1385,7 +1385,7 @@ func TestApplyPlatformManagedLLMEnv_ByokKeepsWorkspaceOwnOAuth(t *testing.T) {
"MODEL": "opus",
}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
if got := envVars["CLAUDE_CODE_OAUTH_TOKEN"]; got != "CUSTOMER-OWN-OAUTH-TOKEN" {
t.Fatalf("CLAUDE_CODE_OAUTH_TOKEN = %q, want the workspace's own token left intact", got)
@@ -1425,7 +1425,7 @@ func TestApplyPlatformManagedLLMEnv_DisabledKeepsTenantGlobalNoProxy(t *testing.
"CLAUDE_CODE_OAUTH_TOKEN": "TENANT-OWN-GLOBAL-OAUTH",
}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
// The tenant's own global cred survives (not stripped).
if envVars["CLAUDE_CODE_OAUTH_TOKEN"] != "TENANT-OWN-GLOBAL-OAUTH" {
@@ -1466,7 +1466,7 @@ func TestApplyPlatformManagedLLMEnv_PlatformManagedStillReceivesGlobalCreds(t *t
"MODEL": "opus",
}
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
res := applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
// Platform-managed routes through the CP proxy: OAuth stripped, proxy creds forced.
if _, ok := envVars["CLAUDE_CODE_OAUTH_TOKEN"]; ok {
@@ -1507,7 +1507,7 @@ func TestApplyPlatformManagedLLMEnv_PlatformManagedStillEmitsResolvedMode(t *tes
"CLAUDE_CODE_OAUTH_TOKEN": "user-oauth-token",
"MODEL": "sonnet",
}
applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "")
applyPlatformManagedLLMEnv(context.Background(), envVars, wsID, "claude-code", "", nil)
// OAuth stripped, proxy forced — unchanged platform_managed contract.
if _, ok := envVars["CLAUDE_CODE_OAUTH_TOKEN"]; ok {