# Backend ChoralSync — Strapi > Racine du repo backend. Vue d'ensemble front + back : `../CLAUDE.md`. ## Stack - Strapi **5.8.1** (⚠️ API v5 : `documentId`, réponses aplaties — pas de `attributes` imbriqués comme en v4) - Node **18 à 22** (`engines` du package.json ; v22 utilisée en dev) — gestionnaire : **yarn** - TypeScript - Base de données : sélectionnée par `DATABASE_CLIENT` — **SQLite** par défaut en dev (better-sqlite3), **PostgreSQL** ou MySQL supportés (voir `config/database.ts`) - Plugins actifs : - Users & Permissions (rôles `Public`, `Authenticated`) - Documentation (`@strapi/plugin-documentation`) - Email : nodemailer via **ZeptoMail** (SMTP) - Upload : **aws-s3** vers **Cloudflare R2** (bucket `choralsync`, servi par `container.choralsync.com`) - `strapi-v5-plugin-populate-deep` (defaultDepth 3) - Autres : Stripe (paiements, content-type `order`), Puppeteer (génération), cron jobs dans `config/cron-tasks.ts` (ex. récupération d'actualités GNews), templates d'emails dans `src/email-templates/` ## Structure ``` src/ ├── api/ # 34 content-types (un dossier chacun) │ └── / │ ├── content-types//schema.json │ ├── controllers/ │ ├── routes/ │ └── services/ ├── components/ # composants Strapi partagés ├── email-templates/ # templates des emails transactionnels ├── extensions/ # overrides : documentation, upload, users-permissions └── admin/ # customisation admin config/ # server, database, plugins, middlewares, cron-tasks, api ``` ## Content-types Vue par domaine (34 au total, liste exhaustive dans `src/api/`) : | Domaine | Content-types | |---|---| | Chorale | `choral`, `choral-membership`, `choral-permission`, `permissions-template` | | Social (offre gratuite) | `post`, `post-ownership`, `comment`, `activity`, `report` | | Groupes | `group`, `group-membership` | | Événements | `event`, `event-relationship` | | Boards (kanban) | `board`, `board-list`, `board-card` | | Messagerie | `channel`, `chat-conversation`, `chat-conversation-member`, `chat-message`, `conversation`, `direct-message`, `message` | | Notifications | `notification`, `announcement`, `invite` | | Paiement | `order` (Stripe — ⚠️ route custom `auth: false` dans `src/api/order/routes/order.ts`, webhook) | | Contenu / divers | `page`, `legal-page`, `ad`, `contact`, `contact-meta`, `form-template`, `mails` | ## Sécurité — règles NON NÉGOCIABLES - Aucune route custom en `auth: false` sans justification écrite en commentaire ET mention dans le CLAUDE.md parent. État actuel : 1 occurrence (`src/api/order/routes/order.ts` — webhook Stripe). - Tout controller custom qui lit/écrit des données utilisateur DOIT filtrer par `ctx.state.user.id`. Jamais de `entityService.findMany` sans filtre dans un contexte authentifié multi-utilisateurs. - Toujours utiliser `sanitizeOutput` / les sanitizers Strapi avant de retourner une entité depuis un controller custom (ne jamais renvoyer l'objet brut). - `populate=*` interdit côté serveur comme côté client : populate explicite. ⚠️ Le plugin populate-deep (defaultDepth 3) est installé — ne pas en abuser, il peut exposer des relations non prévues. - Les permissions du plugin Users & Permissions sont versionnées dans **`src/permissions-sync.ts`** (source de vérité) et synchronisées au démarrage par le bootstrap (`src/index.ts`) — synchro ADDITIVE et idempotente : les manquantes sont créées, les permissions en trop sont seulement loguées (`[permissions-sync]`), jamais supprimées automatiquement. Toute nouvelle route/action consommée par le front DOIT être ajoutée à ce fichier (et jamais cochée uniquement dans l'admin, sinon elle sera signalée comme non déclarée). - Secrets uniquement en variables d'environnement. `.env` jamais commité ; `.env.example` maintenu à jour. ⚠️ **DETTE CRITIQUE : `config/plugins.ts` contient des secrets en dur** (clé API SMTP ZeptoMail, access/secret keys Cloudflare R2). À migrer vers `env()` et à faire tourner (rotation des clés). ## Points d'audit récurrents Checklist à dérouler lors d'une revue sécurité : 1. `grep -rn "auth: false" src/` — chaque occurrence doit être justifiée. 2. Rôle Public dans l'export des permissions : uniquement les find/findOne réellement nécessaires au site public. 3. Controllers custom : filtrage par user, sanitization, gestion d'erreurs (pas de stack trace renvoyée au client). 4. Lifecycles (`lifecycles.ts`) : pas de logique qui bypasse les permissions. 5. Champs privés : vérifier `"private": true` dans les schema.json pour les champs sensibles (ils sont sinon exposés dans les réponses API). 6. Rate limiting / CORS dans `config/middlewares.ts` : origines explicites en prod. 7. API tokens : scope minimal, pas de token full-access utilisé par le front. 8. Webhook Stripe (`order`) : vérification de la signature (`stripe.webhooks.constructEvent`). ## Commandes ```bash yarn develop # dev + admin (strapi develop --debug) yarn build yarn strapi config:dump -f config/sync/permissions.json # export permissions yarn strapi config:restore -f config/sync/permissions.json # import permissions ``` ## Règles pour Claude - Toute modification de schema.json = migration implicite : signaler l'impact (données existantes, types front à mettre à jour dans `harmony-web/types/` et `harmony-web/interfaces/`). - Après modification d'une route/permission : mettre à jour le tableau des content-types ici ET dans le CLAUDE.md parent. - Ne jamais modifier directement la base de données. - Strapi **5** : utiliser les `documentId` et le format de réponse v5 (pas de `attributes` imbriqués). Toujours vérifier package.json en cas de doute.