My App

ADR-04: QR Code

Génération, personnalisation, token rotatif, format d'export

Contexte

Le QR code est le point d'entrée physique du système. Il doit être :

  • Personnalisable (logo, couleurs) pour que l'établissement se l'approprie
  • Sécurisé (token rotatif pour empêcher l'abus à distance)
  • Imprimable en haute qualité

Décision

Génération côté serveur avec token rotatif dans l'URL.

Structure de l'URL

https://app.wcare.fr/report/{toiletId}/{token}
  • toiletId : UUID du WC (stable, ne change jamais)
  • token : Token rotatif (UUID v4, change périodiquement)

Personnalisation

Stockée en JSONB dans la table qr_code :

{
  "logo": "https://cdn.wcare.fr/logos/hotel-xyz.png",
  "foregroundColor": "#1a1a1a",
  "backgroundColor": "#ffffff",
  "style": "rounded",
  "errorCorrection": "H"
}
  • Error correction "H" (30%) obligatoire quand un logo est présent
  • Formats d'export : SVG (web), PNG (aperçu), PDF (impression)

Rotation de token

ParamètreValeur
Durée de validité7 jours (configurable)
Ancien tokenRedirige vers le nouveau pendant 24h
Après 24hAncien token → erreur "QR code expiré, scannez à nouveau"
DéclenchementCron job quotidien

Le QR code physique ne change pas (il encode l'URL fixe avec toiletId). Seul le token dans l'URL est validé côté serveur.

Correction : En fait, le QR physique encode l'URL complète incluant le token. Quand le token est roté, l'ancien QR continue de fonctionner grâce au redirect via previousToken. L'établissement n'a pas besoin de réimprimer.

Alternatives écartées

AlternativeRaison du rejet
QR statique sans tokenAucune protection anti-abus
QR dynamique (short URL)Dépendance à un service tiers, latence
NFC tagsCoût unitaire plus élevé, pas universel
URL fixe avec CAPTCHAPlus de friction pour l'utilisateur

Conséquences

  • Positif : Protection anti-photo (le token expire)
  • Positif : Personnalisation full (logo, couleurs)
  • Positif : Pas besoin de réimprimer (redirect graceful)
  • Attention : Le cron de rotation doit être fiable
  • Attention : Error correction H réduit la densité d'info — l'URL doit rester courte

On this page