Les pages légales
Des mentions légales et une politique de confidentialité générées depuis les réglages, qui annoncent ce qui manque au lieu de l’inventer ; des coordonnées légales distinctes des coordonnées publiques ; et un registre des traitements décrit une seule fois pour deux publics.
Précédemment. Les membres reçoivent les documents du club, partagent leurs fichiers et s’adressent au club par des demandes suivies. Tout cela repose sur des données personnelles.
Un site qui collecte des données personnelles doit dire qui l’édite, ce qu’il fait de ces données, combien de temps il les garde, et permettre à chacun d’exercer ses droits. Cette partie suit ces obligations une à une : les pages légales, puis ce que le site fait réellement des données (durées tenues, export), enfin l’image des personnes, par formulaire papier et en ligne.
Les parcours du chapitre#
Deux parcours traversent ce chapitre : le club qui renseigne ses informations légales, et le visiteur qui lit la politique de confidentialité.
Acteur : Administrateur
- 1
Il enregistre la rubrique « Informations légales » des Réglages ; les pages légales la lisent aussitôt
siteSettings.saveLegaladmin- SiteSettings créée : accountRetentionMonths, backupRetentionDays, credits, hostAddress, hostName, hostPhone, hostUrl, id, legalAddress, legalEmail, legalName, legalPhone, legalRna, legalSiret, legalUpdatedAt, publicationDirector, publicationDirectorTitle, storageRegion, ticketRetentionMonths
- SiteSettings modifiée : accountRetentionMonths, backupRetentionDays, credits, hostAddress, hostName, hostPhone, hostUrl, id, legalAddress, legalEmail, legalName, legalPhone, legalRna, legalSiret, legalUpdatedAt, publicationDirector, publicationDirectorTitle, storageRegion, ticketRetentionMonths
Le chemin dans le code
Chaque ligne est un appel, suivi de l'endroit où le lire (à ouvrir dans l'éditeur, par exemple avec la recherche de fichier).
siteSettings.saveLegalpackages/backend/src/modules/siteSettings/router.ts:106ctx.prisma.siteSettings.upsertpackages/backend/src/modules/siteSettings/router.ts:128SiteSettings crééeSiteSettings modifiée
Des pages générées depuis les réglages ⚖️#
L’association n’a pas toutes ses informations légales sous la main d’un coup : le siège, le numéro RNA, l’hébergeur se renseignent au fil de l’eau. Les pages « Mentions légales » et « Politique de confidentialité » ne sont donc pas rédigées à la main : ce sont des composants serveur qui lisent la rubrique « Informations légales » des Réglages du site, à chaque affichage.
getLegalInfo — une seule lecture des réglages
Clique une étape pour mettre en évidence la zone correspondante dans le fichier complet.
// ⚠ Fichier introuvable : apps/web/src/features/legal/getLegalInfo.ts// Il a été déplacé ou supprimé depuis la rédaction de ce chapitre.La page annonce ce qui manque au lieu de l’inventer :
Une page à moitié remplie le dit, plutôt que de paraître complète avec de fausses valeurs. Une mention facultative (le numéro RNA, le SIRET) n’apparaît que si elle existe ; une mention obligatoire absente est annoncée « en cours de renseignement ».
Chaque page légale accepte enfin un complément libre, rédigé dans le constructeur de pages (une page de contenu du même slug) et affiché à la suite. Ces pages n’ont pas d’interrupteur de publication : elles sont publiques dès qu’elles existent, leurs fichiers aussi (partie « Contenu éditorial »).
L’enregistrement des informations est réservé aux administrateurs et date la mise à jour, que la page affiche :
saveLegal: protectedProcedure.use(isAdmin).input(saveLegalSettingsSchema).mutation(async ({ ctx, input }) => { const opt = (v: string): string | null => (v.trim() === "" ? null : v.trim()); const data = { legalName: opt(input.legalName), legalRna: input.legalRna.trim() ? compactId(input.legalRna) : null, legalSiret: input.legalSiret.trim() ? compactId(input.legalSiret) : null, legalAddress: opt(input.legalAddress), legalPhone: opt(input.legalPhone), legalEmail: opt(input.legalEmail), publicationDirector: opt(input.publicationDirector), publicationDirectorTitle: opt(input.publicationDirectorTitle), hostName: opt(input.hostName), hostAddress: opt(input.hostAddress), hostPhone: opt(input.hostPhone), hostUrl: opt(input.hostUrl), storageRegion: input.storageRegion || null, credits: opt(input.credits), accountRetentionMonths: input.accountRetentionMonths, ticketRetentionMonths: input.ticketRetentionMonths, backupRetentionDays: input.backupRetentionDays, legalUpdatedAt: new Date(), }; await ctx.prisma.siteSettings.upsert({ where: { id: SETTINGS_ID }, create: { id: SETTINGS_ID, ...data }, update: data, }); return { ok: true }; }),Un champ vidé redevient null (et la page l’annonce manquant). Les numéros RNA et SIRET sont enregistrés compactés (compactId retire les espaces et met en majuscules) : saisis « w 731 000 123 » ou « W731000123 », ils sont enregistrés et affichés pareil.
Le registre des traitements, décrit une seule fois#
Le RGPD demande deux documents qui disent la même chose à deux publics. La politique de confidentialité explique aux personnes ce qu’on fait de leurs données. Le registre des activités de traitement (article 30) est le document interne de l’association. Les deux sont produits à partir d’une description unique, dans packages/contracts :
export type ProcessingActivity = { id: string; /** Intitulé court (registre). */ name: string; /** Finalité, formulée pour la personne concernée (« Vous donner accès… »). */ purpose: string; /** Personnes concernées. */ people: string; /** Données traitées. */ data: string; /** Base légale (art. 6 RGPD), en clair. */ legalBasis: string; /** Qui y accède au sein du club. */ recipients: string; /** Prestataires impliqués (noms de PROCESSORS). */ processors: string[]; retention: string;};Chaque traitement (gestion des membres, présentation des instructeurs, demandes, correspondance, documents, photos et vidéos, sécurité) y est décrit une fois : finalité, personnes concernées, données, base légale, destinataires, prestataires et durée. Par exemple :
{ id: "media", name: "Photos et vidéos des activités", purpose: "Publier les photos et vidéos des cours, stages et événements, en galerie publique ou réservée aux membres.", people: "Membres et participants photographiés ; pour un membre mineur, son parent référent", data: "Image et voix des personnes reconnaissables ; formulaire d'autorisation signé (usages choisis, nom et qualité du signataire) ; pour un mineur, nom et e-mail du parent référent", legalBasis: "Autorisation de la personne (de ses parents pour un mineur)", recipients: "Public ou membres, selon la galerie et les usages autorisés ; le formulaire : la personne et les administrateurs", processors: ["Hetzner Online GmbH", "Cloudflare (R2)"], retention: "Images : tant que l'autorisation n'est pas retirée, et au plus tard un an après le départ sauf accord pour un usage au-delà ; formulaire signé : durée de l'adhésion, puis 5 ans", },La relecture de cette partie a complété le registre : le parent référent d’un membre mineur est une personne concernée à part entière (son nom et son e-mail sont enregistrés pour l’autorisation du droit à l’image), et la majorité et la date de dernière connexion font partie des données d’un membre. Une donnée collectée qui n’est pas au registre est une donnée dont l’association ne peut pas rendre compte.
Les deux documents en sont deux présentations :
Document | Où | Public |
|---|---|---|
Politique de confidentialité | /infos/confidentialite | Les personnes concernées (page publique). |
Registre des traitements (art. 30) | /dashboard/rgpd, imprimable | L’association (administrateurs). |
Showing entries1to2entries
Les deux pages appellent la même fonction, avec les mêmes réglages : processingActivities(info). Une fonctionnalité qui collecte une donnée nouvelle s’ajoute dans ce fichier, et les deux documents suivent : ils ne peuvent pas se contredire.
Chaque obligation a son mécanisme, et chaque mécanisme lit la même source : les Réglages pour les informations de l’éditeur et les durées, processingRegister.ts pour la description des traitements. Aucun document légal ne recopie une information qui vit ailleurs.
Le registre décrit ce que le code fait. Toute procédure qui enregistre une donnée personnelle nouvelle (un champ de profil, une adresse d’un tiers, un journal qui garde des IP) doit être relue avec lui ouvert à côté.
Récapitulatif#
Question | Réponse du projet |
|---|---|
D’où viennent les mentions légales et la politique de confidentialité ? | Des Réglages du site, lus à chaque affichage par getLegalInfo. |
Que montre une page pour une information absente ? | « en cours de renseignement » : jamais une valeur inventée. |
Quelles coordonnées figurent dans les documents légaux ? | Les coordonnées légales (siège, téléphone, e-mail de l’éditeur), jamais celles de « Nous contacter ». |
Comment la politique et le registre restent-ils cohérents ? | Ils sont deux présentations d’une même description des traitements (processingRegister.ts). |
Qui figure au registre ? | Toutes les personnes concernées, y compris le parent référent d’un mineur. |
Showing entries1to5entries
À suivre#
Les pages disent ce que le site fait des données. Encore faut-il qu’il le fasse : garder chaque donnée le temps annoncé, pas plus, et permettre à chacun de récupérer les siennes.
Chapitre suivant : les données personnelles. Une purge chaque nuit qui tient les durées annoncées, des comptes jamais supprimés sans décision humaine, et l’export de ses données par chaque membre.