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>
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_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>
À 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>
Un reseau mobile qui decroche laissait l'app en chargement pour toujours.
30 s par appel, 5 min pour un envoi de fichier (corps de plus de 100 Ko),
3 min pour un import GEDCOM. Le message dit que le serveur ne repond pas.
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>
- 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>
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>
Naissance, unions et deces en grands reperes (direction A2 choisie par Patch le 16/10),
evenements importes plus petits, famille proche tiree de l'arbre en retrait, sources
repliees. Evenements charges a l'ouverture de l'onglet via GET /persons/:id/life,
donnees propres a la demo pour Robert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
En mode édition, un administrateur glisse une personne à l'horizontale
parmi ses frères et soeurs pour changer leur ordre. Pour chaque place visée,
le vrai placement est recalculé : la personne soulevée suit le pointeur,
les autres branches glissent vers leur place avec un ressort, et rien ne
saute au lâcher. Appui long au doigt, Échap ou un deuxième doigt pour
annuler, mouvement réduit respecté. La fiche propose aussi deux flèches
(Déplacer à gauche, Déplacer à droite) avec la même animation. L'ordre est
appliqué tout de suite puis enregistré ; en cas d'échec l'arbre revient
en arrière et un message le dit.
Idée de départ : PR #60 de py5932 (glisser-déposer des personnes).
Co-Authored-By: py5932 <py.dequidt@gmail.com>
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>
- Les visages affichent leur miniature ronde au lieu de l'icône. Chargées
quand elles entrent dans la liste (IntersectionObserver), trois requêtes
au plus en parallèle, une requête par visage, cache le temps du panneau.
Les URL blob sont révoquées au démontage. En attente ou sans vignette : un
rond neutre.
- La personne déjà associée à la fiche est marquée « Associée » (lecture
réservée aux administrateurs, via la nouvelle route de lien).
- Le cadre pointillé vide disparaît : l'aperçu n'apparaît qu'une fois un
visage choisi, avec la photo carrée arrondie des fiches. Le bouton principal
reste désactivé tant que rien n'est choisi.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Onglet Avancé des paramètres de l'arbre (admin) : une action « Rétablir la
disposition automatique », visible seulement s'il existe des positions
manuelles, avec confirmation. Elle appelle la route admin
/trees/:id/layout/reset puis recharge le graphe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L'API ne renvoie plus les adresses brutes d'Immich à un administrateur
d'arbre : la liste IMMICH_ALLOWED_API_URLS devient des instances nommées
(« Libellé=https://adresse », libellé facultatif, nom d'hôte par défaut).
Chaque instance a un identifiant opaque dérivé de son adresse, donc stable
même si l'opérateur réordonne la liste. Le PUT accepte cet identifiant et
stocke l'adresse canonique de la liste. Deux instances au même nom d'hôte
sans libellé sont refusées au démarrage avec un avertissement.
Les variables d'exemple documentent le format, la liste reste compatible
avec les adresses seules.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L'association remplaçait et supprimait le portrait en place sans rien
demander. Le serveur refuse maintenant le remplacement d'un portrait
existant (409 avatar_exists), quelle que soit son origine, tant que la
requête ne porte pas replaceAvatar ; le panneau Immich transforme ce
refus en demande de confirmation avant de rejouer la requête. Sans
vignette Immich, l'association ne touche pas au portrait et aucune
confirmation n'est demandée.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Nouvelle table tree_immich_configs (adresse + clé d'API chiffrée AES-256-GCM,
clé dérivée de JWT_SECRET) et routes GET/PUT/DELETE /trees/:id/immich/config
réservées aux administrateurs de l'arbre ; journal d'audit sans secret
(adresse et « clé changée » uniquement).
- Fin des variables d'env IMMICH_ENABLED / IMMICH_API_URL / IMMICH_API_KEY :
l'adresse se choisit parmi IMMICH_ALLOWED_API_URLS, la liste établie par
l'opérateur du serveur. Elle filtre l'enregistrement ET chaque requête :
retirer une adresse coupe aussitôt les connexions qui l'utilisent.
- Changer d'instance exige une nouvelle clé : l'ancienne est écrasée et ne
voyage jamais vers le nouveau serveur.
- Le désassignement reste possible sans connexion : purement local, il nettoie
association et portrait stocké même après suppression de la connexion ; le
panneau affiche « Retirer l'association » dans tous les états.
- Onglet Immich dans Paramètres de l'arbre : menu des instances autorisées,
test de connexion, suppression avec confirmation ; i18n anglais des nouveaux
messages.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Colonne persons.immichPersonId (schéma + migration 20261012_001) et
exposition dans le graphe pour l'afficher côté fiche.
- Client Immich (src/lib/immich.ts) sur le contrat OpenAPI v3.1.0 :
ping, /api/people paginé, vignette par personne ; erreurs distinctes
entre injoignable, clé refusée et introuvable, identifiants validés
comme UUID v4.
- Routes /trees/:id/immich/* (status, people, thumbnail, assign,
unassign), réservées aux administrateurs de l'arbre ; l'adresse et la
clé d'Immich ne quittent jamais le backend.
- La vignette passe par le pipeline des portraits (type lu dans les
octets, métadonnées retirées, quota de l'arbre) : le fichier est écrit
avant la transaction (personne + journal immich_assign) et l'ancien
portrait est supprimé après ; un échec du nettoyage est journalisé
sans faire échouer la requête. Le désassignement retire le portrait
seulement s'il vient d'Immich (préfixe immich-) et préserve un
portrait envoyé à la main.
- Côté front : bouton « Depuis Immich » sur la fiche en édition, panneau
de sélection avec aperçu et retrait de l'association, traductions
anglaises, messages d'erreur distincts.
- Tests : 16 tests backend (succès, 400/401/403/404/413/502/503, quota,
échec de transaction, préservation du portrait manuel, serveur
désactivé) et le mapping immichPersonId côté front.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
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>
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>
- 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>
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>
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>
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>