Commit Graph
31 Commits
Author SHA1 Message Date
Fabrice Coutadeur ebba0c8ce8 Correction : création d'arbre impossible en HTTP simple
crypto.randomUUID n'est exposé par le navigateur qu'en contexte sécurisé
(HTTPS ou localhost). Servie en HTTP simple, l'app plantait dans
generateSecurePassword à l'étape de création de l'arbre.

Repli sur crypto.getRandomValues, disponible partout, qui produit le
même UUID v4 sans tirets.

Signed-off-by: Fabrice Coutadeur <coutadeurf@gmail.com>
2026-10-08 12:00:17 +02:00
IliesAllaliandClaude Opus 5.5 0365a71618 Suivi avant le Show HN : démo, source jusqu'à l'inscription, un seul clic CTA
- demo_opened (une fois par chargement, visiteur sans compte) et demo_interaction (personne, média, recherche, édition, création d'arbre ; une fois par type, sans contenu)
- Source d'arrivée gardée sur l'appareil (?source=hn) et jointe à account_screen_viewed et account_registered ; la landing transmet la vraie source au CTA et à l'iframe de démo au lieu de source=landing
- Plus de remise à zéro PostHog à chaque ouverture anonyme (effaçait le visiteur de la landing), seulement à la déconnexion
- Landing : un seul événement signup_cta_clicked (hero_cta_clicked retiré, plus utilisé par le funnel), envoyé avant la navigation sans sendBeacon (bloqué par Brave)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:41:21 +02:00
IliesAllaliandClaude Opus 5.5 10f1fc5d14 Typo : plus de mot ni de signe seul en fin de ligne
- text-wrap-style pretty sur les paragraphes, listes, légendes et chapôs, balance sur les titres
  (landing, guides statiques, base pz.css de l'app). Longhand pour ne pas réactiver le retour
  à la ligne là où white-space: nowrap est posé. Les noms de l'arbre sont sur le canvas, non touchés.
- Espaces insécables du français dans le texte visible : fine insécable avant ? ! ;,
  insécable avant : et dans les guillemets, entre un nombre et son unité (Mo, Go, €, dpi).
  Landing (i18n.js, bloc fr hors meta) et pages guides FR (corps de page, hors script).
- App : frenchTypography() appliquée par t() en français, avant le remplacement des variables ;
  le dictionnaire anglais reste indexé sur le français tel qu'écrit. Tests mis à jour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 17:06:44 +02:00
IliesAllaliandClaude Opus 5.5 8b50356c4b Démo : vraie vidéo d'époque pour le mariage de Simone, vidéos de remplacement retirées
Le souvenir « Mariage Simone 1943 » ouvrait Big Buck Bunny sur YouTube.
Remplacé par 25 s des actualités Polygoon « Bruiloft te Giethoorn » (1947,
Beeld en Geluid via Open Beelden, CC BY-SA 3.0 NL), sans le son, en H.264
pour Safari, servi par le site (media-src 'self'). Crédit dans CREDITS.md
et sources.json. Les trois autres vidéos YouTube de remplacement de la démo
(Témoignage filmé 1960, Anniversaire 2020, Interview archive radio) sont
retirées.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:55:05 +02:00
IliesAllaliandClaude Opus 5.5 75922f3ed3 Sécurité 1.0.1 : audit indépendant de la 1.0
- Vidéo piégée : l'expression régulière de position était quadratique, un faux MP4 de 2 Mo figeait l'API (bornée, linéaire)
- Sessions émises avant le 01/10/2026 refusées (SESSIONS_NOT_BEFORE) : des sessions ont fuité dans les annotations et les journaux jusqu'à la 1.0
- Contributions : l'« avant » montré au propriétaire vient de la base ; une suppression approuvée part en cascade (unions, liens, souvenirs, portrait, fichiers)
- Mot de passe de partage : essai compté avant bcrypt, comparaisons une par une, changement et rattachement dans une transaction
- Quota mesuré sur le disque, 10 arbres par compte, corps à 1 Mo hors envois, bornes sur annotations, contributions et GEDCOM
- GIF réencodés ; anciennes propositions d'annotation sans adresse stockée ; clé d'exemple refusée sans NODE_ENV
- Déploiement du commit validé par la CI, clé d'hôte obligatoire ; nginx : X-Forwarded-For écrasé, version masquée, journal sans query string
- PostHog verrouillé dans le code, sans script externe ; CSP sans *.posthog.com ; sauvegardes hors serveur chiffrées par défaut

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 12:19:41 +02:00
IliesAllaliandClaude Opus 5.5 431eb06a87 ESLint 10 et @eslint/js 10 (Dependabot #36)
La PR montait @eslint/js seul, dont la config recommandée ajoute no-useless-assignment, no-unassigned-vars et preserve-caught-error. eslint passe aussi en 10 (configuration à plat déjà en place, aucun commentaire eslint-env, Node 24) ; eslint-plugin-react-hooks 7.1 et eslint-plugin-react-refresh 0.5 la déclarent prise en charge. Les trois signalements de no-useless-assignment étaient fondés : une valeur initiale jamais lue, chaque branche suivante l'écrase ou quitte la fonction (libellé de parenté, contenu JSON d'une photo ou d'un tracé posé sur l'arbre). Valeur initiale retirée, comportement inchangé.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:19:27 +02:00
IliesAllaliandClaude Opus 5.5 f509bc1751 lucide-react 1.49 (Dependabot #33) : tracés de l'arbre lus dans @lucide/icons
La version 1 ne publie plus dist/esm/icons/*.js ni __iconNode : renderers.js importait ces fichiers internes pour dessiner les vignettes carte et GPX sur le canvas, d'où l'échec du build (CI Frontend et image Docker). Les tracés viennent maintenant de @lucide/icons, le paquet officiel des données d'icônes (export nommé, propriété node), à la même version que lucide-react. Les 47 icônes utilisées existent toujours sous leur nom (Edit3, HelpCircle, MoreHorizontal, Trash2 restent des alias) et rendent un SVG identique à la 0.564, aria-hidden compris. Les icônes de marque retirées en v1 ne sont pas utilisées ici.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:16:33 +02:00
IliesAllaliandClaude Opus 5.5 5fcaa85d8f Front : mineures et correctifs groupés (Dependabot #31), refs hors du rendu
React et react-dom 19.3.0, @types/react et @types/react-dom 19.3.0, posthog-js 1.434.15, autoprefixer 10.6.1, eslint-plugin-react-hooks 7.1.1, eslint-plugin-react-refresh 0.5.7. La règle react-hooks/refs de la 7.1 voit maintenant les refs lus ou écrits pendant le rendu, corrigés plutôt que désactivés : le nom de l'arbre partagé affiché par l'écran compte passe par un état (un ref ne redessine rien), la personne de départ de l'arbre est recopiée dans un effet déclaré avant celui du cadrage, l'API de zoom est exposée par useImperativeHandle, l'horodatage des portraits est posé au premier chargement au lieu de Date.now() au rendu (react-hooks/purity). react-refresh 0.5 garde l'export par défaut et la config vite utilisés ici.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:12:32 +02:00
IliesAllaliandClaude Opus 5.5 ba15fc8745 Compte : « Supprimer mon compte » joignable, lien mort sans déconnexion
Avec un arbre, la fenêtre « Mon compte » ne menait nulle part : elle a maintenant « Gérer mon compte », qui ouvre « Vos arbres » (déconnexion, suppression du compte), la croix ramène à l'arbre. Sans arbre, « Mon compte » renvoyait aussitôt à l'assistant de création : le repli vers la démo ne se déclenche plus quand l'utilisateur a ouvert l'écran lui-même. Sur le lien d'un arbre supprimé, la session du compte est restaurée, « Créer mon arbre » ouvre le compte connecté au lieu d'un écran de connexion. Page vie privée alignée sur le chemin réel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:22:45 +02:00
IliesAllali bd4f5856ad Intègre securite/front : polices servies par le site, PostHog sans adresse d'arbre, vie privée à jour 2026-09-30 18:09:30 +02:00
IliesAllaliandClaude Opus 5.5 468204c9d3 Images de l'arbre : jeton médias à la place de la session du compte
Portraits, souvenirs, photos posées sur l'arbre et aperçus de relecture chargeaient leur image avec la session complète dans l'adresse. Ils utilisent maintenant le jeton de lecture des médias fourni avec le graphe (utils/mediaToken.js), jamais ajouté à une adresse externe. L'aperçu d'une photo posée par la famille n'accepte qu'une photo de cet arbre, reconstruite depuis son chemin. Message pour un arbre plein (storage_quota_exceeded).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:03:04 +02:00
IliesAllaliandClaude Opus 5.5 81ebad78a2 Arbre : plus d'appel à youtube.com à l'ouverture
Le cache d'images de l'arbre chargeait l'adresse de chaque média, vidéos YouTube
comprises, sans que personne lance la vidéo. Seules les photos, les seules
dessinées, sont chargées.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:02:11 +02:00
IliesAllaliandClaude Opus 5.5 f2a66be51e Vidéos YouTube : identifiant vérifié, lecteur youtube-nocookie
L'identifiant doit faire 11 caractères (lettres, chiffres, - et _), sinon rien
n'est intégré. Le lecteur vient de youtube-nocookie.com. La carte OpenStreetMap
n'envoie plus que l'origine en referrer, plus l'adresse de l'arbre.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:02:10 +02:00
IliesAllaliandClaude Opus 5.5 2253f626c7 Lien de partage : lectures ownerName et ownerEmail retirées
L'API /api/arbre/:slug ne renvoie ni nom ni email du propriétaire. Les lectures
restaient dans le front sans jamais rien recevoir.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:59:34 +02:00
IliesAllaliandClaude Opus 5.5 63c38e79d2 Stockage local : vieux mots de passe effacés au démarrage, compte effacé à la déconnexion
Toutes les copies invite_password_* partent au lancement de l'app, plus seulement
celle de l'arbre rouvert. À la déconnexion et à la suppression du compte, les
brouillons d'édition, la fiche « c'est moi » et le profil sont effacés. Le prénom
du contributeur, la langue et les accueils vus restent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:57:57 +02:00
IliesAllaliandClaude Opus 5.5 f14af72c8d Liens d'aide et de vie privée réglables pour une instance auto-hébergée
VITE_HELP_URL et VITE_PRIVACY_URL remplacent les pages de parenthese.io,
qui restent la valeur par défaut. Documenté dans les deux README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:56:04 +02:00
IliesAllaliandClaude Opus 5.5 e1e623961d Mesure d'audience : l'adresse d'un arbre ne part plus chez PostHog
before_send réécrit /arbre/<slug> en /arbre/:slug dans toutes les propriétés
(URL, chemin, referrer, propriétés initiales de personne). Enregistrement de
session coupé explicitement, appel /flags coupé (aucun feature flag utilisé,
il envoyait les propriétés de personne sans passer par before_send).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:55:12 +02:00
IliesAllaliandClaude Opus 5.5 f40dbac133 Polices servies par l'app et le site, plus aucun appel à Google Fonts
Newsreader et DM Sans : fichiers woff2 identiques à ceux que servait Google Fonts
(mêmes axes, graisses et découpages), licence OFL à côté des fichiers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:40:02 +02:00
IliesAllaliandClaude Opus 5.5 6f28918dde Interface en anglais : traduction, bascule FR · EN, accents corrigés
Module frontend/src/i18n : le texte français sert de clé, dictionnaires anglais
par zone, langue du navigateur puis choix mémorisé, ?lang=en pour forcer.
Bascule dans le menu du compte, la pastille visiteur, le menu Plus, l'écran
d'accès et la connexion. Démo traduite (noms et lieux gardés). Liens d'aide et
de vie privée selon la langue. Textes français sans accents corrigés.
Test : chaque texte passé à t() a sa traduction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:01:15 +02:00
IliesAllaliandClaude Opus 5.5 7a6a3a0942 Arbre sans personne de départ : ouverture sur le portrait le plus proche du centre
Le cadrage de l'étape 5 s'appuyait sur la personne de départ, absente de
certains arbres réels : on retombait sur l'arbre entier illisible.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 19:03:37 +02:00
IliesAllaliandClaude Opus 5.5 9e810fd844 Famille arrivée par le lien : accueil, ajout guidé, mode d'emploi
Replays du 24/09 : personne ne trouvait comment ajouter. Pour qu'une
grand-mère s'en sorte seule depuis un lien :

- arbre ouvert zoomé sur la personne de départ quand il est trop grand
  pour être lisible en entier, sans fiche ouverte par-dessus
- carte d'accueil de deux phrases, une seule fois par arbre
- barre du bas en toutes lettres : Ajouter un souvenir, Ajouter une
  personne, Plus (dessin, mode d'emploi, compte)
- « Pour qui ? » : recherche par prénom avec portraits, puis les souvenirs
  de la personne ; panneau simplifié pour la famille
- une personne ajoutée part tout de suite à l'envoi (prénom, un mot)
- fiche ouverte sur Souvenirs avec le bouton, dates en toutes lettres
- bandeau d'envoi masqué tant qu'il n'y a rien à envoyer
- portraits de l'arbre perdus après un rechargement sans nouveau
  placement : horodatage stable et images rechargées à chaque données
- page parenthese.io/aide/ avec captures de l'arbre de démo, liée depuis
  l'accueil, le menu Plus et le message d'invitation

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 18:51:45 +02:00
IliesAllaliandClaude Opus 5.5 5fc0c08c1c Journal des visites, recherche qui mène à la personne, croix de retour à l'arbre
- Visites : chaque ouverture de l'arbre est notée (prénom facultatif demandé avec le mot de passe, appareil, compte), sans adresse IP, effacée après un an ; onglet Visites dans les paramètres, réservé aux administrateurs
- Recherche : un résultat choisi recentre l'arbre sur la personne, la liste se replie
- Écran de compte ouvert depuis l'arbre : croix pour y revenir
- Enfant presque sous l'union : trait direct au lieu d'un petit S
- Page vie privée : paragraphe sur les visites

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 18:44:07 +02:00
IliesAllaliandClaude Opus 5.5 8a63943497 Arbre : conjoints isolés en petit, renvoi vers les parents, fil en accolade
- Conjoint marié sans parent ni enfant dans l'arbre : petit portrait collé à son partenaire, sans emplacement de nœud ni orbite
- Enfant placé sous l'autre lignée : pastilles « Voir les parents » et « Voir <prénom> » cliquables au lieu du trait qui traverse l'arbre
- Fil terracotta clair en accolade arrondie, union marquée du rond terracotta

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 18:07:56 +02:00
IliesAllaliandClaude Opus 5.5 92a4e5e1b9 Invitation de la famille : mot de passe toujours à jour, message prêt à copier
Le panneau du propriétaire affichait la copie gardée par le navigateur où le
mot de passe avait été défini : changé depuis un autre appareil, il montrait
l'ancien. Le serveur garde maintenant le mot de passe de partage chiffré
(AES-256-GCM, clé dérivée de JWT_SECRET) dans une table à part, pour ne pas
toucher la version des accès déjà ouverts.

- GET /trees/:id/access/passwords : le mot de passe en vigueur, admin seulement
- POST .../remember : arbres d'avant, le propriétaire saisit celui déjà donné,
  vérifié contre les hash, retenu sans rien changer aux accès
- rotation à deux mots de passe distincts : plus de valeur lisible
- anciennes copies locales effacées à l'ouverture du panneau
- message d'invitation (lien, mot de passe, une phrase) modifiable et à copier

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 17:18:18 +02:00
IliesAllaliandClaude Opus 5.5 8bfc78b2f5 Contributions fiables : prénom, mot d'accompagnement, liens gardés
- Prénom demandé à l'envoi d'une contribution et d'un souvenir, retenu
  sur l'appareil pour la fois suivante (submittedByLabel). Le propriétaire
  lit « par Camille » au lieu de « par Contributeur ».
- Mot d'accompagnement enregistré (ContributionSession.comment, migration
  additive) et affiché à la relecture.
- Une personne ajoutée par la famille garde ses liens : identifiant
  provisoire « tmp:… » remplacé par le vrai id à l'application ; un lien
  vers une personne refusée est écarté au lieu de faire échouer la
  relecture. Frère ou sœur : parents calculés aussi pour la famille.
- Soumission et relecture en transaction, appliquées dans l'ordre
  personnes, unions, liens : tout ou rien.
- Bouton « Ajouter une personne » pour la famille sur ordinateur ; après
  l'ajout, le panneau se ferme et un message confirme que la personne est
  dans les modifications ; il ne réapparaît plus au retour en édition.
- Relecture : les liens se lisent « Léon, enfant de Marc ».

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 13:52:23 +02:00
IliesAllaliandClaude Opus 5.5 66752aa1b6 Souvenirs de la famille : envoyés en attente, visibles après relecture
Un membre de la famille (lien de partage ou membre non administrateur)
peut maintenant envoyer une photo, une vidéo, une voix ou une citation.
Le serveur la stocke « en attente » et crée une contribution d'une ligne,
qui arrive dans « Propositions à relire » avec l'aperçu de la photo.
Accepter la rend visible, refuser la masque. En mode « application
immédiate », elle est visible tout de suite.

- Migration additive : MediaItem.status (approved par défaut, tout
  l'existant reste visible), MediaItem.contributionSessionId, valeur
  « media » dans ContributionEntityType.
- Graphe, statistiques, ordre des souvenirs : souvenirs acceptés seuls.
- Relecture d'une session contenant un dessin : ne plante plus
  (l'annotation tombait dans la branche des liens).
- App : message « Merci, c'est envoyé » après un envoi en attente ;
  réordonner, supprimer et changer la photo de profil réservés au
  propriétaire (le serveur les refuse aux autres).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 13:20:12 +02:00
IliesAllaliandClaude Opus 5.5 84ac4e1171 Un seul mot de passe de partage : regarder et proposer
Le déverrouillage ouvre toujours en contributeur, quel que soit le mot de
passe tapé : les deux mots de passe déjà envoyés aux familles continuent
de marcher. Les jetons et accès « visitor » existants peuvent proposer
sans rien ressaisir. La rotation accepte un mot de passe unique, écrit
dans les deux colonnes (pas de migration). Côté app, un nouvel arbre
reçoit un seul mot de passe, gardé dans le navigateur du propriétaire,
et le panneau de partage n'affiche plus qu'un champ, avec Copier.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 12:57:13 +02:00
IliesAllaliandClaude Opus 5.5 afe4a6a6d1 Le rond qui attend : le symbole du logo devient l'indicateur de chargement
Pendant une attente, le rond se divise en trois points qui respirent,
puis se referme avec un léger rebond quand c'est prêt.

- App : écran de démarrage (BootLoader, visible seulement au-delà de 400 ms,
  au moins 900 ms pour ne pas clignoter), remplace « Chargement de l'arbre
  généalogique... ».
- App : les boutons en attente (Création…, Envoi…, Un instant…) montrent
  trois points à la place du libellé, largeur figée, texte gardé pour les
  lecteurs d'écran (PzBusy).
- Landing : chargement de la démo intégrée.
- Réduire les animations : points sur place, fondu seul.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 12:12:58 +02:00
IliesAllaliandClaude Opus 5.5 5b5636e1be Refonte de la direction artistique : accent terracotta, landing, app et démo
- Landing refaite : nouvelle palette claire, Newsreader et DM Sans, logo validé,
  sections (garanties, trois gestes, démo, pour qui, engagements, guides, bloc final).
  Illustration du hero conservée et recolorée, portraits alignés sur les âges.
- App : couleurs et typographie passées à la nouvelle DA, structure et fonctionnalités inchangées.
  Composants communs dans src/styles/pz.css.
- Refaits de zéro : fiche d'une personne (souvenirs, infos, liens, panneau mobile),
  connexion, création de compte, liste des arbres, accès par mot de passe, recherche,
  barre d'actions, menu du compte, zoom, et toutes les fenêtres (compte, création d'arbre,
  contributions, envoi, sortie d'édition, brouillon, ajout de personne, souvenirs, visionneuse,
  paramètres de l'arbre).
- Arbre : chaque personne garde sa forme de cadre tirée au hasard, cadre vertical pour une photo carrée.
- Démo : photos d'époque libres de droits hébergées dans public/demo (sources et licences
  dans sources.json et CREDITS.md), famille Dupont crédible, Isabelle née à Fort-de-France.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 11:21:04 +02:00
IliesAllaliandClaude Opus 5 0c4cc20c97 Suppression des données par les utilisateurs, CI et auto-hébergement vérifié
Utilisateurs
- Suppression de compte depuis l'écran « Votre compte », confirmée par mot de passe :
  arbres possédés et médias effacés, email retiré des contributions, sessions fermées partout.
- Suppression d'arbre définitive, en base et sur le disque.
- Ajout d'un frère ou d'une sœur relié aux parents existants ; relations parent et enfant
  corrigées en mode démo.
- Liste d'attente retirée (route, envoi d'emails, dépendance Resend).

Projet ouvert
- CI : front, landing, backend avec vérification des migrations, test Docker de bout en bout.
- Déploiement lancé seulement après une CI réussie sur main.
- Image API : CLI Prisma installée à part pour que les migrations tournent au démarrage.
- SECURITY.md, CONTRIBUTING.md, modèles d'issue et de pull request.
- Migration renommée avec un nom descriptif, contenu identique.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 16:22:26 +02:00
IliesAllaliandClaude Opus 5 e8e2485dcd Parenthèse
Galaxie familiale : personnes, unions et filiations, photos, vidéos et voix sur chaque personne,
partage par lien avec consultation sans compte et contributions validées par le propriétaire.
Auto-hébergeable avec Docker. Licence PolyForm Noncommercial 1.0.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 15:49:05 +02:00