# API Switching Test Plan

This document outlines how to test the API key switching functionality in the Super Admin panel.

## Overview

The API switching feature allows super admins to:
1. Add multiple API keys for each provider (Claude, Zhipu, Ollama)
2. Set one key as "active" (the star button)
3. Delete keys
4. Switch between keys instantly

## Architecture

### Frontend (SuperAdminModule.tsx)
- Located: `src/frontend/src/modules/system/super-admin/page.tsx`
- **APIKeysSection** component displays keys for each provider
- **handleActivateKey()** - calls `superAdminApi.activateAIKey(provider, index)`
- **handleAddKey()** - calls `superAdminApi.addAIKey(provider, {...})`
- **handleDeleteKey()** - calls `superAdminApi.deleteAIKey(provider, index)`

### Frontend API (api.ts)
```typescript
// API Key Management
addAIKey: (provider, data) => POST /super-admin/ai-keys
deleteAIKey: (provider, index) => DELETE /super-admin/ai-keys/:provider/:index
activateAIKey: (provider, index) => PUT /super-admin/ai-keys/:provider/:index/activate
```

### Backend Routes (superAdmin.ts)
- `POST /ai-keys` - Add a new key
- `DELETE /ai-keys/:provider/:index` - Remove a key
- `PUT /ai-keys/:provider/:index/activate` - Set a key as active

### Backend Logic (aiProvider.ts)
- `getAIConfig()` - Reads config from DB with 30-second cache
- `getActiveKey(keys)` - Returns the key where `isActive: true`
- `invalidateAICache()` - Clears cache when keys change

## Test Cases

### Test 1: Add Multiple Claude Keys
1. Login as super admin
2. Go to Settings tab
3. Under "Claude API Keys", click "Add Key"
4. Enter first key: `sk-ant-api03-test-key-1`
5. Verify it's automatically marked as "Active" (first key)
6. Add second key: `sk-ant-api03-test-key-2`
7. Verify second key is NOT active (no star)

### Test 2: Switch Active Key
1. Click the star icon on the second key
2. Verify:
   - Star appears on the second key
   - Star disappears from first key
   - Loading spinner shows during activation
3. Check backend logs for: `[SuperAdmin] Activate AI key` message

### Test 3: Delete Key
1. Click delete (trash icon) on first key
2. Confirm the deletion
3. Verify:
   - First key is removed
   - Second key remains active

### Test 4: Cache Invalidation
1. After activating a new key
2. Make an AI generation request
3. Verify the backend uses the newly activated key

### Test 5: Key Masking
1. Add a key: `sk-ant-api03-abcdef123456`
2. View the displayed key
3. Verify it shows: `****3456` (last 4 chars only)

### Test 6: Provider Detection
1. Set AI Provider to "Auto-detect"
2. Add Claude key → should use Claude
3. Add Zhipu key → set as active → should use Zhipu
4. Check AI provider detection logic works

## Code Flow Verification

### Activation Flow:
```
Frontend: handleActivateKey('claude', 1)
   ↓
API: PUT /super-admin/ai-keys/claude/1/activate
   ↓
Backend: superAdmin.ts
   - Find super admin user
   - Get claudeKeys array
   - Set all keys.isActive = false
   - Set keys[1].isActive = true
   - Save to database
   - Call invalidateAICache()
   ↓
aiProvider.ts: getAIConfig()
   - Cache cleared (cacheExpiry = 0)
   - Next AI call reads fresh config from DB
   - getActiveKey(claudeKeys) returns keys[1]
   - Uses keys[1].key for API calls
```

## Key Functions

### getActiveKey() in aiProvider.ts:
```typescript
function getActiveKey(keys: APIKeyEntry[] = []): APIKeyEntry | null {
  return keys.find(k => k.isActive && k.key) || null;
}
```

### activateAIKey() in frontend:
```typescript
const handleActivateKey = async (provider: 'claude' | 'zhipu' | 'ollama', index: number) => {
  setKeyOperationLoading(`activate-${provider}-${index}`);
  try {
    const res = await superAdminApi.activateAIKey(provider, index);
    if (res.error) throw new Error(res.error);
    // Update local state
    setForm(prev => ({
      ...prev,
      aiConfig: {
        ...prev.aiConfig,
        [keysArray]: prev.aiConfig[keysArray].map((k, i) => ({
          ...k,
          isActive: i === index,
        })),
      },
    }));
  } catch (err: any) {
    console.error('Failed to activate key:', err);
  } finally {
    setKeyOperationLoading(null);
  }
};
```

### Backend Activate Route (superAdmin.ts):
```typescript
router.put('/ai-keys/:provider/:index/activate', [...], async (req, res) => {
  const { provider, index } = req.params;
  const keys: APIKeyEntry[] = currentAi[keysArrayName] || [];
  
  // Set all keys to inactive, then activate the selected one
  keys.forEach((k, i) => {
    k.isActive = (i === indexNum);
  });
  
  // Save and invalidate cache
  superAdmin.markModified('panelSettings');
  await superAdmin.save();
  invalidateAICache();
  
  res.json({ provider, keys: maskKeysArray(keys) });
});
```

## Potential Issues to Check

1. **Cache Timing**: The AI config has a 30-second cache. After switching keys:
   - First AI call within 30s might use old key
   - `invalidateAICache()` should clear this immediately

2. **Concurrent Requests**: If multiple AI requests are in-flight when switching:
   - Old requests use old key
   - New requests use new key
   - This is expected behavior

3. **Error Handling**: Check error messages when:
   - No keys configured
   - Invalid key index
   - Database save fails

## Manual Test Steps

1. Start the backend:
   ```bash
   cd src/backend
   npm run dev
   ```

2. Start the frontend:
   ```bash
   cd src/frontend
   npm run dev
   ```

3. Login as super admin (role: 'super-admin')

4. Navigate to: `/super-admin/settings`

5. Test each provider's key management:
   - Claude API Keys
   - Zhipu / GLM API Keys
   - Ollama API Keys

6. For each provider:
   a. Add 2-3 keys
   b. Switch active key multiple times
   c. Delete keys
   d. Verify UI updates correctly

7. Verify AI calls use the correct key:
   - Generate AI content
   - Check backend logs for API key being used

## Success Criteria

- ✅ Can add multiple keys per provider
- ✅ Can switch active key (star button)
- ✅ Active key is visually highlighted
- ✅ Keys are masked (only last 4 chars visible)
- ✅ Delete key works with confirmation
- ✅ First key added is automatically active
- ✅ Cache invalidation works (30s TTL + manual clear)
- ✅ Error handling shows user-friendly messages
- ✅ Loading states show during operations