Commit Graph

5 Commits

Author SHA1 Message Date
cedric d8a771161c feat(auth): refresh token Directus explicite dans le callback JWT NextAuth
Sans ce correctif, l'access token Directus (~15 min) expirait silencieusement,
rendant toutes les requêtes API 401 sans déconnecter l'utilisateur.

- Ajout de refreshDirectusToken() : POST /auth/refresh avec rotation du refresh_token
- accessTokenExpires stocké dès la connexion (expires Directus - marge 60s)
- jwt callback : token valide → pass-through, token expiré → refresh, échec → error flag
- session callback : propagation de session.error = 'RefreshAccessTokenError'
  (permet au client de forcer un signOut si le refresh_token est lui-même expiré)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 06:37:11 +04:00
cedric 7b831d5bc4 test: tests unitaires Vitest — format, version-utils, rate-limit
- Installe vitest@4 + @vitest/coverage-v8 (40 tests, 0 échec)
- lib/__tests__/format.test.js        : 14 tests (formatKonstitisyon, formatDate, hasRestrictedChar)
- lib/__tests__/version-utils.test.js : 17 tests (filterVersions par texte/auteur/date, getFilterStats)
- lib/__tests__/rate-limit.test.js    : 9 tests avec fake timers (limite, reset, retryAfter, keys indépendantes)
- vitest.config.mjs : environnement node, imports explicites (pas de globals)
- package.json : scripts test / test:watch / test:coverage + override XO pour les fichiers de test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 06:30:10 +04:00
cedric 170c3c5e90 security: Content Security Policy et headers HTTP sécurité
- Renomme next.config.js → next.config.mjs (ESM, satisfait unicorn/prefer-module)
- Ajout de headers() avec CSP stricte :
    script/style-src 'unsafe-inline' (requis Next.js + Emotion/MUI)
    connect-src dynamique depuis les env vars Directus (API + WebSocket)
    object-src 'none', frame-ancestors 'none', base-uri 'self'
    img-src 'self' data: blob: (html2canvas / export PDF)
- Ajout X-Frame-Options, X-Content-Type-Options, Referrer-Policy,
  Permissions-Policy sur toutes les routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 21:55:40 +04:00
cedric dc1f115bd6 security: sanitiser la sortie marked avec DOMPurify (XSS)
export-pdf-button et print-button injectaient marked(content) directement
dans innerHTML / document.write. Un lien Markdown javascript: passait le
filtre hasRestrictedChar et pouvait s'exécuter.

Ajout de DOMPurify.sanitize() via import dynamique (déjà présent en dep
transitive de jspdf) sur les deux composants, avec whitelist de tags
et d'attributs stricte. markdown-renderer n'est pas touché car
react-markdown-preview utilise rehype-sanitize en interne.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 21:48:26 +04:00
cedric d8a63bc4d8 feat: rate limiting sur les routes d'authentification critiques
- Ajout de lib/rate-limit.js : fabrique de limiter en mémoire (closure +
  Map avec nettoyage lazy), sans dépendance externe, réutilisable
- Ajout de middleware.js : intercepte /api/auth/register (5 req/15min)
  et /api/auth/callback/credentials (10 req/5min), répond 429 + Retry-After
- Ajout de tasks/todo.md et tasks/lessons.md (suivi CLAUDE.md)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 21:30:38 +04:00