SPB Git forge

spb/immbot-ai

Public
1commits 1branches 0releases
1.5 MBsize
maindefault branch
20 days agolast push
TypeScript 98.3% CSS 0.9% Shell 0.7%
4.3 KB · 68 lines markdown
Rendered Raw Blame History
1# Modèle de sécurité — Immbot AI23## Authentification45- **Sessions serveur** : cookie `immbot_session` httpOnly, `SameSite=Lax`, `Secure` en production,6  identifiant aléatoire 256 bits, **haché (SHA-256) avant stockage** dans la table `sessions`7  (un vol de la BD ne permet pas de rejouer une session). Expiration 14 jours glissants,8  révocation à la déconnexion et depuis l'admin.9- **Mots de passe** : bcrypt (coût 12) via bcryptjs. Politique : ≥ 10 caractères. `admin123`10  explicitement refusé comme mot de passe permanent.11- **Compte initial** : créé par script de seed depuis `INITIAL_ADMIN_USERNAME` /12  `INITIAL_ADMIN_PASSWORD` (défauts admin/admin123), champ `must_change_password=1` →13  redirection forcée vers le changement de mot de passe, bannière d'avertissement tant que14  le mot de passe initial est actif. `DISABLE_INITIAL_ADMIN=true` en production le désactive.15- **Limitation des tentatives** : 8 échecs / 15 min par (IP + identifiant), à mémoire serveur +16  journalisées dans `auth_events` (connexions, échecs, changements de mot de passe, déconnexions).17- **Récupération** : changement par l'utilisateur (mot de passe actuel requis) ; réinitialisation18  par l'admin (mot de passe temporaire + changement forcé). Pas de courriel en v1 (documenté).19- **CSRF** : mutations via `fetch` même origine + vérification systématique de l'en-tête20  `Origin`/`Sec-Fetch-Site` sur toutes les routes mutantes + cookies SameSite. Pas de formulaires21  cross-site.22- **SSO futur** : la table `users` porte `auth_provider` (`local` aujourd'hui) et un identifiant23  externe nullable — l'ajout d'OIDC (Microsoft/Google/UQO) n'exige pas de migration.2425## Autorisation2627- Rôles : `student` < `instructor` < `admin` (l'admin a tout ; l'instructeur a la pédagogie et le28  contenu, pas la gestion des utilisateurs).29- **Contrôle d'accès par cours** : table `enrollments` ; toute requête chat/RAG/apprentissage vérifie30  l'inscription au cours visé, côté serveur.31- **Espaces de connaissances** : chaque fragment porte `space`32  (`official-imm1003`, `official-imm1033`, `student-temporary-upload`, `student-persistent-files`,33  `instructor-private`, `general-knowledge`). Les requêtes étudiantes ne touchent jamais34  `instructor-private` ni les téléversements d'un autre étudiant (filtre SQL systématique, testé).35- Routes `/admin` et `/api/admin/*` : middleware + revérification du rôle dans chaque handler.3637## Secrets et données3839- `OPENROUTER_API_KEY` uniquement côté serveur (routes API) ; jamais dans un composant client,40  jamais journalisée. `.env` gitignoré ; `.env.example` sans valeurs réelles.41- Journaux structurés sans secrets ni contenu de mot de passe ; les messages d'erreur client ne42  fuient pas les détails internes.43- Données étudiantes : minimisation (nom d'utilisateur, courriel optionnel) ; les statistiques44  professeur sont **agrégées et anonymisées** (seuil de 3 étudiants minimum avant affichage d'un45  agrégat) ; le contenu individuel n'est jamais montré.46- `submissions.db` du prototype et le matériel d'examen : exclus / `instructor-private` (voir47  repository-analysis.md).48- Sauvegardes : `scripts/backup.sh` (copie datée de `data/` hors uploads temporaires).4950## Défenses applicatives5152- Validation zod de toutes les entrées API ; limites de taille (messages 32 k, uploads 25 Mo,53  types MIME vérifiés par signature).54- Requêtes SQL exclusivement préparées (aucune concaténation).55- Rendu Markdown sans HTML brut (`skipHtml`) → pas de XSS via réponses de modèle.56- En-têtes : CSP (script-src 'self'), X-Content-Type-Options, Referrer-Policy, X-Frame-Options DENY.57- Injection de prompt : le contenu récupéré et les fichiers étudiants sont encadrés de délimiteurs58  et le prompt système précise qu'ils sont des **données**, pas des instructions ; la validation de59  citations empêche l'exfiltration de fragments non autorisés (le serveur ne fournit au modèle que60  les fragments auxquels l'utilisateur a déjà droit).61- Limites d'usage : budgets quotidiens/mensuels par utilisateur et globaux, appliqués côté serveur62  avant chaque appel modèle.6364## Journalisation et audit6566`auth_events` (sécurité), `usage_log` (appels modèles : utilisateur, modèle, jetons, coût, latence),67`ingestion_runs` (contenu), `report_flags` (réponses signalées). Consultables dans l'admin.68