# CLAUDE.md — UQO-Chat (copie de travail) La spécification d'origine (28 sections) est la référence produit ; ce fichier résume ce qui est **implémenté**, les **écarts assumés** et les règles à respecter en travaillant dans ce dépôt. Voir `README.md` pour le démarrage et le déploiement. ## Règles d'or (inchangées) 1. Aucun code étudiant/LLM ne s'exécute dans le processus API : toujours `sandbox-runner` (`app/sandbox/client.py`). 2. Un seul point d'entrée LLM : `app/llm/openrouter.py` → `LLMClient`. 3. Slugs de modèles = config (`app/core/config.py`, env). Vérifier https://openrouter.ai/models avant d'en changer (vérifiés 2026-09-05 : `anthropic/claude-fable-5.1` (primaire depuis le 2026-09-06), `openai/gpt-5.5`, `anthropic/claude-opus-4.6`, `openai/gpt-5.4-nano`). 4. Chaque outil = `app/tools/.py` + `app/tools/schemas/.json` + test + carte `frontend/src/components/tools/-card.tsx`. 5. Streaming SSE partout (`app/api/v1/chat.py`), français dans l'UI/prompts, anglais dans le code. 6. Jamais de contenu de message dans les logs (`app/core/logging.py` masque `content`, `text`, `email`…). 7. Mobile-first (375 px) ; QA Playwright : `python3 /tmp/uqo-qa/qa.py` (captures 375/1440, détection d'overflow). ## État (v0.3, 2026-09-06) - 13 outils : search_course_content, appraisal_calc, financial_calc, unit_convert, execute_python, make_chart, create_excel, inspect_excel, edit_excel, create_docx, analyze_file, web_search, generate_quiz. Auth (v0.5) : liste blanche gérée par le professeur → invitation Resend « choisis ton mot de passe » (`/mot-de-passe?token=`) → connexion courriel + mot de passe (PBKDF2) ; « première connexion / mot de passe oublié » par courriel ; plus de code d'accès. Tableau de bord prof : Activité, Étudiants (ajout en lot + invitations, relances, statut activé/invité, mots de passe manuels), Contenu, Réglages. Modèle par défaut `anthropic/claude-fable-5.1`, budget 2 000 $ US/mois. - Backend FastAPI 3.12 : auth (invitation/réinitialisation par courriel Resend + mot de passe ; `services/mail.py`, `services/invites.py`), conversations, chat SSE avec boucle agentique (8 itérations, outils en parallèle), 7 outils, RAG BM25 sur les sites de notes (`rag/ingest.py` lit le HTML généré `dist//seance/NN`), quiz, fichiers (TTL), tableau de bord prof (analytics anonymisées, ingestion, réglages, annonces), coûts admin, purge/anonymisation horaire. - Frontend React 18 + Vite + Tailwind : chat mobile/desktop, cartes d'outils, quiz interactif, panneau fichiers/sources, préférences, Loi 25 (consentement, suppression), PWA (précache ≈ 2 Mo). - Sandbox : `sandbox-runner/` (FastAPI) exécute `python -I -B` sous `sandbox-exec` (macOS) : réseau interdit, écriture confinée, rlimits, timeout, figures matplotlib capturées. - Déploiement : `mld` (PM2 `uqo-chat-api` :8190 + `uqo-chat-sandbox` :8191 + `uqo-chat-ngrok` www.uqo-chat.app). Secrets dans `M1M32:~/dispatch/apps/uqo-chat.json`. ## Écarts assumés SQLite au lieu de Postgres/pgvector (Postgres accepté via `DATABASE_URL`) ; cache/limiteur mémoire au lieu de Redis ; fichiers sur disque au lieu de MinIO ; BM25 au lieu d'embeddings (OpenRouter n'en propose pas ; `EMBEDDINGS_BASE_URL` optionnel) ; `create_all` au lieu d'Alembic ; Resend (API HTTP) au lieu d'un SMTP, mot de passe au lieu du lien magique à chaque connexion. `k8s/` + `docker-compose.yml` décrivent la cible complète de la spec. ## À faire (roadmap spec) Export PDF de conversation ; file d'attente hors-ligne (Background Sync) ; évaluation pédagogique automatique en CI (40 questions/cours, juge `MODEL_FAST`) ; tests adverses sandbox complets ; Alembic ; migration éventuelle Postgres/pgvector ; autorisation du logo officiel UQO (`VITE_USE_OFFICIAL_LOGO`).