# Runbook — Provider IA Down / Circuit Breaker Ouvert

**Alerte :** `VeylantCircuitBreakerOpen` (severity: critical) ou `VeylantHighErrorRate`
**SLA impact :** Dégradation partielle (fallback) ou interruption totale (aucun fallback)
**Temps de résolution cible :** < 15 minutes

---

## Symptômes

- Alerte PagerDuty/Slack `VeylantCircuitBreakerOpen` pour un provider
- Réponses 503 aux requêtes `/v1/chat/completions` pour le provider affecté
- Erreur rate > 5% sur le dashboard Grafana
- Logs : `"circuit breaker open"` avec `provider=openai` (ou autre)

---

## Diagnostic

### 1. Identifier le provider affecté

```bash
# Voir l'état des circuit breakers dans les métriques Prometheus
curl -s http://localhost:9090/api/v1/query?query=veylant_circuit_breaker_state | \
  jq '.data.result[] | {provider: .metric.provider, state: .metric.state, value: .value[1]}'

# Logs du proxy (dernières 10 minutes)
kubectl logs -n veylant deploy/veylant-proxy-blue --since=10m | \
  grep -E "(circuit_breaker|provider_error|upstream)"
```

### 2. Vérifier le statut du provider en amont

```bash
# OpenAI
curl -sf https://status.openai.com/api/v2/status.json | jq .status.description

# Anthropic
curl -sf https://status.anthropic.com/api/v2/status.json | jq .status.description

# Azure OpenAI — remplacer par l'endpoint configuré
curl -sf https://YOUR_RESOURCE.openai.azure.com/ | head -1
```

### 3. Tester directement le provider

```bash
# Test OpenAI direct (bypasse le proxy)
curl -sf -X POST https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"ping"}]}' | \
  jq .choices[0].message.content
```

### 4. Vérifier les routing rules de fallback

```bash
# Afficher les règles de routing actives (admin API)
curl -sf -H "Authorization: Bearer $ADMIN_TOKEN" \
  https://api.veylant.ai/v1/admin/routing-rules | \
  jq '.[] | {name: .name, provider: .target_provider, fallback: .fallback_provider}'
```

---

## Remédiation

### Option A — Fallback automatique déjà actif

Si une règle de fallback est configurée, le proxy bascule automatiquement sur le provider secondaire. Vérifier :

```bash
# Confirmer que les requêtes passent via le fallback
kubectl logs -n veylant deploy/veylant-proxy-blue --since=2m | \
  grep "fallback" | tail -20
```

Si le fallback fonctionne → **surveiller**, ne pas intervenir. Le circuit breaker se referme automatiquement après 60 secondes si le provider se rétablit.

### Option B — Forcer le reset du circuit breaker

Si le provider est rétabli mais le circuit breaker est resté ouvert :

```bash
# Reset manuel via l'API admin
curl -sf -X POST \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  https://api.veylant.ai/v1/admin/providers/openai/reset-circuit-breaker
```

### Option C — Désactiver temporairement le provider affecté

```bash
# Modifier la routing rule pour exclure le provider down
curl -sf -X PATCH \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_provider": "anthropic", "fallback_provider": null}' \
  https://api.veylant.ai/v1/admin/routing-rules/default-rule

echo "Traffic routed to Anthropic — monitor for 5 minutes"
```

### Option D — Panne prolongée du provider (> 30 min)

```bash
# Activer le message de maintenance pour les utilisateurs affectés
# (feature flag via l'API admin)
curl -sf -X PATCH \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}' \
  https://api.veylant.ai/v1/admin/flags/maintenance-mode

# Notifier les clients impactés via Slack
# Template : "Nous faisons face à une interruption du provider [X].
# Vos requêtes sont temporairement routées vers [Y].
# Impact estimé : [durée]. Nous surveillons activement."
```

---

## Escalade

| Niveau | Condition | Action |
|--------|-----------|--------|
| L1 (on-call) | Circuit breaker ouvert, fallback actif | Surveiller 15 min |
| L2 (platform) | Panne > 15 min sans fallback | Patch routing rules + notification clients |
| L3 (CTO) | Panne totale > 1h (tous providers) | Activation mode maintenance + communication officielle |

**Contacts :**
- On-call : PagerDuty rotation → Slack `#veylant-critical`
- Provider SLA support : support@openai.com / support@anthropic.com

---

## Prévention

- Configurer un `fallback_provider` pour chaque routing rule critique
- Tester le fallback mensuellement (faire planter le circuit breaker en staging)
- Surveiller les `status.openai.com` / `status.anthropic.com` via webhook Slack

---

## Post-mortem Template

```markdown
## Post-mortem — Provider Down [DATE]

**Durée d'impact :** [X minutes]
**Providers affectés :** [liste]
**Requêtes échouées :** [N] (error_rate: X%)

### Timeline
- HH:MM — Alerte VeylantCircuitBreakerOpen reçue
- HH:MM — Diagnostic confirmé : [provider] en panne
- HH:MM — Fallback activé / Action prise
- HH:MM — Service rétabli

### Root Cause
[Description de la cause racine]

### Actions correctives
- [ ] [Action 1]
- [ ] [Action 2]
```
