# Sécurité — BLADE

## Rotation en cours (2026-04-18)

Deux secrets ont été exposés en texte clair dans une conversation d'assistance le **18 avril 2026**. Ils doivent être considérés comme compromis et **remplacés avant toute mise en production** :

| Secret | Où régénérer | Nouvelle destination |
| --- | --- | --- |
| Facebook App Secret (app `785906557842131`) | https://developers.facebook.com/apps/785906557842131/settings/basic/ → *Reset App Secret* | `FB_APP_SECRET` dans `/opt/blade/.env` sur le VPS Vestly |
| OpenAI API Key | https://platform.openai.com/api-keys → *Revoke* puis *Create new* | `OPENAI_API_KEY` dans `/opt/blade/.env` sur le VPS Vestly |

### Après rotation

1. Placer les nouvelles valeurs **uniquement** dans `/opt/blade/.env` sur le VPS (permissions `600`, propriétaire `blade:blade`).
2. Redémarrer le service : `sudo systemctl restart blade.service`.
3. Vérifier les logs : `sudo journalctl -u blade.service -n 50`.
4. Confirmer que `curl https://<blade-domain>/health` répond `{"status":"ok"}`.

## Règles permanentes

- **Jamais** de secret dans le repo Git (commits, historique, issues).
- **Jamais** de secret dans `config.js` ou tout autre fichier front-end (un frontend servi est public).
- **Jamais** de secret dans un canal conversationnel (chat, Slack, ticket, e-mail).
- App Secret Meta, OpenAI Key, tokens long-lived : **serveur uniquement**.
- Page Access Tokens courts : fourniture à la volée par le backend après auth OAuth, stockés chiffrés en IndexedDB côté client (clé AES-GCM dérivée de la session).

## Flow d'authentification Facebook (cible)

```
Utilisateur  →  FB.login() JS SDK  →  short-lived user token
         ↘
           POST /oauth/exchange (backend BLADE)
                ↘  utilise FB_APP_SECRET côté serveur uniquement
                   GET /oauth/access_token?grant_type=fb_exchange_token
                ↙  renvoie long-lived user token (60 jours)
           Backend dérive les page tokens (qui n'expirent pas)
                ↘  renvoie au frontend : {pages, igAccounts} sans secret
         ↙
Frontend  →  stockage IndexedDB chiffré  →  appels via /graph/* (proxy backend)
```

## Content Security Policy (attendue)

Voir `index.html` (une fois le hardening appliqué). Directives minimales :

```
default-src 'self';
connect-src 'self' https://<backend-domain> wss://<backend-domain> https://connect.facebook.net;
script-src 'self' https://connect.facebook.net 'nonce-<X>';
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https://*.fbcdn.net https://*.cdninstagram.com;
object-src 'none';
base-uri 'self';
```

## Détection de token committé

Le frontend (`js/app.js`) intègre une garde de démarrage qui refuse de s'initialiser si un token Facebook committé est détecté dans `config.js` ou `config.local.js` une fois en production. Voir `ensureNoCommittedToken()`.

## Qui contacter en cas de fuite

Remplace les secrets d'abord, communique ensuite. L'ordre :
1. Révoquer dans les dashboards fournisseurs.
2. Auditer `git log -p config.js` et équivalent pour détecter d'éventuels commits fuités.
3. Purger l'historique Git si nécessaire (`git filter-repo` ou BFG).
4. Forcer un `git push --force` après validation du propriétaire.
