Aller au contenu
← Retour aux projets

StockFlow

Gestion de stock, ventes et créances pour une équipe de vendeurs.

Année
2026
Statut
Projet personnel
Stack
TypeScriptNext.js 16React 19Tailwind 4shadcn/uiSupabasePostgreSQLDocker

Le problème

Suivre à la main les ventes, le stock et les créances de plusieurs vendeurs devient vite ingérable : le stock ne correspond plus au réel, les totaux dépendent de qui fait le calcul, et personne ne sait exactement qui doit combien. Il fallait une application où ces chiffres ne puissent pas diverger — y compris si quelqu'un cherche à les faire diverger.

L'architecture

Une application Next.js qui ne parle à sa base que depuis le serveur, adossée à une instance Supabase. Le navigateur ne reçoit que du HTML et des actions serveur : aucune clé, aucune adresse de base de données, donc rien qu'il puisse interroger de lui-même.

aucune clé transmisesession du vendeurNavigateurHTML · actions serveurApplication Next.jsRendu serveur · conteneurSupabasePostgres · RLS et fonctions
Le navigateur n'a aucune clé et ne peut rien demander directement à la base. Et comme l'autorisation vit dans Postgres, on pourrait supprimer toute l'interface sans ouvrir la moindre faille.

Les décisions qui comptent

  1. 01

    L'autorisation vit dans la base, pas dans l'interface

    Chaque table a ses politiques d'accès, chaque fonction d'écriture commence par une garde, et les écritures directes sont révoquées. Le test que je m'applique avant d'ajouter un contrôle : est-ce qu'on pourrait supprimer entièrement l'interface sans ouvrir une faille ? Si la réponse est non, le contrôle est au mauvais endroit.

  2. 02

    Aucun calcul métier en TypeScript

    Totaux, coûts, marges, dettes, contrôles de stock : tout est calculé en SQL. Les montants affichés pendant la saisie ne sont qu'indicatifs, celui qui fait foi est recalculé par la base. Sans cette règle, un vendeur pourrait soumettre un total qui l'arrange, et deux implémentations du même calcul finiraient de toute façon par diverger.

  3. 03

    Aucune clé d'accès dans le navigateur

    Les variables d'environnement ne portent pas le préfixe qui les rendrait publiques : elles sont lues à l'exécution et jamais intégrées au code envoyé au client. Vérifié plutôt que supposé — les 36 scripts chargés par la page ont été inspectés un par un, et l'image Docker ne contient aucun secret.

  4. 04

    Une règle d'accès qui se rappelait elle-même

    La politique qui protège la table des profils appelle une fonction qui doit lire cette même table. En lecture normale, la politique se redéclenche à l'intérieur d'elle-même et la requête part en boucle infinie. La fonction est donc déclarée pour s'exécuter avec les droits de son propriétaire, ce qui lui permet de lire la table sans repasser par le contrôle d'accès.

Aperçu

Capture à venir
Capture à venir