# Per-Provider API Key Management System

## Overview
Implements secure, per-provider API key storage for the stock market dashboard supporting multiple API providers (Twelve Data, Finnhub, etc.).

## Architecture

### 1. Server-Side Storage (PHP Backend)
**File:** `/Users/rbutare/downloads/api/finnhub-key.php`

Stores API keys in per-provider files:
- `~/.downloads/.finnhub/apiKey_twelve.txt` (Twelve Data key)
- `~/.downloads/.finnhub/apiKey_finnhub.txt` (Finnhub key)

**Endpoints:**
```
GET  /downloads/api/finnhub-key.php?action=get&provider=twelve
  → { key: "...", cached: false }

POST /downloads/api/finnhub-key.php?action=set&provider=twelve
  Body: { key: "..." }
  → { success: true }

GET  /downloads/api/finnhub-key.php?action=delete&provider=twelve
  → { success: true }
```

**Security:**
- File permissions: 0600 (user-only read/write)
- Directory permissions: 0700 (user-only)
- Provider name sanitization (alphanumeric only)
- Key length validation (10-500 chars)

### 2. Client-Side Storage (JavaScript)
**File:** `/Users/rbutare/downloads/dash.html`

Per-provider keys stored in preferences object:
```javascript
prefs.apiKey_twelve    // Twelve Data API key
prefs.apiKey_finnhub   // Finnhub API key
prefs.apiProvider      // Currently selected provider ('twelve' or 'finnhub')
```

### 3. Key Management Functions

#### `getProviderKey(provider)`
Retrieves API key from local preferences for given provider
```javascript
const key = getProviderKey('twelve');  // Returns: string or ''
```

#### `setProviderKey(provider, key)`
Saves API key to local preferences
```javascript
setProviderKey('twelve', 'abc123def456');
```

#### `editProviderKey(provider)`
Interactive prompt to enter/update API key for provider
```javascript
editProviderKey('twelve');  // Prompts user, saves to server and prefs
```

#### `updateKeyDisplay()`
Updates preference UI to show masked keys for both providers
```javascript
updateKeyDisplay();  // Updates #keyDisplay-twelve and #keyDisplay-finnhub
```

#### `serverKeyGet(provider = null)`
Retrieves API key from server for given provider (or current API_PROVIDER)
```javascript
const key = await serverKeyGet('twelve');
```

#### `serverKeySet(value, provider = null)`
Saves API key to server for given provider (or current API_PROVIDER)
```javascript
await serverKeySet('abc123def456', 'twelve');
```

#### `serverKeyDelete(provider = null)`
Deletes API key from server for given provider (or current API_PROVIDER)
```javascript
await serverKeyDelete('twelve');
```

#### `switchApiProvider(provider)`
Switches active API provider, loading provider-specific key
```javascript
switchApiProvider('finnhub');  
// Sets API_PROVIDER = 'finnhub'
// Loads Finnhub key via getProviderKey('finnhub')
// Clears quote cache
// Updates UI
// Refreshes data if key is available
```

## Flow Diagrams

### On App Initialization
```
DOMContentLoaded
  ├─ Load API_PROVIDER from prefs (default: 'twelve')
  ├─ Load server key via serverKeyGet(API_PROVIDER)
  ├─ Fall back to prefs via getProviderKey(API_PROVIDER)
  ├─ If no key found, prompt user
  │   ├─ Save to server via serverKeySet(key, API_PROVIDER)
  │   └─ Save to prefs via setProviderKey(API_PROVIDER, key)
  ├─ Load all preferences (including both provider keys)
  ├─ Update preference display via updateKeyDisplay()
  └─ Initialize watchlists and refresh data
```

### On Provider Switch
```
switchApiProvider('finnhub')
  ├─ Update API_PROVIDER = 'finnhub'
  ├─ Load key via getProviderKey('finnhub')
  ├─ Update updateProviderInfo() display
  ├─ Clear quote cache
  └─ Refresh watchlist data (if key available)
```

### On Key Input in Preferences
```
editProviderKey('twelve')
  ├─ Prompt user for API key
  ├─ Validate key (if provided)
  ├─ Save to server via serverKeySet(key, 'twelve')
  ├─ Save to prefs via setProviderKey('twelve', key)
  └─ Update display via updateKeyDisplay()
```

## Preferences UI

**Section 1: API Provider Selection**
```html
<select id="apiProviderSelect">
  <option value="twelve">Twelve Data (indices + stocks + ETFs)</option>
  <option value="finnhub">Finnhub (stocks + ETFs)</option>
</select>
```

**Section 2: Twelve Data API Key**
```html
<div class="form-group">
  <label>Twelve Data API Key</label>
  <input type="password" id="keyDisplay-twelve" readonly />
  <button onclick="editProviderKey('twelve')">Set</button>
  <small>✅ Includes market indices, stocks & ETFs. 800 requests/day.</small>
</div>
```

**Section 3: Finnhub API Key**
```html
<div class="form-group">
  <label>Finnhub API Key</label>
  <input type="password" id="keyDisplay-finnhub" readonly />
  <button onclick="editProviderKey('finnhub')">Set</button>
  <small>Stocks & ETFs only. 60 requests/min.</small>
</div>
```

## API Support

### Twelve Data
- **Base URL:** `https://api.twelvedata.com`
- **Signup:** https://twelvedata.com
- **Features:** Indices (^DJI, ^IXIC), Stocks, ETFs
- **Rate Limit:** 800 requests/day (free tier)
- **Auth:** `apikey=YOUR_KEY` parameter

### Finnhub
- **Base URL:** `https://finnhub.io/api/v1`
- **Signup:** https://finnhub.io
- **Features:** Stocks, ETFs (no indices)
- **Rate Limit:** 60 requests/min (free tier)
- **Auth:** `token=YOUR_KEY` parameter

## Response Normalization

Both APIs return quote data with different field names. The `getQuote(symbol)` function normalizes:

**Twelve Data Response:**
```javascript
{ close: 150.25, open: 149.80, previous_close: 149.50 }
```

**Normalized Response (both):**
```javascript
{ c: 150.25, o: 149.80, pc: 149.50 }  // Standard format
```

## Testing Checklist

- [x] PHP backend syntax valid
- [x] Per-provider key files created correctly
- [x] serverKeyGet() retrieves provider-specific keys
- [x] serverKeySet() saves provider-specific keys
- [x] serverKeyDelete() removes provider-specific keys
- [ ] User can set Twelve Data key without Finnhub key
- [ ] User can set Finnhub key without Twelve Data key
- [ ] Switching provider loads correct key
- [ ] API calls use correct provider-specific key
- [ ] Preference display shows masked keys for both providers
- [ ] Keys persist across browser refresh
- [ ] Keys persist across provider switches

## Security Features

1. **Server-Side Storage:** Keys never stored in browser localStorage
2. **File Permissions:** 0600 (user-only readable/writable)
3. **Directory Permissions:** 0700 (user-only accessible)
4. **Provider Sanitization:** Only alphanumeric provider names accepted
5. **Key Validation:** 10-500 character length required
6. **No Logging:** Keys not logged to console or files

## Migration Path

Old system (single shared key):
- Single file: `~/.downloads/.finnhub/api-key.txt`
- Single prefs key: `prefs.mp_api_key`

New system (per-provider keys):
- Multiple files: `~/.downloads/.finnhub/apiKey_[provider].txt`
- Multiple prefs keys: `prefs.apiKey_[provider]`

**Backward Compatibility:** If old single key exists, it can be manually migrated by:
1. Copying `api-key.txt` to `apiKey_twelve.txt` or `apiKey_finnhub.txt`
2. Setting provider-specific keys via preferences UI
