Files
g9-migration/g9-migration/PHASE4-RECOLLEMENT.md
T

9.0 KiB
Raw Blame History

Phase 4 — récupération du thread supprimé

Ce fichier a deux objets : §0 = état consolidé de la Phase 4 (briques, versions, incidents, .25) ; §1-5 = rapport de récupération du thread de session supprimé (07:20 UTC).

0. État consolidé de la Phase 4 (2026-10-11)

0.1 Briques déployées sur G9 (.24) et versions épinglées

Brique Image épinglée État Watchtower
Vaultwarden (T4.1) vaultwarden/server:1.37.4 healthy, coffre importé (953 ciphers, 2FA), ADMIN_TOKEN argon2 false
Nextcloud (T4.2) nextcloud:35.0.1 (35.0.1.1 = version source) healthy, occ status installed, 8 users, 1522 fichiers (scan 0 erreur), 67 apps activées = liste source false
— MariaDB mariadb:10.11 (utf8mb4_bin, import en une transaction) up false
— Redis redis:7 up false
— Collabora (remplace OnlyOffice .25) collabora/code:26.04.5.1.1 healthy, discovery 200, wopi_url posé false
Gitea (T4.4) gitea/gitea:1.27.3 + postgres:16 healthy, 15 repos / 4 users importés, push-create actif false
Jellyfin (T4.5) jellyfin/jellyfin:10.9 (10.9.11) healthy, média par RÉFÉRENCE (/mnt/usb-media → /media:ro, aucune copie), 1 médiathèque = /media/films, Items Movie = 1 false
edge (T4.6) caddy:2 (digest f2a1290d…) healthy, HTTPS interne (CA interne), 443 seul port exposé WAN true (stateless)
Watchtower (T4.7) nickfedor/watchtower@sha256:45b54f6d… healthy, scope label-enable : dry-run scanned=2 (edge + watchtower), 14 stateful ignorés true
PhotoPrism (T4.3) — non déployée : 07d-migrate-photoprism.sh écrit/testé, exécution reportée (coût = copie 530 Go ; média servi par Jellyfin) —

0.2 Incidents rencontrés et correctifs (détail = journal.md)

  1. Collabora TLS : l'image 26.04 sert TLS par défaut (discovery http = 000) ; env extra_features/O:ssl.enable non appliqués → fix command: ["--o:ssl.enable=false"] (CMD appendu à l'entrypoint).
  2. Collabora healthcheck : image minimale (ni sh ni curl) → CMD curl = unhealthy permanent → healthcheck retiré du compose (sonde externe curl :9980/hosting/discovery).
  3. Jellyfin auth : le wizard laisse Users.EnableLocalPassword=0 → « Invalid username or password » ; fix = UPDATE sqlite + restart (hash PBKDF2-SHA512 vérifié == secret) ; API = en-tête combiné X-Emby-Authorization requis (sinon 400 « Value cannot be null »).
  4. Caddy : snippet (name) inutilisable comme adresse (« ambiguous site definition ») → import ; request_id n'est pas un directive site (validate KO) ; Caddy logue les en-têtes reçus du client, pas ceux envoyés en amont.
  5. Nextcloud / edge : le dépôt d'un second *.config.php monté n'a pas été retenu (merge array_replace_recursive + config.php déjà porteur des clés) → résolu en écrivant g9-double-run.config.php = source de vérité du kit, monté :ro : overwritehost=cloud.folzocorp.fr, overwriteprotocol=https, trusted_proxies=[192.168.1.0/24, 172.16.0.0/12], trusted_domains += cloud.folzocorp.fr.
  6. Watchtower : fork nickfedor = SCHEDULE XOR POLL, pas de --once (⇒ -R) ; notification alignée generic+http://n8n:5678/webhook/watchtower (webhook testé 200 depuis le réseau Docker ; l'edge n'écoute que 443).

0.3 Alignement proxy (TRUSTED_PROXIES)

  • Nextcloud : trusted_proxies = [192.168.1.0/24, 172.16.0.0/12] (bridge Docker de l'edge) + overwrite* https/host — preuve côté app : redirect https://cloud.folzocorp.fr/ → Location: https://cloud.folzocorp.fr/index.php/login.
  • Vaultwarden : TRUSTED_HOSTS=192.168.1.0/24,172.16.0.0/12 (même réseau de confiance).
  • Caddy : X-Forwarded-Proto/Host/Port/For posés par défaut sur tous les reverse_proxy.
  • ufw : 443/tcp = seul port exposé WAN (+ 80 redirect ACME) ; ports briques (3000/2222/3100/5678/5984/8008/8009/8080/8081/8096/9980) = ALLOW IN 192.168.1.0/24 + default deny incoming.

0.4 État du xpenology .25 (double-run G4, rien de destructif)

  • nextcloud_app, nextcloud_db, nextcloud_redis, vaultwarden-server-1, gitea relancés et up après les exports ; dumps/transitaires supprimés sur .25, pilot et G9.
  • Aucun partage, aucune donnée, aucun conteneur .25 supprimé ; transports .25→pilot = ssh 'sudo tar cz'/mysqldump en lecture seule (sshd DSM refuse rsync --server et scp).

Rapport de récupération (thread supprimé)

Session : e67f1166-d70c-42cd-a295-79513757233e (tâche Kanban 8e3e7f073a6806cd — PHASE 4) Suppression : 2026-10-11 07:20:04 UTC (trace systemd : Runner error FOREIGN KEY constraint failed, sessionId=e67f1166…) Méthode : suppression = DELETE sur sessions + cascade sur events. Les pages SQLite libérées gardent leur contenu tant qu'elles ne sont pas réallouées → caravage des pages libres de sessions.db (snapshot), reconstruction des enregistrements.

1. Ce qui a été récupéré

Élément Valeur
Snapshot de travail snap1 pris à 08:20:34 UTC (1 h après la suppression)
Pages contenant l'id de session 21 232
Texte imprimable ≥ 400 caractères 34 227 blocs = 47,9 Mo
Objets JSON payload reconstitués 51 420 = 34,68 Mo
Entrées d'index events (session_id, seq / event_type) 79 830 → 37 821 seq, 42 009 event_type, plage seq 5 → 158 799
Tours de conversation reconstitués 130 (129 assistant + 3 user côté rôles)
Événements réinsérés dans sessions.db 64 657 (33,85 Mo de payload)
Appels d'outils avec arguments intacts 31 998
Résultats / sorties d'outils 124 / 275

2. Ce qui est perdu (non inventé)

  • ~75 % des événements : les pages leaf/overflow ont été réallouées et zérées par SQLite après la suppression (15 951 pages contenaient encore l'id de session mais avec leur tableau de cellules remis à zéro).
  • La prose du fil (messages de l'assistant) est récupérée en fragments dans le désordre : les deltas de streaming sont stockés dans des pages distinctes, l'ordre d'origine n'a pas pu être reconstitué. Les 130 messages insérés contiennent donc des fragments réels, recollés dans l'ordre des pages (ordre d'allocation ≈ ordre chronologique), pas un texte propre.
  • Presque tous les messages utilisateur sont perdus (payloads courts, pages détruites) : 3 rôles user identifiés, sans contenu.
  • Volume attendu ≈ 158 800 événements / 80–110 Mo de payload → ≈ 35 % récupéré.

3. Où sont les artefacts

Fichier Contenu
/home/folzo/openfox/_recover/snap1/ copie octet-pour-octet d'origine (sessions.db, -wal, -shm)
/home/folzo/openfox/_recover/orig.sha256 sha256 des fichiers d'origine
/home/folzo/openfox/_recover/snap2/ + snap2.sha256 état immédiatement avant la réinsertion (point de rollback)
/home/folzo/openfox/_recover/phase4_json.jsonl 51 420 payloads JSON bruts (+ page, offset)
/home/folzo/openfox/_recover/phase4_index.jsonl 79 830 entrées d'index (rowid, seq, event_type)
/home/folzo/openfox/_recover/phase4_events.jsonl flux d'événements synthétisé
g9-migration/PHASE4-RECOLLEMENT.md §5 journal des actions récupérées

4. Rollback

Chirurgical (recommandé, ne touche à rien d'autre) :

DELETE FROM events  WHERE session_id='e67f1166-d70c-42cd-a295-79513757233e';
DELETE FROM sessions WHERE id='e67f1166-d70c-42cd-a295-79513757233e';

Restauration à l'état pré-réinsertion :

systemctl stop openfox
cp /home/folzo/openfox/_recover/snap2/sessions.db{,-wal,-shm} /home/folzo/.local/share/openfox/
sha256sum -c /home/folzo/openfox/_recover/snap2.sha256
systemctl start openfox

PRAGMA integrity_check = ok avant et après réinsertion. Les fichiers d'origine n'ont jamais été modifiés en écriture directe : la réinsertion est passée par SQLite (WAL), et snap1 reste la copie de l'état post-suppression.

5. Journal des actions récupérées

Le journal des 32 409 actions récupérées (appels d'outils + arguments intacts, résultats, sorties) n'est pas versionné ici — il duplique les artefacts et concerne la base de sessions OpenFox, pas le kit G9. Consultable / rejouable :

Artefact Contenu
/home/folzo/openfox/_recover/phase4_actions.md journal brut complet (32 409 lignes, page-ordre)
/home/folzo/openfox/_recover/phase4_actions_curated.md version filtrée/dédupliquée (758 lignes)
/home/folzo/openfox/_recover/phase4_json.jsonl 51 420 payloads JSON (+ page, offset)
/home/folzo/openfox/_recover/phase4_events.jsonl flux d'événements réinsérés dans la base

Reprise du travail Phase 4 : la tâche Kanban 8e3e7f073a6806cd est toujours bindée à la session e67f1166… et le runner n'a jamais cessé d'écrire (journal 09:18 → 10:13, commits a1864c6, scripts 07c/07d) — c'est la source operative, pas le fil recoveré.