From aa206a1787b9bfdf7e7bc6f249413ecdb1da3b1d Mon Sep 17 00:00:00 2001 From: bolbol Date: Fri, 7 Aug 2026 00:19:14 +0000 Subject: [PATCH] docs(hermes-tt): ajout runbook sharepoint-delta-sync --- hermes-tt/sharepoint-delta-sync.md | 130 +++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 hermes-tt/sharepoint-delta-sync.md diff --git a/hermes-tt/sharepoint-delta-sync.md b/hermes-tt/sharepoint-delta-sync.md new file mode 100644 index 0000000..46ec06d --- /dev/null +++ b/hermes-tt/sharepoint-delta-sync.md @@ -0,0 +1,130 @@ +# SharePoint delta-sync (hermes-mail-browser -> archive locale) -- mise en place complete + +**Instance auteur** : hermes-tt +**Date** : 2026-08-06 +**Tags** : hermes-tt, sharepoint, sync, hermes-mail-browser, n8n, onedrive +**Statut** : valide + +--- + +## Probleme + +Objectif : ingestion automatique et sans intervention manuelle des fichiers OneDrive/SharePoint (TT) +dans le RAG nyora-notes-tt. Pipeline en deux moities : +1) Archive locale -> RAG (catalog+process+embed) : deja actif (workflow n8n Q6ZAXgd8HYoQbk9K). +2) SharePoint cloud -> archive locale : endpoint POST /sharepoint-sync ecrit sur hermes-mail-browser, + code jamais teste en conditions reelles avant cette session. + +Reprise de session : verifier le rebuild hermes-mail-browser (montage RW de l'archive ajoute), +puis valider tout le mecanisme (listing + filtre + telechargement + placement fichier). + +--- + +## Contexte et contraintes + +- hermes-mail-browser (port 3110->8000, VNC 8810->6080), Edge reel via CDP (`--remote-debugging-port=9222`), + profil persistant `--user-data-dir=/data/profile` (monte sur `./data:/data` cote hote, donc SURVIT + aux restart/recreate/rebuild -- confirme par la session SSO OWA qui a tenu apres un rebuild complet). +- Endpoint `POST /sharepoint-sync?lookback_hours=N` : un seul appel `_api/web/GetList(...)/items` par site, + 22 sites definis dans `SHAREPOINT_SITES` (main.py), filtre OData `Modified ge datetime''`. +- Montage RW `/volume1/docker/nyora-onedrive-archive:/data/onedrive-archive` partage avec nyora-notes-tt + (qui scanne le meme dossier en lecture seule) -- tout fichier depose est repris automatiquement par + le pipeline partie 1 sans chainage explicite necessaire. + +--- + +## Ce qui NE fonctionne PAS + +| Tentative | Erreur obtenue | Raison de l'echec | +|-----------|----------------|--------------------| +| curl depuis mcp-nas vers `172.17.0.1:3110` | timeout, exit 28 | le port est publie sur `192.168.100.33:3110`, pas sur `0.0.0.0` -- pas de route via le bridge docker0 interne pour un port bind sur une IP specifique | +| curl depuis mcp-nas vers `192.168.100.33:3110` en direct | timeout, exit 28 | pas de hairpin NAT container -> IP LAN de son propre hote sur Synology/docker bridge par defaut | +| Telechargement PDF via `page.goto(dl_url)` + `Browser.setDownloadBehavior` (CDP), reglages navigateur par defaut | `fichier non trouve sur disque apres 20s` -- 100% des `.pdf`, 0% des `.docx` | le lecteur PDF integre d'Edge intercepte l'ouverture et l'affiche inline au lieu de declencher un telechargement, meme avec `?download=1` dans l'URL et l'override CDP | +| `lookback_hours=0.01` (test de cas limite) | requete jamais retournee, CPU container a 224% pendant 6+ min | edge case non representatif d'un usage reel ; cause non investiguee plus avant -- eviter les fenetres tres courtes (<1h) meme en test | + +--- + +## Solution validee + +**1) Reglages navigateur (persistants, via VNC noVNC sur le port 8810) :** +- Desactiver l'ouverture des fichiers Office dans le navigateur. +- Activer "Toujours telecharger les fichiers PDF" et desactiver la reprise a la derniere position de lecture PDF. +- Ces reglages vivent dans `/data/profile` (volume hote persistant) -- pas besoin de les refaire a chaque + rebuild/restart. + +**2) Authentification sur `/sharepoint-sync` (alignee sur la convention `/onedrive-sync` de nyora-notes-tt) :** +```bash +# cle generee une fois +openssl rand -hex 24 +# ajoutee dans hermes-mail-browser/.env +SHAREPOINT_INGEST_KEY= +``` +Cote code (`main.py`) : import `Header` depuis fastapi, nouvelle constante +`SHAREPOINT_INGEST_KEY = os.environ.get("SHAREPOINT_INGEST_KEY", "")`, verification en tete de +`sharepoint_sync()` : `HTTPException(401, ...)` si `x_ingest_key` absent ou different. + +**3) Rebuild + redeploiement :** +```bash +ssh nas-host "cd /volume1/docker/hermes-mail-browser && nohup \ + /volume1/@appstore/ContainerManager/usr/bin/docker compose build > /tmp/hmb-build.log 2>&1 &" +# suivre : ssh nas-host "tail -f /tmp/hmb-build.log" +ssh nas-host "cd /volume1/docker/hermes-mail-browser && \ + /volume1/@appstore/ContainerManager/usr/bin/docker compose up -d" +``` + +**4) Workflow n8n cree et publie** : *hermes-tt -- Auto-sync SharePoint (delta -> archive locale)* +(id `pBF8OzVvPnGILGgj`), meme pattern de resilience que l'auto-sync OneDrive (`Q6ZAXgd8HYoQbk9K`) : +- Trigger planifie toutes les 60 min. +- `POST http://hermes-mail-browser:8000/sharepoint-sync?lookback_hours=2` (nom de service Docker, + reseau externe `n8n` partage). +- Header `X-Ingest-Key`. +- `options.timeout: 600000` (10 min), `response.neverError: true`, `retryOnFail: false`, + `onError: continueRegularOutput`. + +--- + +## Verification + +```bash +# Auth +curl -s -o /dev/null -w '%{http_code}' -X POST 'http://192.168.100.33:3110/sharepoint-sync?lookback_hours=2' +# -> 401 (sans cle) +curl -s -o /dev/null -w '%{http_code}' -X POST '...' -H 'X-Ingest-Key: mauvaise' +# -> 401 +curl -s -X POST '...' -H 'X-Ingest-Key: ' +# -> 200, JSON complet +``` +Test reel sur 1 an d'historique : 12 candidats (PDF + docx) sur 3 sites actifs, **10 downloaded, 0 errors** +(les 2 restants = doublons deja presents sur disque, skip attendu). Fichiers verifies un par un sur disque : +noms et extensions corrects (PV d'ouverture, decisions de commission, rapports d'evaluation). + +Execution n8n manuelle (id `36338`) : `status: success`, 111s, 22 sites scannes via le nom de service +Docker `hermes-mail-browser:8000` (resolution DNS interne confirmee), resultat JSON conforme, +`cutoff` calcule correctement a partir de `lookback_hours=2`. + +--- + +## Pieges specifiques DSM / NAS + +- Port publie sur une IP LAN specifique (`192.168.100.33:PORT`) plutot que `0.0.0.0:PORT` => inaccessible + depuis un autre container via `172.17.0.1` (bridge docker), et pas de hairpin NAT vers l'IP LAN de son + propre hote non plus. Pour tester ce genre d'endpoint depuis mcp-nas : toujours passer par + `ssh nas-host "curl ... 192.168.100.33:PORT/..."` (le curl part alors du host lui-meme). +- `start.sh` nettoie les verrous `Singleton*` et `X99` au demarrage -- necessaire pour un restart propre + apres un arret brutal (deja en place, ne pas retirer). +- Rebuild rapide (~20-30s) une fois les couches pip en cache ; le tout premier rebuild d'une session + (cache purge) peut prendre plusieurs minutes -- ne pas s'inquieter si le premier est plus long. +- Un `POST /sharepoint-sync` en cours (verrou `sp_sync_lock`) fait attendre 423 "deja en cours" a toute + requete concurrente -- normal, mais ne pas empiler des tests avec des `-m` trop courts en pensant + relancer un run frais : c'est le meme run qui continue derriere. +- Le scan complet des 22 sites prend 90-120s meme quand `candidats=0` partout (navigation reelle + site par site) -- prevoir un timeout client genereux (>=150s) pour tout test manuel. + +--- + +## References + +- Workflow n8n jumeau : *nyora-notes-tt -- Auto-sync OneDrive* (`Q6ZAXgd8HYoQbk9K`) +- Code source : `/volume1/docker/hermes-mail-browser/app/main.py` + (fonctions `sp_sync_site_delta`, `sharepoint_sync`, `SHAREPOINT_SITES`) +- Nouveau workflow : https://n8n.nd.i234.me/workflow/pBF8OzVvPnGILGgj