RECOVMAX
RECOVMAX  ›  DPA  ›  Audit sécurité
Document de transparence · v1 · 9 mai 2026

Audit sécurité RECOVMAX

État détaillé de la sécurité technique et juridique de la suite RECOV / RECOVMAX. Document destiné aux DPO, responsables sécurité, dirigeants de cabinets qui veulent comprendre ce qui est en place avant d'utiliser le service. Ce document est public et imprimable en PDF (Ctrl + P) pour archivage.

Solide
18
contrôles en place
À améliorer
8
priorités P1-P2
Gaps critiques
4
à 250+ utilisateurs
Score global
A−
solide pour pilote 30 fondateurs
Verdict en une phrase : RECOVMAX est solidement sécurisé pour le pilote 30 fondateurs. Les fondations (RLS multi-tenant, headers HTTP, hébergement UE, RGPD, signature webhooks) sont au niveau attendu d'un SaaS B2B sérieux. Les 8 améliorations identifiées sont planifiées en P1-P2. Les 4 gaps critiques (DPO formel, audit juridique externe, runbook incidents, retention auto) deviennent recommandés au-delà de 250 utilisateurs.

Architecture & isolation des données

ContrôleStatutDétail
RLS PostgreSQL multi-tenant ✓ En place Toutes les tables métier (creances, clients, debiteurs, dossier_events, promesses_paiement, echeanciers, templates) appliquent auth.uid() = user_id. Un cabinet ne peut techniquement pas voir les données d'un autre — la base elle-même refuse.
RLS read-only enforcement ✓ En place Migration 031 (mai 2026) : helper is_user_writable() bloque INSERT/UPDATE/DELETE quand subscription_status ∉ (active, grace). Les comptes archived/purged ne peuvent que lire.
RLS plan enforcement ✓ En place Migration 032 : quotas (50 clients, 50 créances, 1 000 relances) appliqués au niveau base, pas seulement applicatif.
Service-role isolé serverless ✓ En place La clé SUPABASE_SERVICE_ROLE_KEY n'apparaît jamais côté client. Uniquement utilisée dans les fonctions Vercel serverless (admin.js, webhook.js, generate.js).
Migrations versionnées ✓ En place 43 migrations SQL versionnées dans Git, idempotentes (DROP IF EXISTS, CREATE OR REPLACE, ALTER...IF NOT EXISTS).
Backups automatisés ⚠ À tester Cron weekly /api/backup?action=cron_weekly dans vercel.json. Test de restauration jamais effectué — à faire avant lancement officiel.

Headers HTTP & durcissement web

HeaderStatutValeur appliquée
Strict-Transport-Security (HSTS) max-age=63072000; includeSubDomains; preload (2 ans, sous-domaines, preload list)
X-Frame-Options DENY — pas d'embed possible (anti-clickjacking)
X-Content-Type-Options nosniff — anti-MIME sniffing
Content-Security-Policy Whitelist stricte : self + cdn.jsdelivr.net + cdnjs + unpkg + js.stripe + supabase + plausible. frame-src https://js.stripe.com uniquement. connect-src limité aux domaines explicites.
Referrer-Policy strict-origin-when-cross-origin — pas de leak de chemins lors de navigation externe
Permissions-Policy camera=(), geolocation=(), interest-cohort=() — APIs sensibles désactivées + opt-out FLoC
X-Robots-Tag (pages sensibles) noindex, nofollow, noarchive, nosnippet sur /admin, /recovmax-dashboard, /partner-report
Cache-Control (pages auth) private, no-store, no-cache, must-revalidate, max-age=0 — pas de cache sur les pages connectées
Cross-Origin-Opener-Policy ⚠ Non configuré À ajouter en P1 pour isolation totale du contexte de navigation (SAB / process isolation)
CSP 'unsafe-inline' ⚠ Présent Nécessaire actuellement pour les inline-styles HTML. Mitigation : tous les innerHTML avec données user passent par esc() qui échappe & < > ". Refactor vers nonces possible mais lourd (5+ jours).

Authentification & sessions

ContrôleStatutDétail
Supabase Auth (PostgreSQL backed) ✓ En place Email + mot de passe, magic links, OAuth Google. JWT signés HS256. Tokens d'accès en session storage, refresh tokens en cookie httpOnly côté Supabase.
Hash des mots de passe ✓ En place bcrypt côté Supabase (workfactor 10). Aucun mot de passe en clair côté DEZVOLTA.
Rate limiting login ⚠ Backend Supabase uniquement Pas de rate limit applicatif persistant côté Vercel (cold start reset toutes les 5 min). Supabase a son propre rate limit backend (5 tentatives / 5 min / IP). À renforcer en P1 avec Upstash Redis (gratuit jusqu'à 10k requêtes/jour).
Honeypot anti-bot signup ✓ En place Champ caché gateWebsite dans le formulaire d'inscription, rempli par les bots, vérifié côté serveur.
2FA (TOTP) À faire P1 Supabase Auth supporte TOTP nativement. Sprint estimé : 2-3 jours. Recommandé avant 100 utilisateurs payants.
CAPTCHA login À faire P1 Cloudflare Turnstile ou hCaptcha. Sprint estimé : 1 jour. Mitigation actuelle : rate limit Supabase backend.
Tokens API admin ✓ En place ADMIN_TOKEN (HMAC bearer) pour les endpoints sensibles. Secret stocké en env Vercel, jamais en code.

XSS, CSRF, injection

VecteurStatutMitigation
XSS — escape HTML user-controlled ✓ En place Fonction esc() utilisée 129× dans le dashboard pour échapper & < > " sur toute donnée provenant de la base. Pattern systématique : ${esc(variable)}.
SQL injection ✓ Couvert Requêtes via Supabase JS SDK (paramétrées) ou via supabaseQuery() côté serverless. Aucune concaténation SQL côté code applicatif. RPCs côté Postgres en SECURITY DEFINER avec params typés.
CSRF dashboard ✓ Couvert Authentification par JWT en header Authorization: Bearer (pas de cookie session) → CSRF par formulaire impossible. SameSite cookies sur Supabase Auth.
CSRF webhooks Stripe ✓ Couvert Signature HMAC SHA-256 vérifiée sur chaque event via STRIPE_WEBHOOK_SECRET. Rejet immédiat si signature invalide.
CSRF webhooks partenaires ✓ Couvert HMAC mutuelle via partner.webhook_secret. Header X-Recov-Signature sur les réponses sortantes.
Open redirect ✓ Couvert Tous les redirects (login, magic link, Stripe checkout) utilisent des URLs hardcodées vers le domaine recov.pro. Aucun paramètre user-controlled dans les redirects.

Données personnelles & RGPD

Exigence RGPDStatutDétail
Hébergement Union européenne ✓ Conforme Supabase région eu-central-1 (Frankfurt). Vercel UE pour les fonctions sensibles. Cloudflare CDN POP UE.
Transferts hors UE encadrés ✓ Conforme Anthropic (USA, API Claude) : Clauses Contractuelles Types Commission UE 2021/914 + Zero Data Retention. Stripe Irlande (UE). Cloudflare : POPs UE forcés.
Liste publique des sous-traitants (art. 28-2) ✓ Conforme Page recov.pro/sous-traitants mise à jour à chaque ajout/retrait. Préavis 15 jours pour droit d'opposition.
DPA spécifique RECOVMAX ✓ Conforme 15 articles couvrant la sous-traitance à 3 niveaux (RECOV → Cabinet → Client TPE). Voir DPA RECOVMAX.
Mandat de gestion fourni ✓ Conforme Template PDF généré par RECOVMAX (7 articles, références L441-10 + DGCCRF). Le cabinet doit le signer avec chacun de ses clients TPE avant traitement.
Droits des personnes (art. 15-22) ✓ Conforme Accès, rectification, effacement, portabilité, limitation, opposition. Procédure : pedro.berbel@dezvolta.org. Délai 30 jours.
Pseudonymisation analytics ✓ Conforme PostHog : userId hashé, IP anonymisée, blacklist explicite (email, nom, SIRET). Aucune PII transmise.
Retention policy automatisée À faire P2 Pas de purge auto après inactivité. Recommandé : 3 ans après dernière connexion. Sprint estimé : 1 jour (cron).
DPO désigné Non requis Pas obligatoire en l'état (volume < 250 users, pas de données sensibles RGPD strict art. 9). Recommandé au-delà de 250 utilisateurs ou en cas de saisine CNIL. Budget : 50-150 €/mois externalisé.
Procédure incident (notification 72h) À faire P2 Pas de runbook formel pour notification CNIL en cas de violation. À documenter (modèle CNIL fourni).

Paiements & facturation

PCI DSS ✓ N/A direct Aucune donnée carte ne transite chez DEZVOLTA. Stripe Payments Europe Ltd (Irlande, PCI DSS Level 1) gère intégralement la collecte et le stockage des moyens de paiement.
Webhook Stripe — signature HMAC SHA-256 vérifié via STRIPE_WEBHOOK_SECRET (env Vercel). Rejet immédiat si invalide. Idempotence sur stripe_payment_id.
Customer Portal (annulation, MAJ CB) Géré 100% par Stripe (UI hosted). DEZVOLTA n'a jamais accès aux données carte.
Mode TEST séparé du LIVE Environnements isolés. Bascule LIVE = changement de variables d'env Vercel uniquement, pas de code.

Monitoring actif en production

Au-delà des contrôles statiques (architecture, headers), un middleware Vercel Edge tourne en permanence devant chaque requête. Il bloque les scrapers, AI bots non autorisés et outils offensifs avant même qu'ils n'atteignent l'application.

Couverture
Edge runtime
Latence ~ 0 ms · zero cold start
Modèles bloqués
30+
User-Agents + IPs + comportements
Crawlers légitimes
~ 15
Whitelist Google, Bing, LinkedIn, Apple…
Dashboard live
interne
Admin SOC · accès restreint
Catégorie bloquéeExemplesJustification
Scrapers Python génériques scrapy, python-httpx, python-requests Aucun usage légitime sur un SaaS — uniquement des scripts d'extraction massive de contenu.
AI scrapers non autorisés gptbot, ccbot, perplexitybot, cohere-ai Ces bots utilisent le contenu pour entraîner des modèles concurrents sans contrepartie. Anthropic (notre sous-traitant IA) est exempté car couvert par DPA.
SEO crawlers agressifs semrushbot, ahrefsbot, mj12bot, bytespider Crawl à haute fréquence sans valeur ajoutée pour les utilisateurs. Ralentissent l'application.
Outils offensifs nikto, nmap, nuclei, zgrab, masscan Outils de pentest publics — leur présence indique une tentative active de cartographie ou exploitation.
Crawlers SEO secondaires dotbot, petalbot, blexbot, seokicks Sources de bruit sans valeur pour les utilisateurs. Bloqués pour préserver les ressources Edge.

Ce qui est observé en production (extrait anonymisé)

Statistiques sur 7 jours — accessibles en temps réel dans le dashboard admin interne :

MétriqueValeur observée 7jLecture
Requêtes bloquées~ 200Tentatives de scraping rejetées avant traitement
Crawlers légitimes autorisés~ 400Google, LinkedIn, Apple : indexation normale
Top scraper bloquégptbotOpenAI tente régulièrement — toujours rejeté
Pays de provenance des scrapersUS, BR, NL, PT, CN, TH, ID, TR, GB, BEProfil mondial typique des pools de proxies
Vecteurs distincts détectés8 typesUA pattern, IP pattern, comportement anormal
Whitelist explicite — les bots légitimes (Googlebot, Bingbot, LinkedInBot, AppleBot, FacebookBot, TwitterBot, DuckDuckBot, Slackbot, WhatsApp, Telegram, Discord) sont autorisés explicitement. Le SEO et le partage social fonctionnent normalement.
Pas de blocage géographique massif — RECOVMAX cible le marché français mais l'application reste accessible depuis l'étranger. Un cabinet français peut avoir un client à l'étranger ou un dirigeant en déplacement. Le blocage géographique serait disproportionné.

Secrets & gestion des clés

Variables d'environnement Vercel Tous les secrets stockés en env vars Vercel (chiffrement at-rest). Aucun secret en code (vérifié par grep + secrets scanning GitHub Push Protection).
Rotation des secrets ⚠ Manuelle Pas de rotation automatique. Procédure manuelle documentée. À industrialiser en P2 (rotation tous les 6 mois recommandée).
Anon key Supabase publique L'anon key est par design publique. Sécurité reposant intégralement sur les policies RLS. Service-role key strictement serverless.

Roadmap sécurité 2026-2027

Priorisation transparente — voici ce qui est prévu et quand. Si un point est critique pour vous, contactez-nous : nous pouvons accélérer pour un client cabinet majeur.
SprintActionBénéfice
P1 · Q3 20262FA TOTP optionnelleProtège contre les comptes compromis (mot de passe leaké)
P1 · Q3 2026CAPTCHA login (Turnstile)Anti brute-force applicatif persistant
P1 · Q3 2026Rate limit persistant (Upstash Redis)Remplace le rate limit in-memory Vercel
P2 · Q4 2026Headers COOP/COEPIsolation totale du contexte navigation
P2 · Q4 2026Audit log applicatif admin (table immutable)Traçabilité juridique des actions admin
P2 · Q4 2026Test restauration backupValidation effective de la stratégie DRP
P2 · Q4 2026Retention auto (purge 3 ans)Conformité RGPD art. 5-1-e
P2 · Q4 2026Runbook incident + notification CNILProcédure documentée 72h
P3 · Q1 2027Pentest externe (1 500-3 000 €)Audit indépendant tiers
P3 · Q1 2027Audit juridique CGU/DPA externe (800-1 500 €)Validation par avocat tech-RGPD
P3 · Q2 2027DPO externalisé si > 250 usersConformité art. 37 RGPD si volume / sensibilité

Pour aller plus loin

DPA RECOVMAX → Accord de traitement de données · 15 articles · sous-traitance à 3 niveaux Sous-traitants RGPD → Liste publique exhaustive · art. 28-2 RGPD · mise à jour continue CGU RECOVMAX → Conditions générales d'utilisation · 14 articles
Une question, une demande spécifique ?

Contactez directement le fondateur : pedro.berbel@dezvolta.org.
Pour les sujets RGPD : pedro.berbel@dezvolta.org.

Si vous êtes responsable sécurité d'un cabinet ou d'une entreprise et avez besoin d'un complément (audit indépendant, certification, contrat sur mesure), nous pouvons en discuter en visio.

Accessibilité — déclaration partielle

DEZVOLTA s'engage à rendre la suite RECOV / RECOVMAX accessible au plus grand nombre. L'audit professionnel WCAG 2.1 AA / RGAA 4.1 n'a pas encore été réalisé — nous publions ici une auto-déclaration partielle honnête, mise à jour au fil des améliorations.

Date de la déclaration : 9 mai 2026. Méthode : auto-évaluation interne (sans audit externe). Un audit professionnel sera réalisé dans les 12 mois.

Ce qui est déjà en place

CritèreNiveauÉtat
Hiérarchie de titres + langue de la page (lang="fr")WCAG A · 1.3.1 / 3.1.1✓ Conforme
Labels formulaires associés (label for=)WCAG A · 3.3.2✓ Conforme
Navigation 100 % au clavier (Tab, Enter, Espace, Échap)WCAG A · 2.1.1✓ Conforme
Skip link "Aller au contenu principal"WCAG A · 2.4.1✓ Conforme
Trap focus dans les drawers / modalesWCAG A · 2.4.3✓ Conforme
Focus visible (outline lime)WCAG AA · 2.4.7✓ Conforme
aria-hidden sur emojis décoratifsWCAG A · 1.1.1✓ Conforme
aria-label enrichi sur composants dragWCAG A · 4.1.2✓ Conforme
Annonces lecteurs d'écran (aria-live)WCAG AA · 4.1.3✓ Conforme
Identification erreurs forms (aria-invalid, role="alert")WCAG A · 3.3.1✓ Conforme (login)
Alternative clavier au glisser-déposer Kanban (touche Espace)WCAG AA · 2.5.7✓ Conforme
prefers-reduced-motion respectéWCAG AAA · 2.3.3✓ Conforme
Tooltips dismissable par ÉchapWCAG AA · 1.4.13✓ Conforme (partiel)
Mode confort de lecture (zoom utilisateur, contraste renforcé, animations off)Bonus utilisateur✓ Disponible
Compatible NVDA, JAWS, VoiceOver, TalkBackWCAG A · 4.1.2⚠️ Théoriquement OK · tests utilisateurs réels à faire

Ce qui n'est pas encore conforme ou non vérifié

CritèreNiveauÉtat
Audit professionnel externe (cabinet RGAA)❌ Non réalisé · prévu dans les 12 mois
Contraste texte (4,5:1) audité partoutWCAG AA · 1.4.3⚠️ Audit partiel · variable --lime-text introduite mais non auditée systématiquement
Contraste éléments non-texte (3:1)WCAG AA · 1.4.11⚠️ Non audité
Resize text 200 % sans perte de fonctionWCAG AA · 1.4.4⚠️ Non testé sur l'ensemble des écrans
Reflow 320 px CSS sans scroll horizontalWCAG AA · 1.4.10⚠️ Partiellement testé · ajustements en cours
Suggestions structurées sur erreurs (au-delà du message texte)WCAG AA · 3.3.3❌ Non implémenté
Tests réels utilisateur avec lecteurs d'écran❌ Non réalisés (programmés post-30 fondateurs)
Sous-titres / transcripts pour contenu vidéoWCAG A · 1.2.x⚠️ Pas de vidéo embarquée actuellement · sera fait si vidéo ajoutée

Comment nous signaler un problème

Si vous rencontrez un défaut d'accessibilité (élément non navigable au clavier, contraste insuffisant, contenu mal lu par un lecteur d'écran, etc.), écrivez-nous à pedro.berbel@dezvolta.org avec :

Engagement de réponse : sous 5 jours ouvrés. Correction : selon la gravité, entre 1 jour (bloquant) et 30 jours (amélioration).

Voies de recours

Cette procédure est à utiliser dans le cas suivant : vous avez signalé au responsable du site un défaut d'accessibilité qui vous empêche d'accéder à un contenu ou à un service, et vous n'avez pas obtenu de réponse satisfaisante. Vous pouvez :

Ce document décrit l'état de la sécurité technique et juridique au 9 mai 2026. Il est mis à jour à chaque évolution structurelle. Il n'engage pas DEZVOLTA sur des résultats ni sur l'absence de failles non identifiées. Pour toute observation ou signalement de faille de sécurité (responsible disclosure), écrire à pedro.berbel@dezvolta.org — réponse sous 48h ouvrées.