# Modèle de données Deux tables Supabase (Postgres). Pas de table `users` côté invité : les invités n'ont pas de compte. L'admin n'a pas de compte non plus en V1 — son accès repose sur un token secret (voir `decisions.md`). ## Table `events` | Colonne | Type | Description | |---|---|---| | `id` | `uuid` (PK, défaut `gen_random_uuid()`) | Identifiant unique de l'événement | | `slug` | `text`, unique | Identifiant lisible utilisé dans l'URL publique d'upload (`/e/`) | | `nom` | `text` | Nom de l'événement (ex : "Mariage Julie & Marc") | | `date_evenement` | `date` | Date de l'événement, sert de référence pour l'expiration | | `created_at` | `timestamptz`, défaut `now()` | Date de création de l'événement dans le système | | `expire_at` | `timestamptz` | Date/heure d'expiration calculée (`date_evenement` + 7 jours) | | `statut` | `text` | Statut de l'événement : `actif`, `expire`, `archive` (à affiner) | | `admin_token` | `text`, unique | Token secret donnant accès à la galerie admin | | `client_nom` | `text`, nullable | Nom du client (utile en V2/V3 quand le service est vendu) | | `facture_montant` | `numeric`, nullable | Montant facturé au client (utile en V2/V3) | ## Table `photos` | Colonne | Type | Description | |---|---|---| | `id` | `uuid` (PK, défaut `gen_random_uuid()`) | Identifiant unique de la photo | | `event_id` | `uuid` (FK → `events.id`, `on delete cascade`) | Événement associé | | `url_storage` | `text` | Chemin/URL du fichier dans Supabase Storage | | `nom_invite` | `text`, nullable | Nom saisi par l'invité (optionnel) | | `message` | `text`, nullable | Message laissé par l'invité (optionnel) | | `uploaded_at` | `timestamptz`, défaut `now()` | Date d'upload | ## Row Level Security (RLS) RLS activé sur les deux tables. Règles à valider avec Kévin avant implémentation définitive, principe retenu pour l'instant : ### `events` - **Lecture publique** : non autorisée directement (pas de `SELECT` public sur `events`). L'accès public à l'upload passe par une vérification côté fonction/API sur le `slug` et le `statut = 'actif'`, sans exposer toute la ligne (notamment pas `admin_token`). - **Lecture admin** : autorisée si la requête présente l'`admin_token` correspondant (comparaison côté fonction Postgres/Edge Function plutôt que policy RLS naïve, pour éviter d'exposer le token dans une clause `WHERE` côté client). - **Écriture** : réservée à l'admin/back-office (pas de policy publique d'insertion/update sur `events`). ### `photos` - **Insertion (upload) anonyme autorisée** si et seulement si : - l'`event_id` correspond à un événement dont le `statut = 'actif'`, et - la date courante est antérieure à `expire_at`. - **Lecture** réservée à l'admin (accès via `admin_token` validé), jamais de lecture publique de la liste des photos d'un événement. - **Update / delete** : pas d'update par les invités ; delete réservé au job d'expiration automatique (ou à l'admin, à confirmer). > ⚠️ Le détail exact des policies RLS (SQL) sera écrit dans > `supabase/migrations/` au moment de l'implémentation, et validé avec > Kévin avant application — cf. règle "décision structurante" dans > `CLAUDE.md`.