Commit Graph
40 Commits
Author SHA1 Message Date
IliesAllaliandClaude Opus 5.5 dd738c483a Import GEDCOM : vraies dates, toutes les notes
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>
2026-10-16 22:12:16 +02:00
IliesAllaliandClaude Opus 5.5 bca0543803 Import GEDCOM : lieu lisible, sans colonnes vides ni codes
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>
2026-10-16 20:20:17 +02:00
IliesAllaliandClaude Opus 5.5 897ada2665 Import GEDCOM : tous les fichiers cités deviennent des souvenirs
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>
2026-10-16 19:55:56 +02:00
IliesAllali 12ccb520f5 Merge remote-tracking branch 'origin/main' into pr60-fix
# Conflicts:
#	frontend/src/components/PersonCard.jsx
#	frontend/src/i18n/en/fiche.js
2026-10-16 19:27:11 +02:00
IliesAllaliandClaude Opus 5.5 8556d32bce API : l'ordre d'une fratrie s'applique aux deux liens de l'union
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>
2026-10-16 19:08:05 +02:00
IliesAllaliandClaude Opus 5.5 588ac0c4e9 API : un nouvel enfant se place après ses frères et soeurs
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>
2026-10-16 18:53:23 +02:00
IliesAllaliandClaude Opus 5.5 1caa090efd API : réordonner une fratrie en une transaction
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>
2026-10-16 18:51:37 +02:00
IliesAllaliandClaude Opus 5.5 8574dfed9e Retour au placement automatique : abandon du placement libre
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>
2026-10-16 18:46:28 +02:00
IliesAllaliandClaude Opus 5.5 d93710a00d Tests Immich : la suppression d'une personne efface aussi son lien Immich
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:16:16 +02:00
IliesAllaliandClaude Opus 5.5 7f159d5111 Immich : route admin pour lire le lien d'une fiche
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>
2026-10-16 18:13:26 +02:00
IliesAllaliandClaude Opus 5.5 f37fc329ba Immich : lectures bornées, erreurs de corps en 503, lien retiré avec le portrait
- 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>
2026-10-16 18:12:21 +02:00
IliesAllaliandClaude Opus 5.5 c8df8df937 Immich : une clé illisible n'est plus signalée comme configurée
Le résumé ne lisait que l'adresse : après un changement de JWT_SECRET, l'onglet
affichait « Configurée » alors que chaque appel échouait. Le résumé déchiffre
désormais la clé (configured: false, keyNeedsReentry: true, instance gardée pour
préremplir le menu). L'onglet Immich affiche « Clé à ressaisir », garde le
bouton de suppression, et un PUT sans clé est refusé tant que la clé en place
ne se lit pas. Tests : résumé avec clé illisible, refus de conserver la clé.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:11:17 +02:00
IliesAllaliandClaude Opus 5.5 d17cee20df feat(arbre): rétablir la disposition automatique
Route admin POST /trees/:id/layout/reset : remet layoutX/layoutY à null
pour toutes les personnes de l'arbre, dans une transaction, avec une
entrée de journal (tree_layout_reset). Documentée dans l'OpenAPI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:09:11 +02:00
IliesAllaliandClaude Opus 5.5 265b3b30a0 Immich : les instances se choisissent par leur nom, jamais par leur adresse
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>
2026-10-16 18:08:54 +02:00
IliesAllaliandClaude Opus 5.5 420bda5e38 fix(arbre): bornes des positions et conflit de relecture
- Les coordonnées de disposition sont bornées à ±1 000 000 (PATCH personne,
  modification en session de contribution, OpenAPI).
- Un déplacement par le propriétaire ne met plus en conflit les
  contributions en attente sur la même personne : layoutX/layoutY sont
  exclus de la comparaison de conflit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:08:50 +02:00
IliesAllaliandClaude Opus 5.5 fbcac3afd4 Tests Immich : liste d'instances vide explicite, indépendante du .env local
Le test « aucune instance autorisée » héritait de IMMICH_ALLOWED_API_URLS du
backend/.env de développement et échouait sur une machine qui le renseigne.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:05:51 +02:00
IliesAllaliandClaude Opus 5.5 63b9761ec4 Immich : garder le chemin de l'instance, comparer origine et chemin
new URL(chemin, base) effaçait le sous-chemin d'une instance derrière un
proxy (https://hote/immich devenait https://hote/api/...). L'adresse se
concatène désormais. Une adresse avec identifiants, requête ou fragment est
refusée, et le client reçoit l'adresse autorisée normalisée, jamais la
valeur brute de la base. Tests : sous-chemin, domaine préfixe, userinfo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:05:50 +02:00
IliesAllaliandClaude Opus 5.5 44dd203069 Immich : ne jamais suivre une redirection avec la clé d'API
fetch suivait les redirections par défaut : une instance autorisée qui
répond 3xx pouvait recevoir x-api-key sur une autre adresse. Les appels
passent en redirect: 'error' (remontée en immich_unreachable), avec un test
qui le prouve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:04:50 +02:00
py5932 43441f31e1 Ajout de la fonctionnalité drag and drop 2026-10-14 23:25:11 +02:00
Mistral Vibe cf946be617 Immich : un portrait déposé à la main remplace aussi le lien Immich
POST /trees/:id/persons/:personId/avatar lit immichPersonId de la personne et le
remet à null quand une association existe ; l'entrée d'audit person_avatar_updated
trace le retrait via payloadJson immichLinkRemoved. Sans cela, l'association
survivait invisible en base après remplacement du portrait par un fichier.

Test : l'envoi d'un fichier sur un portrait Immich efface l'association (échouait
avant ce fix : immichPersonId absent de l'update) ; sans association, le champ
n'est pas touché.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-10-13 19:08:52 +02:00
Mistral Vibe 310f2fb597 Immich : publier l'origine du portrait dans le graphe, pas l'identifiant
- avatarFromImmich (fichier préfixé « immich- ») remplace immichPersonId
  côté front : le panneau ne propose le retrait que si le portrait vient
  d'Immich, et le bouton de la fiche retrouve son libellé distinctif
- helper isImmichAvatarPath partagé entre le payload du graphe et la route
  unassign, qui testaient le préfixe chacun de son côté
- tests : origine du portrait dans le payload (vrai/faux/null)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-10-13 17:47:37 +02:00
Mistral Vibe 8d36a08b11 Immich : retirer l'identifiant Immich du graphe envoyé aux visiteurs
- buildGraphPayload ne mappe plus immichPersonId ; test qu'il n'apparaît pas
- le front ne propage plus le champ (graphAdapter, mockData et son test)
- le panneau Immich propose le retrait d'association en permanence, sans lire
  le champ ; unassign sans association ne fait rien : pas d'écriture, pas
  d'entrée d'audit (test du no-op), et le bouton de la fiche garde un
  libellé fixe

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-10-13 17:39:23 +02:00
Mistral Vibe 0bda88920d Immich : demander confirmation avant de remplacer un portrait existant
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>
2026-10-13 15:58:32 +02:00
Mistral Vibe a3386824d3 Immich par arbre : connexion propre à chaque arbre, instances autorisées par l'opérateur
- 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>
2026-10-13 14:04:45 +02:00
Mistral Vibe c703a34165 Immich : vérifier l'existence d'une personne avant l'association
Le 404 de la vignette ne distingue pas une personne inexistante d'une
vignette manquante : l'association pouvait donc être enregistrée pour
une personne Immich qui n'existe pas.

- ImmichClient.getPerson() : GET /api/people/{id} (200 | 404), qui
  établit l'existence de la personne et annonce sa vignette.
- La route d'association rejette une personne inexistante (404
  immich_person_not_found) ; un refus d'authentification (502) ou une
  erreur serveur (503) n'est jamais pris pour une absence.
- La vignette n'est demandée que si Immich en annonce une ; une vignette
  manquante chez une personne existante associe toujours sans portrait.
- Tests : personne inexistante refusée sans toucher base, audit ni
  fichiers ; vignette disparue entre les deux appels ; échec
  d'authentification pendant l'association sans changement en base.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-10-12 13:40:38 +02:00
Mistral Vibe 47083ec274 Merge upstream/main : premières photos, Docker tout-en-un, dépendances
Reprise de upstream (IliesAllali/main) dans la branche Immich. Seul
conflit : l'import des icônes dans PersonCard.jsx — les deux lignes
sont gardées (ImagePlus pour le portrait vide de « Premières photos »,
Sparkles pour le bouton « Depuis Immich »). Tout le reste fusionne
automatiquement ; l'intégration Immich (routes, exports de media.ts,
mapping immichPersonId, panneau) est inchangée.

Vérifié après la fusion : tests Immich (16), tests backend focalisés
gedcom-photos (4), build tsc, eslint et les 107 tests du front. Seul
« rate-limits login endpoint » dépasse son délai de 5 s, déjà le cas
sur main avant la fusion (bcrypt, machine lente).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-10-12 12:18:41 +02:00
Mistral Vibe 378071bf13 Intégration Immich : associer un visage à une personne de l'arbre
- 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>
2026-10-12 11:53:12 +02:00
IliesAllaliandClaude Opus 5.5 83443ac9dc Premières photos : import dès la création, photos du logiciel retrouvées, premiers visages
- Création d'arbre : « J'ai déjà un arbre » importe le .ged sans fiche « vous » en double.
- Import GEDCOM : lit les photos citées (OBJE / FILE, en ligne ou par renvoi, _PRIM d'abord)
  et renvoie leur chemin ; rien n'est gardé côté serveur.
- Fenêtre « Il manque les visages » après un import : dossier des photos apparié par nom de
  fichier, cinq visages à demander (famille de « Moi », sinon les plus jeunes).
- Portrait vide chez le propriétaire : cadre cliquable sur la fiche hors édition, « + photo »
  au survol sur l'arbre.
- Photos de plus de 5 Mo réduites à 2000 px avant l'envoi ; portraits à 120 envois par minute.
- PostHog : gedcom_imported, portraits_bulk_placed, portrait_added (effectifs arrondis).
- Corrigé : une union à un seul parent connu relie ses enfants à ce parent, sous un seul
  « Inconnu », au lieu de les laisser sans lien.
- Corrigé : réimporter un GEDCOM reprend les personnes, unions et liens déjà présents au lieu
  de tout doubler.

Recette locale (vraie API, vraie base) : 29/29 sur le parcours photos, 47/47 sur la recette
de non-régression des parcours. Tests 123 serveur, 107 app, lint et build propres.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:54:56 +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 f6fb6540e7 API : @fastify/cors 11.3.0, méthodes annoncées gardées
Reprend la PR Dependabot #32. Rupture de la 11.0.0 : la pré-vérification CORS n'annonce plus par défaut que GET, HEAD et POST, un navigateur d'une autre origine aurait refusé les PUT, PATCH et DELETE de l'API. La liste d'avant est maintenant écrite dans app.ts, et un test vérifie la réponse à un OPTIONS d'une origine autorisée (il échoue sans la ligne). Option origin inchangée. Les ajouts de la 11.x (logLevel du préflight, cors par route dans config.cors) ne sont pas utilisés. 113 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:13:07 +02:00
IliesAllaliandClaude Opus 5.5 91c93ddfa1 Tests de l'audit 1.0 : fichiers, annotations, jetons, mot de passe de partage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:57:27 +02:00
IliesAllaliandClaude Opus 5.5 34afa51866 Test de l'apostrophe : délai porté à 30 s (bcrypt lent en CI)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 19:18:43 +02:00
IliesAllaliandClaude Opus 5.5 84d0637ab7 Mot de passe de partage : apostrophe de téléphone et espace finale acceptées
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 19:05:48 +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 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 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