Home/Sécurité & Architecture

Vos données,
sous verrou.

Chaque organisation est isolée à trois niveaux indépendants. Un bug dans un seul contrôle d'accès ne suffit jamais à exposer les données d'un autre client — c'est la garantie qu'on doit à chaque commerce, chaque équipe, chaque client final.

Permissions vérifiées en 2ms
2FA natif RFC 6238
Automatisations sans couplage
Isolation à 3 niveaux
Chaque action tracée
ACCES_01

Rôles & permissions dynamiques

Problème réel

Des permissions figées dans le code obligent à redéployer pour chaque nouveau rôle métier — un gérant qui veut créer un rôle « Caissier junior » doit attendre une mise à jour.

Solution Neruki

Rôles et permissions stockés en base de données, modifiables depuis les paramètres de l'organisation sans redéploiement. Mise en cache Redis : la vérification passe de 150ms à 2ms.

Impact

Un gérant crée et ajuste ses rôles lui-même. Chaque requête reste vérifiée en 2ms, même avec des dizaines de rôles personnalisés.

permission.guard.ts
01async canActivate(ctx): Promise<boolean> {
02const perms = await cache.getUserPermissions(
03user.sub, user.org_id // Redis TTL 5min
04);
05if (perms.includes('*')) return true; // OWNER
06return required.every(p => perms.includes(p));
07}
AUTOMATISATIONS_02

Modules découplés, automatisations fiables

Problème réel

Coupler directement Fidélisation et Coupons dans le code créerait une dépendance rigide : impossible de désactiver l'un sans casser l'autre, impossible d'ajouter un troisième module réactif sans tout retoucher.

Solution Neruki

Un déclencheur configurable écoute les événements métier (ex. « offre de fidélité acceptée ») et déclenche une action dans un autre module via une file d'attente dédiée, avec 3 tentatives et un échec toujours silencieux côté utilisateur.

Impact

Fidélisation ignore totalement l'existence de Coupons. Désactiver un module premium ne casse jamais les autres — le comportement se reconfigure sans toucher au code.

event-trigger-bridge.service.ts
01async enqueue(event, payload) {
02await queue.add('dispatch', { event, payload }, {
03attempts: 3, backoff: 'exponential',
04}); // jamais d'erreur remontée à l'appelant
05}
Fidélisation ↛ Coupons
Modules découplés
3, backoff expo.
Tentatives
Jamais bloquant
En cas d'échec
ACCES_03

2FA TOTP — zéro dépendance

Problème réel

Les librairies TOTP tierces ajoutent des vecteurs d'attaque et des dépendances à maintenir. Les codes de secours sont souvent stockés en clair.

Solution Neruki

Implémentation native : HMAC-SHA1, base32 RFC 4648, dynamic truncation RFC 4226. Codes de secours générés et hashés en SHA-256, à usage unique.

Impact

Le compte d'un gérant reste protégé même si son mot de passe fuite. Compatible Google Authenticator, Authy, 1Password.

account.service.ts — 2FA TOTP RFC 6238
01function totpCode(secret, counter) {
02const key = base32Decode(secret);
03const hmac = createHmac('sha1', key).update(buf);
04// Dynamic truncation RFC 4226
05return (offset & 0x7fffffff) % 1_000_000;
06} // Zéro dépendance externe
ISOLATION_04

Isolation multi-tenant — 3 niveaux indépendants

Problème réel

Une seule couche d'isolation est insuffisante : un bug dans un seul contrôle expose toutes les données de toutes les entreprises clientes.

Solution Neruki

Le token d'accès identifie l'organisation dès la connexion, un contrôle serveur valide l'appartenance à chaque requête, et la base de données applique elle-même l'isolation via Row Level Security.

Impact

Trois couches indépendantes : une seule suffit à bloquer une intrusion. Vos données ne sont jamais visibles par une autre entreprise cliente, même en cas de bug.

@repo/auth/src/types/jwt-payload.ts — Isolation dès la compilation
01type SaaSJwtPayload = {
02scope: 'saas'; org_id: string; // obligatoire
03}
04type AdminJwtPayload = { scope: 'admin' };
05// Un token Admin ne peut jamais passer pour un token client
JWT séparés
SaaS / Mobile / Admin
Contrôle d'accès
Vérifié à chaque requête
Row Level Security
Au niveau base de données
prisma.service.ts — withTenant()
await prisma.$transaction(async (tx) => {
await tx.$executeRaw`SET LOCAL app.org_id = ${orgId}`;
return await tx[model].findMany(...);
});
TRACABILITE_05

Traçabilité complète — qui a fait quoi, quand

Problème réel

Sans journal d'audit, impossible de répondre à « qui a annulé cette vente ? » ou « pourquoi ce stock a-t-il changé ? » — un vrai problème en cas de litige client ou de contrôle interne.

Solution Neruki

Chaque action sensible (vente annulée, stock ajusté, rôle modifié, coupon validé) est journalisée avec l'utilisateur, l'organisation et l'horodatage — automatiquement, sans code additionnel dans chaque module.

Impact

Un historique complet et consultable, utile pour trancher un litige ou auditer l'activité d'une succursale.

audit-log.interceptor.ts — qui, quoi, quand
01const store = als.getStore();
02await prisma.auditLog.create({ data: {
03orgId: store?.orgId, userId: store?.userId,
04action, entity, entityId, // avant / après
05} });
Portée
Vente annulée, stock ajusté, rôle modifié…
Corrélation
requestId / orgId / userId
Format
NDJSON, exploitable en production
Utilité
Litige client, contrôle interne

Sécurité & fiabilité

Vos données, celles de vos clients et de votre équipe restent protégées à chaque couche de la plateforme.

Isolation des données

  • Multi-tenantOrg isolée à 3 niveaux
  • Base de donnéesRow Level Security
  • RequêtesFiltrées par organisation
  • SuccursalesStock scopé par site
  • Scopes JWTSaaS / Mobile / Admin séparés

Accès & permissions

  • AuthentificationJWT + 2FA TOTP natif
  • RôlesDynamiques par organisation
  • Vérification droitsCache Redis — 2ms
  • SessionsPar appareil, révocables
  • Mots de passeArgon2 + SHA-256

Infrastructure & continuité

  • Base de donnéesPostgreSQL managé
  • Cache & filesRedis + BullMQ
  • Emails & automatisationsToujours asynchrones
  • FichiersS3 / MinIO
  • DéploiementDocker reproductible
100% Type-Safe
Docker Ready
Permissions en 2ms
2FA TOTP natif

Prêt à reprendre le contrôle de votre activité ?

Un volet suffit pour démarrer. Ajoutez le reste — CRM, fidélisation, suivi — quand vous êtes prêt, jamais l'inverse.

Multi-succursale
Point de vente & caisse
Pipeline commercial
Devis & Services
Fidélisation & Coupons
Suivi & relances automatiques
Mobile Money
Isolation totale par organisation