RECOVMAX
RECOVMAX  ›  DPA  ›  Audit sécurité
Document de transparence · v1 · 11 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
21
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 service applicatif 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.

Vos données — ce qu'on stocke, ce qu'on ne stocke jamais

Stocké chez DEZVOLTA (UE)

  • Email du compte · mot de passe haché (bcrypt Supabase Auth)
  • Clients accompagnés (nom, SIRET, email contact, IBAN client final si fourni)
  • Créances suivies (débiteur, montant, échéance, statut, historique)
  • Pièces justificatives uploadées
  • Relances envoyées + tracking Resend (sent/delivered/opened/clicked)
  • Journal d'audit append-only avec chaînage cryptographique SHA-256 (mig 052, livré 13/05/2026) — chaque ligne contient le hash de la précédente, toute altération a posteriori est détectable via RPC verify_audit_chain()

Jamais stocké

  • Données de paiement (CB, IBAN client) — gérées par Stripe (PCI DSS L1)
  • Mots de passe en clair
  • Cookies de tracking publicitaire tiers
  • Adresse IP brute dans les journaux (hash SHA-256 tronqué uniquement)
  • Aucune donnée de prompt utilisée pour entraîner l'IA Anthropic (ZDR)

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 & procédure restore Cron quotidien /api/backup?action=cron_weekly (Vercel 3h UTC) — 17 tables critiques exportées en JSON, envoyé par email TLS à l'opérateur. Procédure de restauration documentée v1.0 (13/05/2026) avec 4 scénarios (1 ligne · 1 table · base complète · compromission), vérifications d'intégrité post-restore (verify_audit_chain(), FK, comptes), calendrier trimestriel. Premier test checklist validé le 13/05/2026 (backup généré + reçu + hash chain validée). Engagements : RPO 24h · RTO 48h (formalisés dans DPA prochaine révision).
Audit append-only avec chaînage cryptographique Migration 052 (13/05/2026) — colonnes prev_hash + event_hash SHA-256 sur app_audit_log calculées via trigger BEFORE INSERT. Toute altération a posteriori d'une ligne casse la chaîne et est détectable via RPC verify_audit_chain() qui retourne {valid, broken_at_id, reason}. Genesis hash GENESIS pour la première ligne. Extension pgcrypto Supabase. Service_role uniquement pour la RPC de vérification.

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.
BYO Stripe Payment Link — anti-phishing Migration 049 (11/05/2026) : contrainte CHECK whitelist ^https://buy.stripe.com/[A-Za-z0-9_/-]+$ sur les liens fournis par les utilisateurs cabinet. Impossible d'injecter une URL de phishing dans les emails de relance envoyés à leurs débiteurs.
Transparence débiteur Le débiteur paye sur buy.stripe.com avec le branding du créancier final. Zéro mention RECOVMAX ni du cabinet dans le parcours de paiement. L'argent va directement au compte Stripe du créancier — DEZVOLTA n'est pas intermédiaire de paiement (pas d'agrément PSP/ACPR requis).
Hard cap fondateurs — race-safe Migration 050 (11/05/2026) : RPC claim_founder_seat() avec lock SELECT ... FOR UPDATE sur app_config. Deux paiements concurrents au cap-1 ne peuvent pas dépasser la limite. Fallback Standard + audit warning en cas de cap déjà atteint.
Réconciliation Stripe native client_reference_id Stripe injecté automatiquement dans les Payment Links et QR codes (MED + LRAR PDF). Permet à terme une réconciliation automatique sans intermédiaire technique.

IA Recovo — assistant rédaction & synthèse

Recovo est l'assistant IA intégré au dashboard RECOVMAX pour la rédaction de relances et la synthèse de dossiers, propulsé par Anthropic Claude (sous-traitant documenté dans la liste publique sous-traitants).

Anthropic ZDR (Zero Data Retention) Aucun prompt utilisé pour entraîner les modèles. Conservation côté Anthropic = 0 jour. Accord ZDR signé entre DEZVOLTA et Anthropic.
Filtre PII avant appel IA Aucun email débiteur ni nom de client final n'est transmis dans les prompts. Filtre serveur côté API avant tout appel.
Disclaimer juridique systématique Chaque réponse Recovo inclut explicitement : « RECOVO oriente la rédaction. Pour conseil juridique, voir avocat ou commissaire de justice. »
Sources internes figées Cadre français : L.441-10, loi 2026-307, Factur-X. Pas d'hallucination juridique sur réglementations étrangères.
Positionnement clair Recovo est un assistant d'orientation et de synthèse, pas un conseiller juridique automatisé. Le professionnel garde la responsabilité de chaque envoi.
Redaction des logs Stricte côté serveur : pas d'email débiteur, nom client, SIRET dans les traces de monitoring ou logs Vercel.
Anti prompt injection ⚠ En cours P1.3 Filtre input utilisateur (rejet des patterns "ignore previous instructions", "system:", etc.) en livraison sprint sécurité semaine 12 mai 2026.

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 append-only avec chaînage)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.

Signaler une faille de sécurité

Si vous avez identifié une vulnérabilité dans RECOV ou RECOVMAX, merci de nous écrire à pedro.berbel@dezvolta.org avec l'objet [SECURITY].

Notre engagement

Hors périmètre : DoS volumétrique, ingénierie sociale, accès physique, services tiers (Stripe, Supabase, Vercel, Resend, Anthropic, Cloudflare — à signaler directement à leur équipe sécurité respective).

Format standard : ces informations sont également publiées au format RFC 9116 — voir recov.pro/.well-known/security.txt.

Accessibilité — déclaration partielle

DEZVOLTA s'engage à rendre la suite RECOV / RECOVMAX accessible au plus grand nombre. L'audit professionnel accessibilité partielle (audit en cours) / 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 : 11 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 11 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.