# Journal des décisions Ce fichier consigne les décisions structurantes actées pour le projet, avec la date à laquelle elles ont été prises. Toute nouvelle décision structurante (schéma DB, auth, hébergement, etc.) doit être ajoutée ici après validation par Kévin. ## 2026-09-18 - **Galerie invité (revirement)** : les invités peuvent désormais voir **toutes** les photos de l'événement (pas juste envoyer la leur), dans le cadre de la nouvelle DA "Polaroid Néon". Ça **inverse** la décision du cahier des charges initial ("Pas de galerie visible côté invité, confirmé : upload only"). Conséquence RGPD : le texte de mention légale (`docs/rgpd.md` + modale de bienvenue) doit indiquer que photo/prénom/ message sont visibles par les autres invités de l'événement, pas seulement mis à disposition de l'organisateur — mis à jour dans la foulée. Implémentation : backend (nouvelle RPC/Edge Function publique de listing + URLs signées pour les invités) pas encore fait à cette date, seul le rendu visuel est en cours. - **Nouvelle direction artistique "Polaroid Néon"** actée, voir `.claude/skills/photobooth-da/SKILL.md` pour le détail complet (palette, typographie, composant polaroid signature). Remplace les 3 passes DA précédentes (palette corail/prune/doré + Fraunces) — celles-ci restent en prod tant que la nouvelle direction n'est pas implémentée écran par écran. - **Stack confirmée inchangée** : vanilla JS/HTML/CSS, pas de framework (React proposé dans un brief externe, décliné — mandat CLAUDE.md déjà explicite sur ce point, aucune décision contraire prise). ## 2026-09-16 (récap fin de journée) Produit passé de "code écrit, rien de déployé" à **réellement en ligne et testé** : `https://photobooth.assistantaikev.eu` (VPS Hostinger, nginx + Traefik), backend sur le projet Supabase définitif `kevin-lecou-hub`. - **Bugs réels trouvés et corrigés en cours de route** (tous via tests en conditions réelles, pas en théorie) : - MIME type `.mjs` mal servi par nginx (bloquait tout le JS qui importe un module vendorisé — upload invité ET générateur QR étaient cassés). - Chemins relatifs (`style.css`, `config.js`, `gallery.js`) cassés sur les URLs réécrites `/e/` et `/admin/` — passage en chemins absolus partout. - Bug de cascade CSS présent **depuis le tout premier commit** : `display: flex` déclaré en dur sur `.upload-form`/`.welcome-modal` empêchait `hidden` (JS) de masquer quoi que ce soit visuellement — le formulaire est resté affiché en permanence, superposé aux autres états, sans que personne ne s'en rende compte avant un test réel. - Faille d'abus sur `insert_public_photo` (spam de lignes sans upload réel) — corrigée, vérification d'existence du fichier Storage ajoutée. - **Nouvelle fonctionnalité** : limite de photos par invité par événement (`max_photos_per_guest`), appliquée côté serveur via un `guest_id` anonyme (localStorage) — pas une identité vérifiée, contournable, mais fait respecter la vraie limite côté base. - **RGPD** : mention légale déplacée d'un bloc permanent vers une modale de bienvenue personnalisée (nom de l'événement) au premier passage par événement — texte légal inchangé, juste la présentation. - **Direction artistique** : 3 passes (palette sobre → palette punchy corail/prune/doré/Fraunces → mode sombre + finition animations). Statut au 2026-09-16 soir : jugée "pas mal, vraiment fonctionnel" par Kévin, mais **couleurs/DA pas encore validées définitivement** — Kévin prévoit un retour détaillé à l'agent direction-artistique lors d'une prochaine session. - **Reste ouvert** : activation du workflow n8n de purge Storage (credentials à créer côté Kévin), documentation de création d'un événement (encore manuel en SQL), remote Git à définir. ## 2026-09-15 - **Expiration des données** : suppression à **J+7 à partir de la date de l'événement** (`date_evenement`), et non à partir de la date de création de l'événement dans le système. - **Sécurité admin (V1)** : accès à la galerie admin via un **token secret dans l'URL** (`admin_token`), pas de système de login/mot de passe. Réévaluer ce choix avant V2/V3 si le nombre de clients augmente. - **Suppression des données** : effective à J+7 **dans tous les cas**, y compris si l'organisateur a déjà téléchargé le ZIP d'export des photos. - **Hébergement** : utilisation du **VPS existant de Kévin** (148.230.114.175), pas de nouvel hébergement dédié pour l'instant. ## 2026-09-16 - **Compression image côté client** : utilisation de la lib **`browser-image-compression`**, plutôt qu'une implémentation maison via Canvas API. Doit gérer l'orientation EXIF et les formats HEIC (iPhone). ## 2026-09-15 (bis) - **Préfixage des tables** : le projet Supabase de photobooth-qr sera mutualisé avec les autres projets de Kévin (KOMI, KAZA...). Tables préfixées `pq_` (`pq_events`, `pq_photos`), conformément à la convention du CLAUDE.md global. Les fonctions Postgres exposées au front (`get_public_event`, `event_accepts_uploads`) restent sans préfixe : ce sont des points de contrat public, pas des tables internes. - **Bucket Supabase Storage `event-photos`** : bucket **privé** (pas de lecture publique). Convention de chemin : `{event_id}/{uuid}.{ext}`. Consultation admin exclusivement via URLs signées générées par l'Edge Function `service_role`. Aucune policy SELECT/UPDATE/DELETE publique sur `storage.objects`. Limité à `file_size_limit = 6 Mo` et `allowed_mime_types = image/jpeg` (aligné sur la sortie de compression du front, qui force tout en JPEG y compris les HEIC convertis). - **`pq_photos.url_storage`** : contrainte `CHECK` garantissant que le chemin commence par `event_id/`, pour empêcher qu'une ligne de l'event A pointe vers un fichier de l'event B (isolation multi-tenant), trouvé lors de la relecture sécurité du 2026-09-15. - **`get_public_event`** : renvoie l'événement même si son statut n'est pas `actif` (expiré/archivé), pour permettre au front d'afficher un message adapté. Risque jugé faible : les slugs sont partagés via QR code, donc non secrets par nature. ## 2026-09-16 (quater) - **Limite de photos par invité** : nouvelle colonne `photobooth.events.max_photos_per_guest` (NULL = illimité par défaut), réglable uniquement en SQL à la création de l'event pour l'instant (pas d'UI admin dédiée). Appliquée via un `guest_id` anonyme généré et persisté côté client (localStorage) — **pas une identité vérifiée**, contournable en changeant d'appareil ou en vidant le storage. Fait respecter côté serveur (RPC `insert_public_photo`, source de vérité) et côté client de façon proactive (évite un envoi pour se le faire refuser à la dernière étape). ## 2026-09-16 (ter) - **Domaine de production (V1)** : `photobooth.assistantaikev.eu`, sous-domaine du domaine déjà utilisé pour n8n. Décision explicitement temporaire : à déplacer vers un domaine dédié en V2/V3 si le produit est vendu sous sa propre marque. Front servi par un container nginx sur le VPS existant (Traefik/Let's Encrypt déjà en place pour n8n), config dans `deploy/`. `APP_BASE_URL` configurée comme secret sur les 2 Edge Functions pour le CORS. Déploiement testé en conditions réelles le 2026-09-16 (upload + galerie admin fonctionnels depuis le domaine public). ## 2026-09-16 (bis) - **Déclenchement de la purge Storage à J+7** : **option n8n retenue** (plutôt que `pg_cron`+`pg_net`). Un workflow n8n planifié quotidien appelle l'Edge Function `expire-events` avec la `service_role` key (Credentials Store n8n), avec notification Telegram en cas d'échec. Cohérent avec la stack n8n déjà utilisée pour KOMI/KAZA, et le VPS n8n existant sert de point d'orchestration commun. Conception du workflow : `n8n/workflows/purge-storage-j7.json` (JSON importable, **non testé sur l'instance n8n réelle**, credentials à relier manuellement avant activation).