Aller au contenu
mouaad.sek:~$
Tous les dossiers~/work/cf-04$
CF-04Produit · Commerce réelSTATUS: LIVRÉ

Site du restaurant L'Adress

Un site que les gérants pilotent eux-mêmes, avec des formulaires validés, limités en débit et protégés par la sécurité au niveau des lignes.

RÔLE
Seul, réalisé pour le restaurant
QUAND
2026
STACK
Next.js 15 App Router, Tailwind CSS 4, Supabase (Postgres, Auth, Storage), Resend, Docker, Vercel
LIEN
Repo privé, démo sur demande
01 / CONTEXTE

Le problème

Un petit restaurant a besoin de plus qu’une page menu : réservations de table, devis pour événements, galerie photo et actualités, le tout modifiable sans appeler un développeur.

Les formulaires publics d’un petit commerce sont aussi la première chose que trouvent les bots : la sécurité devait faire partie du projet, pas venir après.

02 / APPROCHE

Du formulaire visiteur à la boîte mail du gérant

  1. 01Formulaire
  2. 02Validation Zod
  3. 03Limiteur de débit
  4. 04Supabase + RLS
  5. 05Email au gérant
03 / SÉCURITÉ INTÉGRÉE

Sécurité intégrée

CONTRÔLECOUCHEPROTÈGE
Politiques RLS sur chaque tableBase de donnéesAccès aux données
Espace admin derrière un middleware d’authentificationApplicationBack-office
Validation de schéma sur chaque champAPIInjection, spam
Limitation de débit sur les endpoints publicsAPIAbus
Clé service-role uniquement côté serveurSecretsFuite de clé
Content-Security-Policy et en-têtes de sécuritéHTTPClickjacking, XSS
04 / PREUVES

Directement depuis le code

Extraits du vrai dépôt et des livrables, raccourcis pour la lecture.

supabase/migrations/001_initial_schema.sqlsql
ALTER TABLE public.reservations ENABLE ROW LEVEL SECURITY;

CREATE POLICY "public can insert reservations"
  ON public.reservations FOR INSERT
  TO anon, authenticated
  WITH CHECK (true);

CREATE POLICY "admins can manage reservations"
  ON public.reservations FOR ALL
  TO authenticated
  USING (is_admin());

Sécurité au niveau des lignes : un visiteur peut seulement créer une réservation, jamais en lire une. Lecture et gestion sont réservées aux admins.

src/lib/rate-limit.tstypescript
import { RateLimiterMemory } from 'rate-limiter-flexible'

// NOTE: In-memory limiters reset on cold starts in serverless environments.
// For production, swap to RateLimiterRedis or RateLimiterPostgres.

const limiters = {
  reservation: new RateLimiterMemory({ points: 5, duration: 3600 }),
  devis: new RateLimiterMemory({ points: 3, duration: 3600 }),
  contact: new RateLimiterMemory({ points: 5, duration: 3600 }),
} as const

Limites de débit par endpoint sur les formulaires publics. Le commentaire signale la limite connue, reprise dans le retour d’expérience.

05 / RÉSULTATS

Résultats

11pages publiques, optimisées SEO
16politiques de sécurité RLS
3formulaires publics avec email au gérant
06 / RETOUR D’EXPÉRIENCE

Ce que je ferais autrement

Les clients ne demandent pas de RLS, mais ils en souffrent quand elle manque. Prochaine étape : remplacer le limiteur en mémoire par un stockage partagé pour tenir la montée en charge.

DOSSIER SUIVANT · CF-05Audit d’infrastructure Canritco
Esc

↑↓ naviguer · Entrée ouvrir · Échap fermer