Sur une photo ou une vidéo, on ajoute les personnes de l'arbre qui y figurent et, sur une photo,
on touche leur visage pour poser un point. Le souvenir apparaît aussi sur la fiche de chaque
personne identifiée (« Avec Odette »), un prénom ouvre sa fiche et recentre l'arbre.
L'administrateur enregistre directement. La famille propose, l'administrateur relit dans
« Propositions à relire ». Suppression d'une personne ou d'un souvenir : identifications retirées.
Table media_person_tags (migration additive), route PUT /trees/:id/media/:mediaId/people.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Une photo HEIC (marques heic, heix, mif1, msf1, heim, heis) était typée video/mp4. Elle est maintenant image/heic,
et AVIF image/avif. Elles restent refusées à l'envoi (invalid_media_mime_type), comme avant : sharp ne décode
que l'AVIF en entrée HEIF, pas le HEVC des HEIC. La marque hevc n'est une photo que si l'envoi se déclare photo,
pour qu'une vidéo HEVC en MP4 reste acceptée. Les vignettes Immich ne sont servies que pour les types image
autorisés.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Suppression de compte : un compte qui avait un mot de passe mais qui est relié à OIDC, sur une instance avec
PASSWORD_LOGIN=false, ne pouvait plus se supprimer (le mot de passe ne sert plus). Il se confirme désormais par
son email après une connexion récente, comme un compte né du fournisseur. /me et l'échange OIDC renvoient
hasPassword=false dans ce cas, pour que l'écran demande l'email : aucun changement d'interface.
Identité OIDC : un email vérifié déjà relié à une autre identité (un autre sujet) n'est plus repris par un
nouveau sujet (oidc_email_taken). La connexion d'une identité déjà reliée reste faite par émetteur et sujet,
jamais par email.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
GEDCOM 5.5.1 n'admet que M, F et U ; SEX X n'existe qu'en 7.0, et l'export écrivait X sous un en-tête 5.5.1.
Un sexe « autre » s'écrit maintenant U. L'import lit toujours X comme avant.
Conséquence connue : à l'aller-retour, « autre » revient comme « non précisé » (5.5.1 n'a pas de valeur pour
« autre »). Décision à trancher, voir la description de la PR.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Use Immich previews for photos, enforce the image download cap while streaming,
reuse design tokens and remove unused translations. Add regression coverage.
Signed-off-by: Askrosm <155456680+Askrosm@users.noreply.github.com>
- OIDC : une identité n'est plus reliée automatiquement à un compte existant qui a un mot de passe.
L'inscription ne vérifie pas l'adresse, un tiers aurait pu créer ce compte avec l'email de la victime et lire
ce qu'elle y met ensuite. Refus avec oidc_email_taken et un message clair (FR, EN). Trouvé par la relecture
de sécurité avant la release.
- Tests OIDC : chaque connexion simulée a sa propre adresse (limite de 20 appels par minute et par adresse).
- CHANGELOG 1.2.0, OIDC marqué expérimental dans les deux README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET et OIDC_REDIRECT_URI
ajoutent « Se connecter avec … » à l'écran de connexion. Tout le protocole
passe par openid-client 6 : découverte, PKCE S256, state et nonce, échange
du code, vérification de l'ID token (signature, émetteur, audience, dates).
State, nonce et vérificateur PKCE vivent dans un cookie signé, httpOnly,
SameSite=Lax, qui lie le retour au navigateur qui a commencé la connexion.
Le compte est trouvé par (émetteur, sub), sinon relié par email vérifié,
sinon créé sans mot de passe si ALLOW_REGISTRATION le permet (instance
vide comprise). Retour vers l'app par un jeton de passage de 60 s, à usage
unique, dans le fragment, échangé contre une session.
PASSWORD_LOGIN=false retire les mots de passe Parenthèse. Un compte sans
mot de passe se supprime en retapant son email, dans les 15 minutes qui
suivent une connexion. Code OIDC masqué dans les journaux.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Sexe : Femme, Homme, Autre, Non précisé. Autre est enregistré « other »,
refusé en 400 comme toute valeur inconnue, et prend les formes neutres ou
doubles pour nommer un lien.
- GEDCOM : import SEX X (GEDCOM 7) → other, SEX U → non précisé ; export
other → SEX X, non précisé sans ligne SEX. Aller-retour testé.
- « Ajouter quelqu'un » : « Je ne connais pas son prénom » sort de la colonne
Prénom et tient sur une ligne (sous les deux champs sur ordinateur, sous
Prénom sur téléphone) ; les quatre choix du sexe tiennent sur une ligne.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Champ Sexe (femme, homme, non précisé) dans la fiche en modification, à l'ajout
d'une personne et dans une proposition de la famille ; relu « Sexe » dans les
propositions à relire.
- Valeurs ramenées à male / female / null à l'écriture et à la lecture (anciennes
valeurs M/F relues sans migration), valeur inconnue refusée (400). Export GEDCOM
inchangé dans sa forme.
- Lien au survol genré quand le sexe est connu (Père, Tante, Cousine germaine,
Belle-mère…), forme double sinon. Nommage déplacé dans utils/kinship : une
fonction par langue reçoit le chemin complet (pas, personnes, sexe, année de
naissance), pour brancher d'autres langues.
- Anglais : beau-parent distingué de parent par alliance selon l'ordre du chemin
(Stepmother / Mother-in-law).
- Propositions à relire : le nom de la personne modifiée vient de l'avant lu en
base quand la modification ne porte que le champ changé.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
À false, POST /auth/register répond 403 registration_closed et l'app ne
propose plus de créer un compte (accueil, connexion, porte d'un arbre
partagé, menu du visiteur). Les comptes existants se connectent et créent
leurs arbres, le partage par lien et mot de passe ne change pas.
Une instance sans aucun compte accepte quand même le premier, sous un
verrou de transaction PostgreSQL (deux inscriptions simultanées n'en
créent qu'un). GET /auth/options expose l'état à l'écran d'accueil.
Défaut true : rien ne change pour les instances existantes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Le cadre suivait le format de la photo : une photo couchee donnait toujours un
cadre couche. Le recadrage propose maintenant les cinq formes de l'arbre, en
dessin, et la forme choisie est gardee avec le cadrage (avatarCrop.shape, sans
migration). L'arbre la respecte ; sans choix, rien ne change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Onze connexions avec vérification bcrypt dépassaient parfois 5 s sur la CI : quatre échecs le 18/10 sans lien avec les changements.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Un fichier abime pouvait marier une personne a elle-meme ou faire de
quelqu'un son propre ancetre, ce que l'API refuse partout ailleurs. Le
controle se fait en memoire pendant l'import (les validateurs relisent tout
l'arbre a chaque lien), et la reponse compte les relations ecartees
(relationsSkipped).
Premier test de la route d'import.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
La purge des visites de plus d'un an ne passait qu'a l'ouverture de l'onglet
Visites par un administrateur : un arbre jamais consulte gardait tout. Elle
passe aussi a l'enregistrement d'une visite, au plus une fois par heure, pour
tous les arbres.
A la suppression d'un compte, ses visites d'autres arbres gardaient son
identifiant dans la cle du visiteur : elles restent comptees, sous une cle
anonyme.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Une erreur au milieu laissait un etat partiel, et un nouvel essai du client
recreait des doublons.
- Lot d'annotations : creations, modifications, suppressions et trace.
- Moments : session de contribution, moment, souvenirs rattaches et trace ;
modification et suppression d'un moment avec ses souvenirs.
- Reordonnancement des souvenirs d'une personne.
- La famille ne rattache a son moment que des souvenirs libres : elle ne
detache plus un souvenir du moment d'un administrateur.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Un fichier dont chaque fiche cite une note ou une source enorme faisait relire
ce texte pour chaque personne : environ 35 min de calcul pour 20 000 fiches,
0,1 s maintenant (memo par noeud, pour la duree de l'import).
- La lecture des medias ne descend que dans les branches qui menent a un
fichier, avec un budget par personne et une profondeur bornee.
- Les niveaux au-dela de 99 (limite de la norme) sont ignores : une chaine de
sources faisait deborder la pile.
- Les notes ne sont calculees que pour une personne creee, pas reutilisee.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Le cadrage (centre et zoom) est stocké dans Person.avatarCrop (JSON, nullable),
l'original reste sur disque et le cadrage s'applique à l'affichage (canevas et fiche).
Route PUT /trees/:id/persons/:personId/avatar/crop, réservée aux administrateurs.
La suppression et le nouvel envoi remettent le cadrage à zéro.
Migration additive (colonne nullable, sans défaut), testée sur base vide et sur base avec données.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Un administrateur, en mode modification, peut modifier un souvenir depuis la visionneuse : crayon à droite du titre (visible au survol sur ordinateur, toujours visible sur écran tactile), formulaire Titre et Moment de sa vie, texte de la citation réécrit dans caption et dans le fichier citation.txt.
Route PATCH /trees/:id/persons/:personId/media/:mediaId, réservée aux administrateurs. Pas de migration : la date vient du moment de vie rattaché. La légende séparée n'existe pas en base et n'est pas ajoutée.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
- Nom de famille facultatif : une personne garde au moins un prénom ou un nom
(API, contributions, fiche, formulaire). Contributions : seule une personne
sans aucun nom est ignorée.
- Case « Je ne connais pas son prénom » visible seulement si le prénom est vide
(ou cochée), placée sous le champ Prénom.
- Panneau d'ajout : sans sur-titres en capitales.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
- Backend : prénom du compte facultatif à l'inscription (colonne users.firstName,
migration additive), renvoyé à l'inscription, à la connexion et sur GET /auth/me
- Accueil sans session : deux choix (J'ai reçu un lien, Se connecter) et
Créer mon arbre en lien, à la place de la démo (variante B validée)
- Porte : mot de passe puis prénom facultatif pour un nouveau venu ; compte
connecté non rattaché : bandeau avec son prénom, sans champ prénom, et
« Ce n'est pas mon compte » (déconnexion, retour à la porte du même arbre)
- Sur-titre « Arbre partagé » retiré de la porte
- Compte déjà rattaché : inchangé, la racine ouvre l'arbre directement
Vérifié : vitest front 154/154, back 228/228 (sans .env local, le test CORS
attend localhost:5173), tsc back, eslint front, vite build, landing test et build.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
- Prénom inconnu : case « Je ne connais pas son prénom » à l'ajout et en
modification. Enregistré comme prénom vide, affiché « Prénom inconnu »
en italique (arbre, fiche, recherche). Pas de migration.
- Export GEDCOM : « 1 NAME /Nom/ » sans prénom. Import : prénom absent
= vide (au lieu de « ? »).
- Cliquer une personne pendant un ajout ferme le panneau d'ajout ; sa
saisie reste en mémoire comme à la fermeture par la croix.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
- API : nickname accepté à la création, à la modification et dans les
propositions de contribution (trim, vide = null, 120 caractères max)
- Mode direct et circuit des contributions : même validation, avant/après
- Édition et ajout : champ « Surnom » facultatif
- Arbre : surnom en italique sous le nom, coupé avec … au-delà de 150 px
- Recherche : trouve une personne par son surnom (libellé « Surnom »)
- Démo : surnoms sur Marie et Robert
Vérifié : lint, tests (front 159, back 224), builds (front, back tsc, landing).
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
- Champ de date de la fiche et du formulaire « Ajouter quelqu'un » : une annee seule
(1950) ou une date complete (12/03/1950), une aide si le texte n'en est pas une.
L'annee seule s'affiche « 1950 » et non plus « 1 janvier 1950 ».
- Statut « Decede(e) » sans date : persons.isDeceased (migration additive), « 1908–? »
sous le portrait, « Date inconnue » dans la fiche, en bas de la frise. Import de
« 1 DEAT Y », export en « 1 DEAT Y ». Une date de deces retire le drapeau.
- Parents : plus de « (null) » quand l'union n'a pas de type.
Closes#77
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Un moment peut porter plusieurs souvenirs de tout type (photo, video, enregistrement,
acte en PDF) : media_items.lifeEventId, reprise de l'ancienne colonne mediaId.
- Naissance, mariage et deces se completent depuis la frise : documents, source, note
(la date et le lieu restent dans Infos).
- La famille propose un moment par le lien de partage : il attend la relecture, avec
ses fichiers dans la meme proposition, et apparait une fois accepte.
- Fiche : Ajouter un fichier, Choisir parmi ses souvenirs, prenom du contributeur,
textes qui expliquent ce qui se passe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Un bouton « Ajouter un moment » pour les administrateurs, une fiche courte (quoi, quand,
environ, ou, une photo), date exacte, fin, source et note sous « Plus de details ».
La photo devient un souvenir de la personne, rattache au moment (life_events.mediaId,
migration additive). Toucher un moment l'ouvre pour le modifier ou le supprimer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sinon « vers 1879 » restait colle a la date saisie ensuite, et l'export l'aurait ecrite.
Personne, union, et voie contribution.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L'export rend ce que l'import lit : dates qualifiees (ABT, EST, BET ... AND, FROM ... TO)
ou texte d'origine, lieu de deces, surnom, tous les evenements de la personne et du
couple avec lieu, notes et sources, lieu du mariage, PEDI adopted. Test aller-retour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /trees/:id/persons/:personId/life rend la précision des dates, le lieu
de décès, le surnom, les unions avec leur lieu de mariage, et les
événements de la personne et de ses couples. Chargée à l'ouverture de la
fiche, pas dans le graphe. Les droits de lecture du graphe sont factorisés
(resolveReadAccess) et servent aux deux. Supprimer une personne supprime
aussi ses événements et ceux de ses unions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nouvelle table life_events (baptême, résidence, métiers, études, service
militaire, inhumation, divorce, événements libres…) avec date, précision,
lieu, description, notes et sources. Personne : précision et borne des
dates de naissance et de décès, lieu de décès, surnom. Union : lieu et
précision du mariage. Naissance, décès et mariage gardent leur date et leur
lieu sur la personne ou l'union ; leur ligne d'événement ne porte que les
sources et les notes. Migration additive.
L'import lit tous ces événements (balises de la norme, variantes Gramps,
Heredis, RootsMagic), les adresses complètes, et les adoptions déclarées
par PEDI. Une personne ou une union déjà présente ne reçoit rien en double.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dates : « vers », « avant », « après », « entre … et … », dates juliennes,
calendrier républicain converti en grégorien, doubles années (1700/01).
« BET 1794 AND 1796 » ou « @#DFRENCH R@ 18 BRUM 8 » étaient perdues, « ABT
1900 » devient au moins 1900. La précision est déjà lue pour la suite.
Notes : notes partagées (« 1 NOTE @N1@ »), plusieurs notes, RTF nettoyé. Le
lecteur garde la valeur brute de chaque ligne : une note coupée en CONC se
recolle avec ses espaces (« pendant trente-cinq ans », plus « pendanttrente »).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Heredis remplit toutes les colonnes de son format de lieu, même vides, avec
le code INSEE (« La Roche-sur-Yon,85191,Vendée,Pays de la Loire,France, »).
Le lieu de naissance importé garde les noms seulement, séparés par « , »,
sans case vide, code INSEE ou postal, ni répétition. Un lieu déjà propre
ne change pas.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
En plus du portrait, l'import renvoie mediaRefs : les fichiers cités pour
chaque personne créée, où qu'ils soient accrochés (sous la personne, un
événement, une source citée, la fiche de la source, ou la famille pour les
actes de mariage), avec leur titre et leur source. Comme Gramps : adresses
web écartées, un fichier cité deux fois gardé une fois. Particularités
gérées : titre dans la note (Heredis, RTF compris), _PHOTO pour le portrait
(Family Tree Maker), chemins file:// (GEDCOM 7). Pour #59.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L'arbre ne montre qu'un lien par enfant et par union ; le lien vers l'autre
parent de la même union reçoit le même ordre, pour que les deux restent
d'accord.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sans ordre fourni, un lien parent-enfant créé (route, contribution, import
GEDCOM) prend l'ordre suivant celui de la fratrie, pour qu'un enfant ajouté
après un réordonnancement ne passe pas devant les autres.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PUT /trees/:id/links/order réécrit le displayOrder des liens parent-enfant
d'une fratrie, dans l'ordre reçu. Administrateurs seulement ; chaque lien
doit appartenir à l'arbre et à son enfant, et les enfants partager au moins
un parent. Journalisé (children_reordered).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Le mainteneur préfère un réordonnancement des frères et soeurs au placement
libre (coordonnées enregistrées). Ce commit annule le glisser libre, ses
corrections, la migration des coordonnées et le bouton de remise à zéro ;
le réordonnancement arrive dans les commits suivants.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Le sélecteur doit marquer la personne Immich déjà associée. L'identifiant ne
figure pas dans le graphe public : GET /trees/:id/immich/links/:personId le
renvoie aux seuls administrateurs de l'arbre.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Vignette lue en flux : au-delà de 5 Mo (ou sans taille annoncée), la lecture
s'arrête sans charger le reste.
- Vignette servie seulement si les octets sont une image, avec
X-Content-Type-Options: nosniff (plus de repli sur image/jpeg).
- Liste des personnes : délai global de 30 s sur toutes les pages.
- Corps JSON illisible ou flux interrompu : 503 immich_unreachable, au lieu
d'une erreur serveur.
- Retirer le portrait à la main (DELETE avatar) ou supprimer une personne
efface aussi son identifiant Immich, sinon l'association reste invisible.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>