fix(workspace): project Anthropic adapter creds for BYOK MiniMax on restart with workspace override (core#2712) #2735

Merged
devops-engineer merged 1 commits from fix/2712-restart-byok-minimax-projection into main 2026-06-13 08:55:19 +00:00
2 changed files with 53 additions and 1 deletions
@@ -446,3 +446,42 @@ func TestApplyPlatformManagedLLMEnv_ProxyEnvPresentInjectsCredential(t *testing.
t.Errorf("sqlmock expectations: %v", err)
}
}
// TestApplyPlatformManagedLLMEnv_BYOKMiniMaxWorkspaceOverrideProjectsCreds is
// core#2712: a claude-code workspace with an explicit per-workspace BYOK
// override and a stored MiniMax model must still project ANTHROPIC_AUTH_TOKEN
// and ANTHROPIC_BASE_URL from MINIMAX_API_KEY.
//
// ResolveLLMBillingModeDerived returns early on a workspace_override with
// ProviderSelection=nil. Without a fallback derivation here, the core#2709
// projection block would skip because providerFromRegistry("") fails, leaving
// the Anthropic SDK adapter credential-less after restart.
func TestApplyPlatformManagedLLMEnv_BYOKMiniMaxWorkspaceOverrideProjectsCreds(t *testing.T) {
ctx := context.Background()
const wsID = "b4914c3d-7ce0-4e14-aa32-02da048e2ae7"
mock := setupTestDB(t)
expectOverrideQuery(mock, wsID, LLMBillingModeBYOK)
envVars := map[string]string{
"MODEL": "MiniMax-M2.7",
"MINIMAX_API_KEY": "real-minimax-key",
}
res := applyPlatformManagedLLMEnv(ctx, envVars, wsID, "claude-code", "", nil)
if res.ResolvedMode != LLMBillingModeBYOK {
t.Fatalf("resolved mode = %q, want byok", res.ResolvedMode)
}
if got := envVars["ANTHROPIC_AUTH_TOKEN"]; got != "real-minimax-key" {
t.Fatalf("ANTHROPIC_AUTH_TOKEN = %q, want real-minimax-key", got)
}
if got := envVars["ANTHROPIC_BASE_URL"]; got != "https://api.minimax.io/anthropic/v1" {
t.Fatalf("ANTHROPIC_BASE_URL = %q, want https://api.minimax.io/anthropic/v1", got)
}
if got := envVars["MINIMAX_API_KEY"]; got != "real-minimax-key" {
t.Fatalf("MINIMAX_API_KEY was overwritten: %q", got)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("sqlmock expectations: %v", err)
}
}
@@ -1170,7 +1170,20 @@ func applyPlatformManagedLLMEnv(ctx context.Context, envVars map[string]string,
// restart. Project the provider's preferred auth token env and Anthropic
// base URL from the workspace's available provider credential.
if res.ResolvedMode == LLMBillingModeBYOK && runtimeUsesAnthropicNativeProxy(runtime) {
if provider, ok := providerFromRegistry(derefOrEmpty(res.ProviderSelection)); ok && provider.AuthTokenEnv != "" {
providerName := derefOrEmpty(res.ProviderSelection)
// core#2712: a per-workspace billing-mode override (source=workspace_override)
// short-circuits ResolveLLMBillingModeDerived before it sets ProviderSelection,
// but the Anthropic-adapter projection still needs to know WHICH BYOK
// provider the workspace is running so it can map MINIMAX_API_KEY (etc.)
// to ANTHROPIC_AUTH_TOKEN. Derive it from the effective model when missing.
if providerName == "" && effectiveModel != "" {
if manifest, mErr := providerRegistry(); mErr == nil && manifest != nil {
if p, dErr := manifest.DeriveProvider(runtime, effectiveModel, availableAuthEnv); dErr == nil {
providerName = p.Name
}
}
}
if provider, ok := providerFromRegistry(providerName); ok && provider.AuthTokenEnv != "" {
if _, hasToken := envVars[provider.AuthTokenEnv]; !hasToken {
for _, authEnv := range provider.AuthEnv {
if v := strings.TrimSpace(envVars[authEnv]); v != "" {