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>
Un nom GEDCOM piégé bloquait l'API plusieurs secondes (expression régulière quadratique) : lu par indexOf, lignes et fiches plafonnées. L'export n'injecte plus de lignes. Deux relectures simultanées appliquaient deux fois les ajouts : la session est verrouillée dans la transaction. Au plus 200 changements par envoi, photos refusées effacées du disque.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Les annotations se lisaient avec n'importe quel compte, et une annotation photo enregistrait l'adresse de l'image avec la session de son auteur. Accès vérifié, adresse retirée à l'écriture comme à la lecture. Les images portent un jeton de lecture des médias (12 h, un arbre) au lieu de la session du compte. trustProxy ne croit plus que nginx (TRUST_PROXY), l'API peut n'écouter que la boucle locale (HOST), plafond de 30 échecs par arbre sur le mot de passe de partage, changer ce mot de passe coupe les comptes rattachés, connexion à durée constante, secrets d'exemple refusés en production.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Un SVG ou du HTML déclaré « photo » passait et s'exécutait sur app.parenthese.io à l'ouverture (vol de session du propriétaire). Le type vient maintenant des premiers octets, les photos sont réencodées par sharp (rotation appliquée, EXIF et GPS retirés), les vidéos de téléphone perdent leur position, et chaque fichier est servi avec nosniff et une CSP sandbox (téléchargement pour tout ce qui n'est pas image, son, vidéo ou PDF). Fichiers supprimés effacés du disque, quota par arbre, limite de débit sur les envois.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chaque action est référencée par son commit, version en commentaire. Le
déploiement lit la clé d'hôte dans le secret SSH_KNOWN_HOSTS et exige sa
vérification ; sans secret, repli sur ssh-keyscan avec un avertissement.
La CI échoue sur une faille critique d'une dépendance de production.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
deploy.sh sauvegarde la base dans $BACKUP_ROOT/pre-migration quand prisma migrate
status signale un écart, garde les 10 derniers dumps et s'arrête si pg_dump échoue.
backup.sh crée ses fichiers en umask 077 et, si BACKUP_AGE_RECIPIENT est renseigné,
n'envoie sur S3 que des copies chiffrées avec age. Commentaires sur les polices
du frontend mis à jour (deploy.sh, ci.yml).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
X-Frame-Options ALLOWALL (invalide) et X-XSS-Protection retirés. Les location qui
posent leur propre add_header répètent la liste complète, sinon nginx n'hérite
de rien. CSP de l'app et de la landing construites depuis ce que chargent les
builds (PostHog, YouTube sans cookie, OpenStreetMap, blob:, iframe de démo).
Prod seulement : HSTS avec includeSubDomains, ssl_protocols TLSv1.2 TLSv1.3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lancé à la main. Clone, .env, docker compose up -d sur le port 80 comme le
README, test de fumée, puis captures de l'app en anglais jointes au run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Les versions françaises passent dans CONTRIBUTING.fr.md et SECURITY.fr.md.
Convention mise à jour : tout texte visible passe par t() avec sa traduction.
Modèles d'issue et de pull request en anglais, le français reste accepté.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Licence et façon dont le projet a été fait en tête, capture de la démo anglaise,
section sur les traductions. Les deux versions à jour : un seul mot de passe de
partage, « arbre » plutôt que « galaxie », interface en deux langues.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Accueil prérendu en deux langues, huit pages statiques traduites avec hreflang
des deux côtés, captures de l'aide refaites dans l'app anglaise, modèles PDF
générés en français et en anglais, sitemap. Test des liens internes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
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>
- 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>
- 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>
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>
- 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>
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>
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>
Les parenthèses s'ouvrent, le rond se pose, le nom suit (700 ms). Le logo
de l'en-tête passe en SVG en ligne (tracés du logo validé, nom arrondi au
dixième). La décision « première page de la session » est prise dans le
<head> avant le premier affichage : pas de clignotement, HTML prérendu
inchangé. Rien si « réduire les animations » est activé.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Le canvas déborde sur la marge droite jusqu'au bord de l'écran (garde de 24 px)
et monte à 700 px de haut. Environ 1,7 fois plus grand en 1920 px, sans coupure
de 1024 à 1920 px ; mobile et tablette inchangés.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Cousinade : quatre questions ajoutées (qui inviter, budget, repas, activités), title
recentré sur la recherche. Comparatif : ce qui est gratuit et payant chez Geneanet et
MyHeritage, d'après leurs pages tarifs officielles au 25/09/2026. Deux-points et
« galaxie » retirés du texte des anciens guides, espaces insécables avant ? ! ; et
dans les guillemets.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
Chaque page statique liste désormais tous les guides, y compris les deux nouveaux.
Retire la déclaration Bradford et la palette cosmos de Tailwind, l'alias @fonts
de Vite et les .ttf Bradford du frontend, plus utilisés nulle part.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Nouvelle page /arbre-genealogique-a-remplir/ (point 3 de l'audit SEO) :
modèles 3 générations, 3 générations avec photos, 4 générations paysage,
5 générations en éventail et arbre dessiné, avec aperçus WebP, section
pour les remplir, renvoi vers la version en ligne et FAQ (JSON-LD).
Gabarits et script de génération Playwright dans landing/modeles/.
Entrée ajoutée au sitemap et au tableau GUIDES de la landing.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Nouvelle page statique /comment-faire-un-arbre-genealogique/ : sept étapes,
section papier, logiciel ou en ligne, place de Parenthèse, FAQ reprenant
les questions Google, JSON-LD Article, HowTo et FAQPage. Balisage aligné
sur la nouvelle DA des guides (polices, logo, theme-color). Ajout au
sitemap et au tableau GUIDES de la landing.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Les 5 pages de landing/public reprennent les tokens, typos et boutons de la
landing (fond grège, encre, accent terracotta, Newsreader + DM Sans chargées
par Google Fonts). Logo du header remplacé par /logo.svg, theme-color à
#FBFAF7. Suppression des polices Bradford de landing/public/fonts, qui
n'étaient plus référencées que par guides.css.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Textes de la landing (pastille, lede, H2 des étapes, de la démo et des guides, Pour qui)
et métadonnées og/twitter/JSON-LD sans « galaxie »
- npm run build fait le build client, un build SSR (src/entry-server.jsx, renderToString)
puis scripts/prerender.mjs injecte le HTML dans dist/index.html ; hydrateRoot côté client
- Rendu serveur sans accès window : source et isMobile posés après montage
- noscript rend visibles les blocs data-reveal sans JavaScript
- App : robots.txt en Allow pour que la meta noindex soit lue
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- 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>