DMV — Audit Readiness V1
Date : 2026-06-07
Auditeur : Analyse statique du code (Claude Code)
Périmètre : dmv-public, dmv-workspace, api Laravel, dmv-docs
1. Résumé exécutif
L'écosystème DMV est techniquement solide dans son architecture : API Laravel bien structurée en modules, deux Next.js distincts (public statique + workspace SPA), séparation Supabase anon / Sanctum token bien maîtrisée, design system cohérent.
La préoccupation principale pour le go-live est la sécurité : le workspace acteur ne vérifie pas côté client que l'utilisateur connecté est propriétaire de l'acteur dont il accède à l'espace. Cette vérification existe bien côté API Laravel (ActeurPolicy), mais le frontend n'empêche pas un utilisateur authentifié de naviguer librement dans l'interface de n'importe quel acteur, ce qui crée une expérience trompeuse et un potentiel de confusion.
Plusieurs modules sont partiels mais non bloquants pour un lancement pilote (paiement, stats avancées, mur contributeur). Le socle cœur (annuaire, fiches, auth, espace acteur, espace mairie) est fonctionnel.
Verdict préliminaire : No-Go strict, mais Go conditionnel si 3 points P0 sont corrigés.
2. Score global V1 (%)
| Domaine | Score estimé |
|---|---|
| Annuaire & fiches publiques | 90 % |
| Auth (inscription/connexion/reset) | 88 % |
| Espace acteur (workspace) | 80 % |
| Espace mairie (workspace) | 82 % |
| Mur de ville (home) | 75 % |
| Mon espace contributeur | 70 % |
| Favoris | 85 % |
| Stats | 65 % |
| Offres / tarifs | 70 % |
| Sécurité API | 85 % |
| Sécurité frontend | 55 % |
| Déploiement / infra | 80 % |
| Global | 76 % |
3. Tableau des modules
| Module | Statut | Remarque |
|---|---|---|
| Mur de ville (home) | Partiel | Flag feature_tabs conditionnel, OK fonctionnellement |
| Annuaire local | OK | Recherche, filtres, carte, tri coeff_annuaire, badges ouvert/fermé |
| Fiches acteurs (public) | OK | Logo, bannière, horaires, JSON-LD, bouton favori, revendiquer |
| Auth (connexion/inscription/reset) | OK | Magic link, password, OAuth Google/Facebook, reset complet |
| Mon espace contributeur | Partiel | Mur personnel feature-flaggé, favoris OK, profil OK |
| Espace acteur — tableau de bord | OK | Score complétude, publications récentes, accès rapides |
| Espace acteur — profil | OK | Logo, bannière, horaires, tags, documents, couleurs, SEO |
| Espace acteur — publications CRUD+AI | OK | Création, édition, suppression, assistant IA intégré |
| Espace acteur — stats | Partiel | Stats basiques OK, graphiques dans le temps absents |
| Espace acteur — avantages / boosts | OK | Boosts, défis, récompenses affichés et utilisables |
| Espace acteur — offre | OK | Lecture plan, limites, lien vers tarifs, "bientôt" pour paiement |
| Espace acteur — paramètres | Partiel | Déconnexion OK, membres/notifs/abonnement "à venir" |
| Espace mairie — vue d'ensemble | OK | Navigation 6 sections |
| Espace mairie — profil | OK | Visuels, identité, coordonnées, réseaux, horaires, thème |
| Espace mairie — élus | OK | CRUD élus complet |
| Espace mairie — collectes | OK | CRUD collectes |
| Espace mairie — infos pratiques | OK | CRUD infos |
| Espace mairie — publications | OK | CRUD + pagination |
| Espace mairie — services | OK | CRUD services |
| Favoris | OK | Toggle, liste avec dernière pub, état vide, unfollow |
| Mise en avant / sponsorisation | OK | en_avant + coeff_annuaire pris en compte |
| Tarifs / offres | Partiel | Affichage complet, paiement non ouvert (modal "bientôt") |
| API Laravel — Identity | OK | exchange, me, update, logout |
| API Laravel — Actor | OK | CRUD + tags + documents + XP + claims |
| API Laravel — Publication | OK | CRUD + types + report + moderate |
| API Laravel — Mairie | OK | Alertes, services, élus, collectes, infos, publications |
| API Laravel — AI | OK | generate, improve, variants, tags, quota |
| API Laravel — Analytics | OK | acteur, commune, global, push |
| API Laravel — Monetization | OK | plans, souscriptions, boosts, webhook Stripe |
| API Laravel — Admin | OK | Dashboard, users, acteurs, publications, claims, etc. |
| Déploiement CF Pages | Partiel | Worker OK, _redirects OK, env vars hardcodées workspace |
| Sécurité — accès non-propriétaire | Bloquant | Le workspace acteur n'a pas de gate côté client |
| Sécurité — clé DB dans .env.local | P1 | SUPABASE_DB_PASSWORD présent dans .env.local public |
| Charte — couleur violet | P1 | 4 occurrences de classes violet-* interdites |
4. Bugs P0 (bloquants go-live)
P0-1 — Absence de gate propriétaire dans le workspace acteur
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/acteur-layout-client.tsx (lignes 74-75)
Le layout récupère la liste userActeurs de l'utilisateur et trouve currentUserActeur, mais ne redirige jamais ni ne bloque si currentUserActeur est null (= l'utilisateur n'est pas propriétaire de cet acteur). N'importe quel utilisateur authentifié peut accéder à /mon-espace/acteur/[n'importe-quel-slug]/tableau-de-bord et voir l'interface de gestion de cet acteur.
La protection existe côté API (ActeurPolicy via $this->authorize('update', $acteur)), donc les modifications seront refusées avec 403. Mais l'interface s'affiche quand même, ce qui est une fuite d'information (nom, logo, publications, stats) et une expérience confuse.
Correction requise : après le Promise.all, si !currentUserActeur et que l'utilisateur n'est pas admin, afficher une page "Accès refusé" ou rediriger vers /connexion.
P0-2 — Env vars hardcodées dans next.config.ts (workspace)
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/next.config.ts (lignes 23-25)
env: {
NEXT_PUBLIC_SUPABASE_URL: "https://odgqttcbofqphwdikwnv.supabase.co",
NEXT_PUBLIC_SUPABASE_ANON_KEY: "sb_publishable_M6ghpkFdfNoahNONvWKbRA_qzYLF6Vx",
NEXT_PUBLIC_API_URL: "https://api.dansmonvillage.fr/api/v1",
},
Ces valeurs sont hardcodées dans le code source versionné. La clé anon Supabase est NEXT_PUBLIC_* donc publique par nature, mais la hardcoder dans git empêche toute rotation sans redéploiement et expose l'URL de l'instance Supabase. Pour la V1 pilote, le risque est faible puisque la clé anon est limitée par RLS, mais c'est une mauvaise pratique à corriger avant tout accès élargi.
Note : dmv-public utilise des variables d'environnement correctement via process.env.NEXT_PUBLIC_* sans les hardcoder dans next.config.mjs.
P0-3 — Absence de rate limiting sur les routes d'auth et de mutation critiques
Fichier : /Users/sylvain/dev/dmv/api/app/Modules/Actor/Routes/api.php
Le throttle throttle:10,1 n'est appliqué qu'à la route /acteurs/{id}/xp. Les routes critiques comme POST /publications (création), POST /claims (public), POST /acteurs (création) et les routes AI (POST /ai/publication/generate) n'ont pas de rate limiting spécifique. Le rate limit global de Laravel (api middleware) protège partiellement, mais il faut des quotas spécifiques par route sensible.
5. Bugs P1 (importants, correctibles rapidement)
P1-1 — Violations de charte : couleur violet interdite
Fichiers et lignes :
/Users/sylvain/dev/dmv/dmv-public/app/[commune]/acteur/[slug]/ActorsClient.tsx:436— badge catégorieborder-violet-200 bg-violet-50 text-violet-700/Users/sylvain/dev/dmv/dmv-public/app/components/MurVille.tsx:552— badge acteurbg-violet-500/15 text-violet-100/Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/profil/page.tsx:402— badge catégorieborder-violet-200 bg-violet-50 text-violet-700/Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/profil/page.tsx:1024— aperçu thèmeborder-violet-200 bg-violet-50 text-violet-700
La règle du design system (CLAUDE.md) interdit explicitement text-violet-*, bg-violet-*, border-violet-*. Ces badges catégorie devraient utiliser blue-100/blue-700 ou neutral.
P1-2 — SUPABASE_DB_PASSWORD dans .env.local
Fichier : /Users/sylvain/dev/dmv/dmv-public/.env.local (ligne 9)
SUPABASE_DB_PASSWORD=pYtpeg-cisni0-remxom
Ce fichier est exclu de git (.gitignore inclut .env*), donc pas de fuite dans le dépôt. Mais la présence d'un mot de passe de base de données dans un fichier d'environnement frontend est une mauvaise pratique : le frontend n'a jamais besoin d'accès direct à la base Postgres. À supprimer.
P1-3 — Page /mon-espace/acteur référencée mais chemin dépend de l'ancienne architecture
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/offre/page.tsx:164
href={`${PUBLIC_SITE}/mon-espace/tarifs?slug=${slug}`}
Et dans /Users/sylvain/dev/dmv/dmv-public/app/mon-espace/tarifs/page.tsx:227 :
const backUrl = slugParam ? `/mon-espace/acteur?slug=${slugParam}&tab=abonnement` : null;
Le lien de retour pointe vers /mon-espace/acteur?slug=…&tab=abonnement qui semble être une ancienne route de l'app public (dmv-public/app/mon-espace/acteur/) — à vérifier que cette page existe et fonctionne.
P1-4 — Worker CF : hostname hardcodé dmv-mon-espace.pages.dev
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/cloudflare/mon-espace-proxy-worker.js:13
const PAGES_HOSTNAME = "dmv-mon-espace.pages.dev";
Si le projet CF Pages est renommé, le Worker casse. À externaliser en variable d'environnement Worker (env.PAGES_HOSTNAME).
P1-5 — Absence de vérification propriétaire dans le workspace mairie
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/mairie/[slug]/layout.tsx et mairie-guard.tsx
Même problème structurel que P0-1 pour le workspace acteur : si le garde mairie ne vérifie pas que l'utilisateur est commune.manager pour la commune en question, un utilisateur mairie d'une commune A pourrait voir l'interface de la commune B. À vérifier dans mairie-guard.tsx.
P1-6 — Paramètres acteur : fonctionnalités affichées "à venir" sans alternatives
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/parametres/page.tsx (lignes 46-63)
La page affiche "Membres", "Notifications", "Abonnement" comme badges "À venir" sans aucune fonctionnalité active hors la déconnexion. Pour V1, c'est acceptable mais peu engageant.
P1-7 — Publication modal : sélection type par nom fragile
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/components/acteur/publications/publication-modal.tsx:85
setKind(publication?.type?.nom === "evenement" ? "evenement" : "actualite");
La logique de détection du type de publication repose sur la comparaison du nom textuel ("evenement", "actualite"). Si ces noms changent en base, le comportement casse silencieusement. Utiliser un type_id ou un champ code stable serait plus robuste.
6. Bugs P2 (mineurs, hors scope V1)
P2-1 — AnnuaireClient : setLoading(false) manquant sur le chemin noSearch
Fichier : /Users/sylvain/dev/dmv/dmv-public/app/[commune]/AnnuaireClient.tsx (lignes 240-247)
if (noSearch) {
if (myReqId !== reqIdRef.current) return;
const filtered = ...;
setItems(filtered);
setLoading(false); // ← présent, OK
return;
}
En relisant : setLoading(false) est bien appelé. Pas de bug ici.
P2-2 — Stats page : graphiques d'évolution absents
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/stats/page.tsx (lignes 148-155)
Un encart avec TrendingUp annonce explicitement que les graphiques d'évolution arrivent dans "une prochaine version". Acceptable pour V1 pilote, mais à noter pour les utilisateurs.
P2-3 — Seeders très limités
Fichier : /Users/sylvain/dev/dmv/api/database/seeders/DatabaseSeeder.php
Seuls BoostCatalogSeeder et RewardRuleSeeder sont appelés, plus un User::factory test. Pas de seed pour :
- Communes de test
- Acteurs de démonstration
- Types de publications
- Plans d'abonnement (
subscription_plans— pourtant lus depuis Supabase)
Les données de test dépendent intégralement de Supabase, ce qui rend les tests Laravel sans Supabase impossibles.
P2-4 — Type ActeurKind incohérent entre frontend et DB
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/types/index.ts (lignes 104-109)
export type ActeurKind = "association" | "commerce" | "artisan" | "service" | "mairie";
Mais la DB et le code utilisent "pro" | "association" | "public" (visible dans AnnuaireClient.tsx:33, [commune]/page.tsx:18). Ce type ActeurKind dans types/index.ts est obsolète et n'est pas utilisé pour Acteur.kind (qui est string). Risque de confusion pour les futurs contributeurs.
P2-5 — indigo utilisé dans mon-espace/page.tsx (onboarding)
Fichier : /Users/sylvain/dev/dmv/dmv-public/app/mon-espace/page.tsx (lignes 654, 659)
className="... bg-indigo-600 ... hover:bg-indigo-500"
La charte autorise blue/neutral/amber/red/green. L'indigo dans le bouton "Créer mon espace" n'est pas dans la palette officielle, mais c'est un écran d'onboarding rarement vu.
P2-6 — dynamicParams = false dans [slug]/layout.tsx du workspace
Fichier : /Users/sylvain/dev/dmv/dmv-workspace/app/(workspace)/acteur/[slug]/layout.tsx (lignes 3-6)
export function generateStaticParams() {
return [{ slug: "_" }];
}
export const dynamicParams = false;
Avec dynamicParams = false, seul le slug _ est pré-rendu statiquement. Tout autre slug retourne 404 en production unless la _redirects redirige vers _. La règle _redirects :
/acteur/:slug/* /acteur/_/:splat 200
gère cela correctement. Cohérent mais subtil — si la règle _redirects échoue pour une raison quelconque, toutes les pages acteur retournent 404.
7. Fonctionnalités V1 prêtes
- Annuaire local : liste d'acteurs avec recherche full-text (RPC
search_acteurs_public), filtres par type, tri sponsorisé (coeff_annuaire), badge ouvert/fermé, carte Leaflet avec pins, pagination, "Je ne trouve pas mon activité", bouton "Revendiquer" - Fiches acteurs publiques : logo, bannière, horaires, description, coordonnées, publications, bouton favori (authentifié), bouton revendiquer, JSON-LD Schema.org complet (LocalBusiness / NGO / GovernmentOrganization)
- Authentification : magic link, mot de passe, Google OAuth, Facebook OAuth, inscription avec confirmation email, forgot password, reset password (flux PASSWORD_RECOVERY Supabase complet)
- Mon espace contributeur : profil, favoris avec dernière publication, liste des acteurs gérés, mur feature-flaggé
- Tableau de bord acteur : score de complétude de fiche, publications récentes, avantages disponibles
- Édition profil acteur : logo upload, bannière upload, informations, SEO text, horaires multi-créneaux avec copie semaine/tous, tags avec drag&drop, documents (quota/upload XHR progressif), couleurs de thème (plan supérieur)
- Publications acteur CRUD : création avec assistant IA (generate/improve/variants), édition, suppression, types actualité/événement
- Stats acteur : vues, clics, partages, top sources, top devices (mois courant)
- Avantages acteur : boosts disponibles, utilisation (featured_actor, featured_publication), défis, récompenses récentes
- Offre acteur : lecture plan courant, fonctionnalités incluses, lien vers tarifs
- Espace mairie : profil (6 composants), publications CRUD, élus CRUD, collectes CRUD, infos pratiques CRUD, services CRUD
- Page tarifs : affichage plans depuis DB, toggle mensuel/annuel, promos, FAQ — paiement "bientôt disponible" (modal transparente)
- API Laravel : 15 modules fonctionnels, routes protégées Sanctum + Policy, X-App-Source enforced, middleware admin, webhook Stripe structuré
- Déploiement : Worker CF proxy
/mon-espace/*,_redirectsacteur et mairie, static export Next.js, font Ubuntu auto-hébergée
8. Fonctionnalités V1 incomplètes
| Feature | Manque |
|---|---|
| Workspace acteur — gate propriétaire | Pas de redirect si non-owner côté frontend |
| Stats acteur — graphiques temporels | Encart placeholder "prochaine version" |
| Paramètres acteur — membres/notifs | Interface "à venir" uniquement |
| Mur de ville (home) | Conditionnel feature_tabs — désactivé par défaut |
| Mur contributeur personnel | Feature-flaggé get_mur_contributeur_enabled |
| Publications workspace — image upload | À vérifier : l'upload image dans la modal publication workspace n'a pas été audité en détail |
| Paiement abonnements | Non ouvert (ComingSoonModal), Stripe structuré mais pas de flow client |
9. Fonctionnalités hors scope V1 (bonus/partiel)
- Achat de boosts : bouton "Acheter des boosts — bientôt disponible" (
avantages/page.tsx:306) - Double publication Facebook : champ présent dans les plans, implémentation absente
- Support prioritaire : feature plan sans implémentation
- RBAC contextuel : NEXT_STEPS.md décrit un futur système de rôles granulaires
- Versionnement API
/api/v1/: NEXT_STEPS.md note que le préfixev1n'est pas encore appliqué - Graphiques d'évolution stats : placeholder explicite
- AssoSuite / PlayLoop / Chat : modules API présents mais frontend non audité
- Module Community : présent dans l'API mais non branché au frontend
10. Risques sécurité
🔴 CRITIQUE — Absence de gate propriétaire frontend (workspace acteur)
Impact : Un utilisateur authentifié A peut naviguer sur /mon-espace/acteur/acteur-de-B/tableau-de-bord et voir le tableau de bord, les publications, les stats et les informations privées de B. Les mutations sont protégées par l'API (ActeurPolicy) mais les lectures Supabase dans le workspace profil page (ligne 179) utilisent directement le client Supabase sans filtrer sur user_acteurs. Un utilisateur malveillant peut lire les données d'un acteur dont il n'est pas propriétaire via le client Supabase.
Spécifiquement : profil/page.tsx:179 fait un supabase.from("acteurs").select(...) sans vérifier user_acteurs. La RLS Supabase est la dernière ligne de défense — si la RLS permet à tout utilisateur authentifié de lire tous les acteurs, alors les données sont lisibles.
🟡 MOYEN — Clés Supabase anon hardcodées dans next.config.ts
Niveau de risque réel : faible (c'est une clé publique), mais mauvaise pratique.
🟡 MOYEN — Pas de rate limiting sur routes critiques
Routes sans throttle : POST /claims (public), POST /publications (auth), POST /ai/publication/generate (auth). Un acteur malveillant authentifié pourrait spammer l'endpoint AI et générer des coûts.
🟡 MOYEN — SUPABASE_DB_PASSWORD dans .env.local frontend
Non commis (.gitignore), mais présence inexpliquée. Un frontend Next.js n'a jamais besoin d'accéder à la DB Postgres directement.
🟢 OK — Pas de service_role dans le frontend
Aucune occurrence de service_role dans les fichiers audités frontend. Bon signe.
🟢 OK — Sanctum token exchange
Le flux Supabase JWT → Sanctum token est correct : le frontend échange le JWT Supabase contre un token Sanctum via /auth/exchange, qui est ensuite utilisé pour toutes les mutations API. Le token est mis en cache en sessionStorage avec expiration.
🟢 OK — ActeurPolicy et PublicationPolicy
Les policies Laravel vérifient correctement la propriété via user_acteurs (acteurs) et l'auteur (publications). $this->authorize() est appelé sur les routes d'écriture.
🟢 OK — Admin middleware
EnsureUserIsAdmin vérifie users_roles.role = 'admin' avant tout accès /api/admin/*. Double vérification auth + rôle.
⚠️ ATTENTION — CORS Sanctum non configuré pour production
config/sanctum.php ne liste que localhost dans stateful. Pour un usage token-based (Sanctum Bearer), cela n'est pas bloquant, mais à documenter.
11. Risques UX
Charte couleur violée (4 occurrences)
Les classes violet-* apparaissent dans 4 endroits clés (badge catégorie, aperçu thème). Ces badges violets sont visibles par les utilisateurs finaux sur les fiches acteurs publiques et dans le workspace. Impact visuel modéré.
Espace acteur : accès sans ownership affiché
Un utilisateur non propriétaire qui arrive sur un espace acteur verra un tableau de bord complet sans message d'erreur clair. Les actions échoueront silencieusement (403 API) — expérience confuse.
Mur de ville désactivé par défaut
La page d'accueil (/) redirige vers HomeHero si feature_tabs.mur-ville est false. Les nouveaux utilisateurs verront une page d'accueil sans contenu dynamique. À documenter comme choix de déploiement progressif.
Mur contributeur non accessible par défaut
Le mur personnel du contributeur est contrôlé par get_mur_contributeur_enabled — si à false, l'utilisateur voit "Fonctionnalité bientôt disponible". La valeur par défaut de cette RPC n'a pas été auditée.
Paramètres acteur très vide
La page paramètres ne contient que l'email affiché et un bouton déconnexion. Pour un lancement V1, l'utilisateur s'attendrait à plus.
Modal "bientôt disponible" pour les plans payants
Chaque clic sur "Choisir [plan]" ouvre une modal expliquant que le paiement n'est pas encore ouvert. C'est honnête mais peut décevoir lors d'un demo ou lancement.
12. Risques déploiement
Worker CF hostname hardcodé
/Users/sylvain/dev/dmv/dmv-workspace/cloudflare/mon-espace-proxy-worker.js:13 — PAGES_HOSTNAME = "dmv-mon-espace.pages.dev" est hardcodé. Si le projet CF Pages est renommé ou migré, le proxy casse sans modification du Worker.
dynamicParams = false + _redirects dépendance critique
Le workspace Next.js ne génère statiquement que slug = "_". Toute la mécanique de routing dynamique repose sur la règle _redirects :
/acteur/:slug/* /acteur/_/:splat 200
Si cette règle n'est pas correctement appliquée en production CF Pages, toutes les pages acteur retournent 404.
dmv-public sans env vars dans next.config
dmv-public/next.config.mjs ne contient pas d'env vars hardcodées — elles doivent être définies dans CF Pages (settings Build). Le NEXT_PUBLIC_SUPABASE_* doit être configuré côté CF Pages. Si oublié, le site public ne charge aucun acteur.
API sans préfixe /v1/ officiel
NEXT_STEPS.md note que le préfixe /v1/ n'est pas encore appliqué uniformément via le routage Laravel. Le frontend pointe sur https://api.dansmonvillage.fr/api/v1 — si le routage Laravel n'expose pas correctement ce préfixe, toutes les requêtes échouent.
Stripe webhook URL
NEXT_STEPS.md mentionne que la route webhook Stripe est maintenant /api/v1/webhooks/stripe et doit être mise à jour dans le dashboard Stripe avant les tests paiement.
13. Données de test manquantes
| Donnée | Statut | Impact |
|---|---|---|
| Communes de test | Manquante (seeder) | Tests Laravel isolés impossibles |
| Acteurs de démonstration | Manquante (seeder) | Demo uniquement via Supabase prod/staging |
| Types de publications | Manquante (seeder) | Dépend de Supabase |
| Plans d'abonnement | Manquante (seeder) | subscription_plans lus depuis Supabase directement |
| Boost catalog | Présent (BoostCatalogSeeder) | OK |
| Règles de récompense | Présent (RewardRuleSeeder) | OK |
| Utilisateur admin de test | Présent (test@example.com) | Limité |
| Acteurs revendiqués | Manquante | Test du claim impossible en CI |
Conséquence : l'intégralité des tests manuels dépend des données Supabase (prod ou staging). Il n'y a pas de jeu de données reproductible pour les tests Laravel.
14. Plan d'action priorisé
Sprint immédiat (avant go-live)
- [P0-1] Ajouter dans
acteur-layout-client.tsx: si!currentUserActeuraprès chargement, afficher "Accès non autorisé" ou rediriger vers/connexion(10 lignes de code) - [P0-1 bis] Vérifier
mairie-guard.tsxpour le même pattern côté mairie - [P1-1] Remplacer les 4 classes
violet-*parblue-*dans ActorsClient.tsx, MurVille.tsx, profil/page.tsx - [P0-2] Sortir les clés Supabase de
next.config.tsworkspace — les passer via variables d'env CF Pages (ou au minimum via.env.localnon commis) - [P1-2] Supprimer
SUPABASE_DB_PASSWORDde.env.localdmv-public - [P0-3] Ajouter
throttle:60,1surPOST /ai/publication/generateetPOST /claims
Sprint court terme (post-lancement)
- [P1-4] Externaliser
PAGES_HOSTNAMEdans les variables Worker CF - [P1-3] Vérifier la route
/mon-espace/acteur?slug=…&tab=abonnementdans dmv-public - [P2-4] Corriger le type
ActeurKinddanstypes/index.ts - Ajouter des seeders communes + acteurs de test pour CI
Moyen terme (V1.1)
- Graphiques d'évolution stats
- Paramètres acteur : gestion membres, notifications
- Paiement abonnements (flow Stripe)
- Versionnement API
/api/v1/unifié - RBAC contextuel (municipal_manager, moderator)
15. Verdict : Go / No-Go V1
NO-GO strict — GO conditionnel après 3 corrections
Le code est de bonne facture et l'architecture est solide. Mais 3 corrections sont nécessaires avant tout accès réel d'utilisateurs :
- Gate propriétaire workspace acteur (P0-1) — risque de fuite de données et d'expérience brisée
- Env vars sorties du code versionné (P0-2) — bonne pratique minimale
- Rate limiting routes AI et claims (P0-3) — protection contre abus et coûts imprévus
Si ces 3 points sont corrigés, le reste de l'écosystème est prêt pour un lancement pilote (une commune, une poignée d'acteurs) avec les limitations connues et documentées (paiement désactivé, stats sans graphiques, paramètres acteur minimalistes, mur contributeur feature-flaggé).
Le score de 76 % reflète un produit solide pour une V1 pilote, pas un produit finalisé. Les lacunes sont connues, documentées (NEXT_STEPS.md, badges "à venir"), et non bloquantes pour l'usage cœur de l'annuaire et de l'espace acteur.
Audit réalisé par analyse statique du code — 2026-06-07
Fichiers couverts : ~35 fichiers TSX/PHP/JS lus intégralement + ~20 grepped