consolidation: fusion doublons (mcp-nas, opencode, bifrost-vk, doc-api rebuild), purge obsoletes (gotenberg, ports-registry racine), re-spherage runbooks metier (perso/tt/nyora), refonte _INDEX.md — 09/07/2026

This commit is contained in:
bolbol 2026-07-09 12:28:30 +00:00
parent cdeb9ebbc3
commit 390202d93f
25 changed files with 308 additions and 1068 deletions

172
_INDEX.md
View File

@ -1,83 +1,121 @@
# NAS Runbooks — Index
> Referentiel operationnel partage entre hermes-tt, hermes-nyora, hermes-perso.
> Chaque instance ecrit dans son dossier. Tous peuvent lire tous les dossiers.
> Derniere mise a jour : auto-generee par n8n (dimanche 03:00)
> Référentiel opérationnel partagé entre hermes-tt, hermes-nyora, hermes-perso.
> Chaque instance écrit uniquement dans son dossier ; tous les dossiers sont lisibles par tous.
> **Consolidation du 09/07/2026** : doublons fusionnés, runbooks obsolètes purgés, runbooks métier re-sphérés (détail en bas de page).
---
## common (infra partagee, transverse aux 3 instances)
## common — Protocoles & référence
| Runbook | Date | Tags |
|---------|------|------|
| [Acces Bifrost (passerelle LLM, vision/OCR)](common/bifrost-access.md) | 2026-06-14 | infra, bifrost, llm, vision, x-bf-vk |
| [Audit securite reseau NAS (surface WAN, crowdsec, firewall, wg-easy)](common/audit-securite-reseau-nas-20260703.md) | 2026-07-03 | infra, securite, reseau, crowdsec, firewall, wg-easy, wan |
| [Audit securite mcp-nas — RCE root ANONYME exposee Internet (docker.sock, secrets clairs audit.log, correctifs P0 + rotation)](common/mcp-nas-security-audit.md) | 2026-07-08 | infra, securite, mcp-nas, rce, docker-socket, secrets, rotation |
| [Fragilites de dependances stack 43 containers (restart/persistance/couplages)](common/fragilites-dependances-stack-20260703.md) | 2026-07-03 | infra, stack, restart, couplage, dependances, rla-api, n8n |
| [Correctifs fragilites appliques (rla-api compose, n8n/trilium restart, bifrost-proxy healthcheck)](common/correctifs-fragilites-application-20260704.md) | 2026-07-04 | infra, correctifs, rla-api, n8n, bifrost-proxy, healthcheck |
| [nyora-doc-api mode template — cause racine non-restyle des runs (rPr > styles) + correctif restyle opt-in proposé](common/nyora-doc-api-template-restyle-cause-racine.md) | 2026-07-08 | infra, nyora-doc-api, docx, pptx, template, cause-racine |
| [Rebuild nyora-doc-api + footer Nyora DOCX (procedure SSH host, multipart, verif XML)](common/nyora-doc-api-rebuild-footer-docx.md) | 2026-07-04 | infra, nyora-doc-api, docker, rebuild, footer, docx |
| [Generation / edition d'images IA (nano-banana)](common/openrouter-image-gen.md) | 2026-06-14 | infra, openrouter, image, nano-banana |
| [Gotenberg HTML->PDF (piege police web)](common/gotenberg-pdf.md) | 2026-06-14 | infra, gotenberg, pdf, fonts |
| [Migration provider OpenCode Go (+ fallback OpenRouter)](common/migration-provider-opencode-go.md) | 2026-06-14 | infra, opencode, hermes, family-help, fallback |
| [nyora-doc-api v3 Premium - guide usage Hermes](common/nyora-doc-api-hermes-guide.md) | 2026-07-01 | infra, nyora-doc-api, hermes, docx, xlsx, pptx, pdf |
| [Envoi de fichiers via Telegram depuis les agents (sendDocument, fix fallback mail)](common/envoi-fichier-telegram.md) | 2026-07-04 | infra, hermes, telegram, senddocument, fichiers |
- `common/partage-pingvin-gros-fichiers.md` — Partage fichiers > 50 Mo via Pingvin/pv.bolbol.tn (cookie auth, chunks 30 Mo, skill partage-pingvin)
| [Skills concurrents à nyora-doc-api (docx/pdf/pptx/xlsx) sur les 3 instances — 2e vague auditée](common/skills-concurrents-pdf-docx-pptx-xlsx.md) | 2026-07-02, MAJ 2026-07-04 | infra, hermes, skills, docx, pdf, pptx, xlsx, nyora-doc-api |
| [Generation chunkee obligatoire pour taches volumineuses (DeepSeek V4 Flash)](common/generation-chunkee-taches-volumineuses.md) | 2026-07-02 | infra, hermes, deepseek, truncation, chunking, skill |
| [Bifrost access - MAJ sk-bf-/Authorization Bearer, piege allow_all_keys, limite anthropic providers custom, recette Hermes Desktop](common/bifrost-access.md) | 2026-07-02 | infra, bifrost, hermes-yesmine, virtual-keys |
| [gstack : evaluation et decision (MacBook Claude Code natif, pas hermes-perso)](common/GSTACK-EVALUATION-MACBOOK-VS-HERMES.md) | 2026-07-02 | infra, gstack, claude-code, hermes-perso, macbook |
| [PROTOCOL-INFRA — règles opérationnelles](common/PROTOCOL-INFRA.md) | maj continue | infra, protocole |
| [Ports Registry NAS (source de vérité services — miroir de /volume1/docker/ports-registry.md)](common/ports-registry.md) | 2026-07-04 | infra, ports, registry |
| [mcp-nas — référence opérationnelle consolidée (run_command v2, contraintes post-audit)](common/mcp-nas-reference.md) | 2026-07-09 | infra, mcp-nas, scripting |
| [Git push depuis mcp-nas (172.17.0.1, API Gitea si git absent)](common/git-push-depuis-mcp-nas.md) | 2026-07-08 | infra, git, mcp-nas |
| [Boîte à idées Claude (radar non décisionnel)](common/boite-a-idees-claude.md) | 2026-07-08 | infra, veille, ideation |
| [Vision fondatrice Nyora + SOUL.md 3 instances](common/nyora-definition-fondatrice.md) | 2026-06-23 | nyora, soul, vision |
## common — Sécurité
| Runbook | Date | Tags |
|---------|------|------|
| [Audit sécurité réseau NAS (surface WAN, crowdsec, firewall)](common/audit-securite-reseau-nas-20260703.md) | 2026-07-03 | securite, reseau, wan |
| [Audit sécurité mcp-nas — RCE root anonyme, correctifs P0](common/mcp-nas-security-audit.md) | 2026-07-08 | securite, mcp-nas, rce, rotation |
| [Permissions credentials/clés — piège 777](common/permissions-credentials-cles-chmod.md) | 2026-07-05 | securite, credentials, chmod |
| [Décommission wg-easy (remplacé par Tailscale)](common/wg-easy-decommission-tailscale.md) | 2026-07-08 | wireguard, tailscale, vpn |
## common — Stack & fiabilité
| Runbook | Date | Tags |
|---------|------|------|
| [Fragilités de dépendances stack 43 containers](common/fragilites-dependances-stack-20260703.md) | 2026-07-03 | stack, restart, couplage |
| [Correctifs fragilités appliqués (rla-api, n8n, bifrost-proxy)](common/correctifs-fragilites-application-20260704.md) | 2026-07-04 | correctifs, healthcheck |
| [Baserow mem_limit 2g](common/baserow-memlimit.md) | 2026-06-29 | baserow, memoire |
| [Cache SSD write-back fin de vie + backup USB](common/ssd-cache-endurance-usb-backup.md) | 2026-07-04 | ssd, backup, usb |
| [Telegram — réponses dupliquées 4-5× (getUpdates/NAT TT) + fix DNS agents](common/telegram-duplication-getupdates-offset.md) | 2026-07-09 | telegram, hermes, dns, nat-tt |
| [Nettoyage stack documentaire (historique containers retirés)](common/cleanup-stack-documentaire.md) | 2026-07-09 | cleanup, doc-stack |
## common — LLM (Bifrost, OpenCode, n8n)
| Runbook | Date | Tags |
|---------|------|------|
| [Accès Bifrost (passerelle LLM, vision/OCR)](common/bifrost-access.md) | 2026-06-14 | bifrost, llm, x-bf-vk |
| [Bifrost — incidents VK & fallback (consolidé 23/06 + 06/07)](common/bifrost-vk-incidents.md) | 2026-07-09 | bifrost, vk, opencode, cout |
| [Migration provider → OpenCode Go (consolidé, état des modèles à jour)](common/opencode-go-migration.md) | 2026-07-09 | opencode, hermes, family-help |
| [n8n Code nodes LLM vers Bifrost obligatoire](common/runbook-n8n-llm-bifrost.md) | 2026-06-15 | n8n, bifrost, code-node |
| [Génération/édition d'images IA (nano-banana)](common/openrouter-image-gen.md) | 2026-06-14 | openrouter, image |
## common — Hermes (plateforme)
| Runbook | Date | Tags |
|---------|------|------|
| [Mise à jour des 3 instances Hermes](common/RUNBOOK-HERMES-UPDATE.md) | 2026-06-15 | hermes, update, compose |
| [Skills concurrents PDF/DOCX/PPTX/XLSX archivés (anti-bypass nyora-doc-api)](common/skills-concurrents-pdf-docx-pptx-xlsx.md) | 2026-07 | hermes, skills, doc |
| [Génération chunkée tâches volumineuses (>1000 mots)](common/generation-chunkee-taches-volumineuses.md) | 2026-07 | hermes, skill, chunk |
| [Skill sobriété-code (7 règles Ponytail)](common/sobriete-code-ponytail.md) | 2026-07-05 | skill, code, tokens |
| [Envoi de fichiers via Telegram (sendDocument)](common/envoi-fichier-telegram.md) | 2026-07-04 | telegram, senddocument |
| [Telegram rich_messages flag + restart Portainer API](common/rich-messages-telegram.md) | 2026-06-24 | telegram, rich-messages |
| [Partage Pingvin gros fichiers](common/partage-pingvin-gros-fichiers.md) | 2026-07 | pingvin, partage |
| [Tap Gitea privé hermes-skills](common/tap-gitea-hermes-skills.md) | 2026-06-17 | gitea, skills |
## common — Documents (nyora-doc-api)
| Runbook | Date | Tags |
|---------|------|------|
| [nyora-doc-api v3 Premium — guide d'usage Hermes](common/nyora-doc-api-hermes-guide.md) | 2026-07-01 | nyora-doc-api, docx, xlsx, pptx, pdf |
| [nyora-doc-api — procédure rebuild & déploiement](common/nyora-doc-api-rebuild.md) | 2026-07-09 | nyora-doc-api, docker, rebuild |
| [nyora-doc-api mode template — cause racine non-restyle + restyle=full (déployé 08/07)](common/nyora-doc-api-template-restyle-cause-racine.md) | 2026-07-08 | nyora-doc-api, template |
## common — Divers
| Runbook | Date | Tags |
|---------|------|------|
| [Hébergement de sites statiques produits par Hermes](common/HEBERGEMENT-SITES-STATIQUES.md) | 2026-06-20 | hebergement, statique |
| [HTML vers PNG headless (Puppeteer)](common/html-to-png-puppeteer.md) | 2026-07-09 | html, png, puppeteer |
| [gstack — évaluation MacBook vs Hermes](common/GSTACK-EVALUATION-MACBOOK-VS-HERMES.md) | 2026-06 | evaluation, gstack |
## hermes-tt
| Runbook | Date | Tags |
|---------|------|------|
| [rla-api : gestion utilisateurs & superadmin (piège users.json baké)](hermes-tt/rla-api-users-superadmin.md) | 2026-07-04 | rla-api, users, bcrypt |
| [Kanban multi-agent évaluation AO](hermes-tt/kanban-evaluateur-ao.md) | 2026-06-18 | kanban, ao |
## hermes-nyora
| Runbook | Date | Tags |
|---------|------|------|
| [mimo-v2.5 : 400 Param Incorrect screenshots browser_vision — fix plugin provider](hermes-nyora/mimo-400-param-incorrect-vision-tool-messages.md) | 2026-07-09 | mimo, vision, 400 |
| [Verdict pilote mimo-v2.5 : GARDER mimo, V4 Flash fallback](hermes-nyora/verdict-pilote-mimo-v25.md) | 2026-07-08 | mimo, modele, pilote |
| [Veille Dr. Nexum — email enrichi](hermes-nyora/veille-nexum-email-enrichi.md) | 2026-07-03 | dr-nexum, veille, email |
| [Cron figé + publish n8n cassé — veille Dr Nexum (timezone Tunis)](hermes-nyora/veille-dr-nexum-cron-timezone-publish-n8n.md) | 2026-07-07 | cron, timezone, veille |
| [Veille hebdo Dr. Nexum (kanban fan-out)](hermes-nyora/veille-hebdo-kanban.md) | 2026-06-18 | veille, kanban |
| [Workflow Claude-GLM Nyora API Builder](hermes-nyora/workflow-claude-glm.md) | 2026-06-17 | workflow, glm |
| [VPS Contabo — réinstall + bascule Tailscale](hermes-nyora/vps-contabo-reinstall-tailscale-07-07.md) | 2026-07-07 | vps, tailscale |
| [VPS Contabo — WireGuard + qBittorrent natif (kill-switch)](hermes-nyora/vps-contabo-wireguard-qbittorrent-natif.md) | 2026-07-05 | vps, wireguard |
| [Backup NAS → VPS Contabo (restic chiffré)](hermes-nyora/backup-nas-vps-contabo-restic.md) | 2026-07-05 | vps, backup, restic |
| [Accès supervision Claude sur VPS Contabo](hermes-nyora/vps-contabo-acces-claude-supervision.md) | 2026-07-05 | vps, acces |
| [Surveillance trafic sortant fair-use Contabo](hermes-nyora/vps-contabo-surveillance-bandwidth.md) | 2026-07-05 | vps, bandwidth |
| [Bifrost VK OpenCode fix (403/no route)](common/BIFROST-VK-OPENCODE-FIX.md) | 2026-06-23 | infra, bifrost, opencode, vk |
| [Hebergement sites statiques Hermes (container nginx dedie)](common/HEBERGEMENT-SITES-STATIQUES.md) | 2026-06-22 | infra, nginx, static, hermes |
| [MCP NAS scripting reference (sessions, limites, services internes)](common/MCP-NAS-SCRIPTING.md) — règles 1-3 obsolètes, voir v2 | 2026-06-23 | infra, mcp-nas, scripting |
| [MCP NAS run_command v2 (P0) : heredocs, commandes longues, busy-check, reset_session](common/mcp-nas-run-command-v2.md) | 2026-07-04 | infra, mcp-nas, run-command, tmux, reset-session |
| [Migration OpenRouter vers OpenCode Go (endpoint zen/go/v1)](common/OPENCODE-GO-MIGRATION.md) | 2026-06-16 | infra, opencode, migration, llm |
| [Cleanup stack documentaire (Pandoc/Gotenberg/Carbone retires)](common/cleanup-stack-documentaire.md) | 2026-06 | infra, cleanup, doc-stack |
| [Boite a idees Claude (veille outils/concepts, radar non-decisionnel)](common/boite-a-idees-claude.md) | 2026-07-08 | infra, veille, ideation, common |
| [Git push depuis mcp-nas (172.17.0.1 vs 192.168.100.33)](common/git-push-depuis-mcp-nas.md) | 2026-06-15 | infra, git, mcp-nas |
| [SOUL.md hermes-perso -- ingest API veille (score sur 10 vers sur 100)](common/hermes-perso-SOUL-veille-ingest.md) | 2026-06-15 | infra, hermes-perso, soul, veille |
| [HTML vers PNG headless (Puppeteer + Gotenberg)](common/html-to-png-puppeteer.md) | 2026-06-21 | infra, html, png, puppeteer, gotenberg |
| [Kanban evaluateur-ao (evaluation AO parallele hermes-tt)](common/kanban-evaluateur-ao.md) | 2026-06-18 | infra, kanban, ao, hermes-tt |
| [Vision fondatrice Nyora + SOUL.md 3 instances](common/nyora-definition-fondatrice.md) | 2026-06-23 | infra, nyora, soul, vision |
| [n8n Code nodes LLM vers Bifrost obligatoire](common/runbook-n8n-llm-bifrost.md) | 2026-06-15 | infra, n8n, bifrost, code-node |
| [Tap Gitea prive hermes-skills (6 skills perso, 3 instances)](common/tap-gitea-hermes-skills.md) | 2026-06-15 | infra, gitea, skills, hermes |
| [Veille hebdo Nyora (kanban fan-out 6 sources, profil veilleur)](common/veille-hebdo-nyora.md) | 2026-06-18 | infra, veille, nyora, kanban |
| [Workflow Claude-GLM Nyora API Builder (planner/executor/reviewer)](common/workflow-claude-glm-nyora.md) | 2026-06-15 | infra, workflow, claude, glm |
## hermes-perso
| Runbook | Date | Tags |
|---------|------|------|
| [CrowdSec sur DSM](hermes-perso/security/crowdsec-dsm.md) | 2026-06-12 | securite, ssh, iptables |
## hermes-tt
| Runbook | Date | Tags |
|---------|------|------|
| [rla-api : gestion utilisateurs & superadmin par defaut (piege users.json bake dans l'image)](hermes-tt/rla-api-users-superadmin.md) | 2026-07-04 | infra, rla-api, users, superadmin, bcrypt, gitea |
## hermes-nyora
| Runbook | Date | Tags |
|---------|------|------|
| [mimo-v2.5 : 400 Param Incorrect sur screenshots browser_vision (tool messages liste rejetes par Xiaomi) — fix plugin provider](hermes-nyora/mimo-400-param-incorrect-vision-tool-messages.md) | 2026-07-09 | nyora, mimo, opencode, xiaomi, vision, browser_vision, 400 |
| [Verdict pilote mimo-v2.5 : GARDER mimo, V4 Flash en fallback (config finale + donnees)](hermes-nyora/verdict-pilote-mimo-v25.md) | 2026-07-08 | nyora, mimo, deepseek, opencode, modele, pilote, config |
| [Veille Dr. Nexum -- Email enrichi (fin du bug email illisible)](hermes-nyora/veille-nexum-email-enrichi.md) | 2026-07-03 | nyora, dr-nexum, veille, email, n8n, cron |
| [VPS Contabo -- WireGuard + qBittorrent natif Ubuntu (pas Docker, kill-switch)](hermes-nyora/vps-contabo-wireguard-qbittorrent-natif.md) | 2026-07-05 | nyora, vps, contabo, wireguard, qbittorrent, kill-switch, natif |
| [Backup NAS -> VPS Contabo (restic chiffre, throttle, securise)](hermes-nyora/backup-nas-vps-contabo-restic.md) | 2026-07-05 | nyora, vps, contabo, backup, restic, securite |
| [Acces supervision Claude sur VPS Contabo (claude-oversight, sudo NOPASSWD, alerte connexion)](hermes-nyora/vps-contabo-acces-claude-supervision.md) | 2026-07-05 | nyora, vps, contabo, securite, acces, supervision |
| [Surveillance trafic sortant sous seuil fair-use Contabo](hermes-nyora/vps-contabo-surveillance-bandwidth.md) | 2026-07-05 | nyora, vps, contabo, bandwidth, monitoring, fair-use |
| [SOUL.md hermes-perso — ingest API veille](hermes-perso/soul-veille-ingest.md) | 2026-06-15 | soul, veille |
---
## Regles de contribution
- **Ecriture** : chaque instance ecrit uniquement dans son dossier `hermes-<nom>/`
- **Lecture** : tous les dossiers sont lisibles par toutes les instances
- **Format** : utiliser RUNBOOK-TEMPLATE.md
- **Apres chaque runbook** : poster une note NyoraNotes avec tag [infra, runbook]
- [common/rich-messages-telegram.md](common/rich-messages-telegram.md) — Telegram rich_messages flag + restart Portainer API (2026-06-24)
| [Cache SSD write-back en fin de vie + backup USB urgence](common/ssd-cache-endurance-usb-backup.md) | 2026-07-04 | infra, ssd, cache, backup, usb, mcp-nas |
| [Ports Registry NAS (source de verite etat des services)](common/ports-registry.md) | 2026-07-04 | infra, ports, registry, nas |
| [Skill sobriete-code (7 regles Ponytail, hermes-tt + hermes-nyora)](common/sobriete-code-ponytail.md) | 2026-07-05 | dev, skill, code, tokens, couts, hermes-tt, hermes-nyora |
| [Permissions credentials/cles - piege 777 et regle transverse (skill nas-ops)](common/permissions-credentials-cles-chmod.md) | 2026-07-05 | infra, securite, credentials, permissions, chmod |
| [Bifrost VK stale-cache + fallback OpenRouter vers OpenCode Go](common/bifrost-vk-stale-cache-et-fallback-opencode.md) | 2026-07-06 | infra, bifrost, hermes, opencode, openrouter, cout |
| [Cron Hermes fige + publish n8n casse -- veille Dr Nexum non recue (timezone Tunis)](common/veille-dr-nexum-cron-timezone-publish-n8n.md) | 2026-07-07 | infra, cron, hermes, n8n, publish, timezone, veille, nyora |
| [Décommission wg-easy (remplacé par Tailscale)](common/wg-easy-decommission-tailscale.md) | 2026-07-08 | infra, wireguard, tailscale, vpn, nas |
## Règles de contribution
| [Telegram — réponses dupliquées 4-5× (relivraison getUpdates, offset perdu NAT TT) + fix DNS agents](common/telegram-duplication-getupdates-offset.md) | 2026-07-09 | infra, telegram, hermes, dns, nat-tt, tokens |
- **Écriture** : chaque instance écrit uniquement dans son dossier `hermes-<nom>/` ; `common/` = strictement transverse (infra/ops générique, **jamais de données métier ou familiales**).
- **Lecture** : tous les dossiers lisibles par toutes les instances.
- **Format** : RUNBOOK-TEMPLATE.md. Après chaque runbook : note NyoraNotes tags [infra, runbook] et mise à jour de ce _INDEX.md (pas de sous-index par dossier).
## Consolidation 09/07/2026 (traçabilité)
- **Fusionnés** : MCP-NAS-SCRIPTING + mcp-nas-run-command-v2 → `mcp-nas-reference.md` · OPENCODE-GO-MIGRATION + migration-provider-opencode-go → `opencode-go-migration.md` · BIFROST-VK-OPENCODE-FIX + bifrost-vk-stale-cache → `bifrost-vk-incidents.md` · nyora-doc-api-footer-bug-docx + nyora-doc-api-rebuild-footer-docx → `nyora-doc-api-rebuild.md` (footers supprimés de tous les formats le 08/07).
- **Supprimés (obsolètes)** : gotenberg-pdf.md (container désinstallé 21/06), ports-registry.md dupliqué à la racine (identique à common/), hermes-nyora/_INDEX.md (sous-index abandonné).
- **Re-sphérés depuis common/** : hermes-perso-SOUL-veille-ingest → hermes-perso/ (données familiales) · kanban-evaluateur-ao → hermes-tt/ · veille-hebdo-nyora, workflow-claude-glm-nyora, veille-dr-nexum-cron-timezone-publish-n8n → hermes-nyora/.

View File

@ -1,87 +0,0 @@
# RUNBOOK — Bifrost VK OpenCode Fix + Veille Fallback
**Date** : 2026-06-23
**Contexte** : Veille bolbol.tn — "Resume indisponible" systematique
## Symptomes
- `00:00` et `19:00` : `could not auto resolve a provider`
- `07:00` : `GoUsageLimitError — Weekly usage limit reached`
## Diagnostic
### Erreur 1 — could not auto resolve
Node n8n `Enrichir via Bifrost` (workflow 9378593adccf42dc) envoie x-bf-vk: bfk-e5832bfe (Nabil-Key), model: deepseek-v4-flash.
La Nabil-Key VK n'avait pas OpenCode dans governance_virtual_key_provider_configs.
Bifrost cherchait deepseek-v4-flash dans openrouter/google/nvidia_nim -> introuvable.
### Erreur 2 — GoUsageLimitError
Job cron hermes-nyora `veille-hebdo-nexum-kanban-a1b2c3d4` avait model/provider null.
Orchestrateur -> provider par defaut = OpenCode Go direct -> quota hebdo epuise lundi.
NOTE: Les 6 workers kanban utilisent le profil veilleur (openrouter) -> OK. Seul l'orchestrateur est affecte.
## Fixes appliques
### Fix 1 — Bifrost DB: OpenCode ajoute a Nabil-Key VK
```python
conn = sqlite3.connect('/mnt/docker/bifrost/data/config.db')
cur = conn.cursor()
vk = 'dc17fe0c-f7bf-4752-acb8-798156b2ec9e'
models = '["deepseek-v4-flash","deepseek-v4-pro","glm-5.1","kimi-k2.6"]'
cur.execute(
"INSERT INTO governance_virtual_key_provider_configs "
"(virtual_key_id, provider, weight, allowed_models, blacklisted_models, allow_all_keys) "
"VALUES (?, 'opencode', 1.0, ?, '[]', 1)", (vk, models))
conn.commit()
```
### Fix 2 — Bifrost DB: OpenCode key persistee dans config_keys
```python
kid = str(uuid.uuid4())
now = datetime.datetime.utcnow().isoformat() + 'Z'
cur.execute(
"INSERT INTO config_keys (name,provider_id,provider,key_id,value,models_json,"
"blacklisted_models_json,weight,enabled,encryption_status,created_at,updated_at) "
"VALUES ('opencode-1',36,'opencode',?,?,?,'[]',1.0,1,'plain_text',?,?)",
(kid, BIFROST_OPENCODE_KEY, models, now, now))
conn.commit()
```
### Fix 3 — Bifrost restart (requis apres modif DB)
Via Portainer API http://172.17.0.1:9000 (endpoint_id=2, container 3136d565d6dd).
Auth: POST /api/auth -> jwt. Actions: stop + start sur /api/endpoints/2/docker/containers/{id}/{action}
ATTENTION: container ID change apres recreate -> verifier avant.
### Fix 4 — jobs.json hermes-nyora: orchestrateur job 2
Fichier: /mnt/docker/hermes-platform/hermes-nyora/data/cron/jobs.json
Job veille-hebdo-nexum-kanban-a1b2c3d4 -> model: deepseek/deepseek-v4-flash, provider: openrouter
### Fix 5 — n8n workflow 9378593adccf42dc: fallback gemini-2.5-flash
Node Enrichir via Bifrost modifie: si GoUsageLimitError -> retry avec gemini-2.5-flash.
Via n8n API: PUT /api/v1/workflows/9378593adccf42dc avec {name, nodes, connections, settings}.
## Architecture finale (VK Nabil-Key bfk-e5832bfe)
| Provider | Modeles autorises |
|-------------|------------------------------------------------------------------------|
| openrouter | Gemma-4-31B/26B free, Nemotron, GPT-OSS free, Hermes-3, Qwen3-coder |
| google | gemma-4-31b/26b, gemini-2.5-flash, gemini-2.5-flash-lite |
| nvidia_nim | Llama-3.3-70B, Nemotron-70B, Llama-405B, Qwen2.5-Coder |
| opencode | deepseek-v4-flash, deepseek-v4-pro, glm-5.1, kimi-k2.6 (NOUVEAU) |
## Pieges a eviter
- Bifrost ne hot-reload PAS les providers -> restart obligatoire apres modif DB
- config.json charge providers au boot en memoire; config_keys DB = source persistante
- auth Bifrost = x-bf-vk header, PAS Authorization: Bearer -> 401
- Portainer container ID change apres recreate -> verifier avant restart
- N8N PUT /workflows: accepte uniquement {name, nodes, connections, settings} -> 400 sinon
## MCP NAS — Regles de scripting fiables
| NE PAS faire | Faire a la place |
|--------------------------------------------|-----------------------------------------------|
| Heredoc << 'EOF' | Base64 encode -> transfer -> decode |
| printf 'long code python' | python3 >400c | printf > /tmp/s.py && python3 /tmp/s.py |
| Commands dans session apres plusieurs err | Nouvelle session ou session differente |
| Pipes complexes inline dans printf | Script intermediaire en /tmp/ |

View File

@ -1,190 +0,0 @@
# MCP NAS — Référence de scripting fiable
**Date** : 2026-06-23 | Session debug Veille/Bifrost (40+ tool calls observés)
> ⚠️ **OBSOLÈTE EN PARTIE depuis le patch P0 du 2026-07-04** — voir [mcp-nas-run-command-v2.md](mcp-nas-run-command-v2.md).
> Les RÈGLES 1, 2 et 3 ci-dessous (poisoning, heredoc interdit, limite 350 chars/base64) **ne s'appliquent plus** :
> heredocs, quotes et commandes longues fonctionnent nativement, et `reset_session` récupère une session bloquée.
> La section « RÈGLE 4 — Services internes (172.17.0.1) » reste valide ;
> depuis le P1, `nas.internal` est un alias stable de 172.17.0.1 dans le container.
---
## Environnement du container
| Propriété | Valeur |
|-----------|--------|
| Shell | `/bin/bash` |
| User | `root` uid=0 |
| Python | `3.11.15``/usr/local/bin/python3` |
| Modules Python | `requests`, `sqlite3`, `json`, `urllib`, `subprocess` |
| Filesystem `/mnt` | NAS Synology 11 To, R/W |
| Réseau host Docker | `172.17.0.1` |
| Réseau LAN NAS | `192.168.100.33`**INACCESSIBLE depuis container** |
### Binaires (vérifié 2026-06-23)
| Outil | Dispo | Note |
|-------|-------|------|
| `curl` | oui | `/usr/bin/curl` — soumis limite 350 chars |
| `base64` | oui | `/usr/bin/base64` |
| `python3` | oui | 3.11 complet |
| `git` | oui | via subprocess Python |
| `sqlite3` CLI | non | utiliser module Python `import sqlite3` |
| `docker` CLI | non | pas de socket monté — Portainer API |
| `paramiko` | non | pas de SSH natif Python |
---
## RÈGLE 1 — Sessions : poisoning
Après 3+ erreurs consécutives, la session refuse même `echo hello`.
Symptôme : `{"error": "Error occurred during tool execution"}` sur commande triviale.
Sessions mortes dans cette session : `claude`, `db_update`, `verify`.
Sessions stables : `model_test`, `emergency`, `s1` (utilisées fraîchement).
**Toujours spécifier `session=` dans run_command** (sans = erreur systématique).
Après 2 erreurs d'affilée : changer de session immédiatement.
Si toutes poisonnées : `new_session("fresh1")`.
---
## RÈGLE 2 — Heredoc interdit
`<< 'EOF'` dans toute forme cause un **timeout 120s** qui tue la session.
Cela inclut `cat > f << 'EOF'`, `python3 << 'PYEOF'`, `bash << 'EOF'`.
Cause : l'injection tmux ne gère pas l'attente stdin que heredoc déclenche.
---
## RÈGLE 3 — Limite 350 chars par commande
Au-delà de ~350 chars dans le champ `command` : timeout, troncature ou erreur silencieuse.
**Méthode 1 — Code court (< 200 chars)**
Deux appels séparés :
```
printf 'import json\nprint("ok")\n' > /tmp/s.py
python3 /tmp/s.py
```
**Méthode 2 — Code moyen (200350 chars)**
Appender en plusieurs appels :
```
printf 'import sqlite3\nconn=sqlite3.connect("/mnt/docker/bifrost/data/config.db")\n' > /tmp/s.py
printf 'cur=conn.cursor()\ncur.execute("SELECT * FROM config_keys")\n' >> /tmp/s.py
printf 'for r in cur.fetchall(): print(r)\n' >> /tmp/s.py
python3 /tmp/s.py
```
**Méthode 3 — Code long ou avec quotes simples (> 350 chars)**
Base64 encode côté Claude (bash_tool), decode sur NAS (2 run_command) :
```
# bash_tool : base64 -w0 fichier.py → obtenir la chaîne B64
# run_command 1 : printf '<B64>' | base64 -d > /tmp/s.py
# run_command 2 : python3 /tmp/s.py
```
Piège : une quote simple `'` dans printf termine la chaîne → code tronqué sans erreur.
Dès qu'il y a des `'` dans le code Python → base64 obligatoire.
---
## RÈGLE 4 — Services internes (172.17.0.1)
**Portainer — restart container**
```python
import urllib.request, json
# Auth
body = json.dumps({"username":"bestof","password":"<depuis .env>"}).encode()
req = urllib.request.Request("http://172.17.0.1:9000/api/auth", data=body,
headers={"Content-Type":"application/json"})
jwt = json.loads(urllib.request.urlopen(req).read())["jwt"]
h = {"Authorization": "Bearer " + jwt}
# ID dynamique — change après recreate
req = urllib.request.Request(
"http://172.17.0.1:9000/api/endpoints/2/docker/containers/json", headers=h)
cs = json.loads(urllib.request.urlopen(req).read())
cid = [c["Id"][:12] for c in cs if "bifrost" in str(c.get("Names","")).lower()
and "proxy" not in str(c.get("Names","")).lower()][0]
# Stop + Start
for action in ["stop","start"]:
req = urllib.request.Request(
f"http://172.17.0.1:9000/api/endpoints/2/docker/containers/{cid}/{action}",
data=b"", headers=h)
urllib.request.urlopen(req)
```
**n8n API — PUT workflow**
```python
# Uniquement ces 4 champs acceptés — autres -> 400
payload = {"name": wf["name"], "nodes": wf["nodes"],
"connections": wf["connections"], "settings": wf.get("settings", {})}
# Header : X-N8N-API-KEY (pas Authorization Bearer)
```
**Bifrost**
```
Auth : header x-bf-vk: <VK> — PAS Authorization Bearer (-> 401)
URL : http://172.17.0.1:3085
```
**Gitea push**
```python
import subprocess, os
env = open("/mnt/docker/hermes-platform/.env").read()
pwd = [l.split("=",1)[1].strip() for l in env.splitlines() if "PASSWORD_GITEA" in l][0]
os.chdir("/mnt/docker/nas-runbooks")
subprocess.run(["git","add","."])
subprocess.run(["git","commit","-m","message"])
subprocess.run(["git","push", f"http://bolbol:{pwd}@172.17.0.1:3232/bolbol/nas-runbooks.git"])
```
**NyoraNotes**
```python
tok = open("/mnt/docker/nyora-notes/data/hermes-perso.token").read().strip()
note = {"title":"...","content":"...","tags":["infra","runbook","terminee"]}
body = json.dumps(note).encode()
req = urllib.request.Request("http://172.17.0.1:8787/notes", data=body,
headers={"Authorization":"Bearer "+tok,"Content-Type":"application/json"})
urllib.request.urlopen(req) # -> 201
```
**SQLite Bifrost DB**
```python
import sqlite3, shutil
# Lecture : copier d'abord (WAL actif)
shutil.copy("/mnt/docker/bifrost/data/config.db", "/tmp/bifrost.db")
conn = sqlite3.connect("/tmp/bifrost.db")
# Écriture live (restart Bifrost après pour prise en compte)
conn = sqlite3.connect("/mnt/docker/bifrost/data/config.db")
```
---
## Tableau de décision rapide
| Besoin | Faire |
|--------|-------|
| Code Python < 200 chars | printf > /tmp + python3 (2 appels) |
| Code Python > 350 chars ou avec quotes | base64 encode -> decode -> exec |
| Heredoc | Jamais. Python open().write() en /tmp |
| Restart container | Portainer API, ID dynamique |
| sqlite3 | Python import sqlite3 |
| Session instable | list_sessions -> session fraîche |
| Gitea push | subprocess git avec http://bolbol:pwd@ |
---
## Améliorations suggérées linux-mcp-nas
1. **Monter docker.sock** : `-v /var/run/docker.sock:/var/run/docker.sock` — Docker CLI direct, supprime Portainer API workaround
2. **Installer sqlite3 CLI** : `apt install -y sqlite3` dans l'image — inspection DB sans Python
3. **Augmenter timeout run_command** : 120s trop court pour git sur gros repos
4. **Nommer sessions par rôle** : `git`, `db`, `api`, `test` — rotation propre entre tâches
5. **Installer paramiko** : `pip install paramiko` — SSH natif si besoin accès NAS direct

View File

@ -1,59 +0,0 @@
# Migration OpenRouter → OpenCode Go — 2026-06-16
Objectif : basculer la stack LLM du NAS vers **OpenCode Go** (forfait Go, endpoint
`https://opencode.ai/zen/go/v1`, auth `Authorization: Bearer <clé>` uniquement —
pas de `x-bf-vk`, pas de `HTTP-Referer`/`X-Title`).
## Modèles OpenCode Go
IDs **sans préfixe** (`glm-5.1`, `deepseek-v4-pro`…), PAS `openrouter/` ni `deepseek/`.
Utilisables en **OpenAI-compat (oa-compat)** : `deepseek-v4-flash`, `deepseek-v4-pro`,
`glm-5.1`, `qwen3.7-plus`, `kimi-k2.6`, `kimi-k2.7-code`, `minimax-m3`, `glm-5`,
`qwen3.6-plus`, `mimo-v2.5-pro`
⚠️ **NE FONCTIONNE PAS** :
- `qwen3.7-max``Model not supported for format oa-compat` (dispo seulement en format Anthropic côté OpenCode Go). Tout consommateur OpenAI-compat (Bifrost custom provider, Open WebUI, family-help) doit utiliser `glm-5.1` à la place.
- MiniMax M2.7 vision via OpenCode Go = `prompt_tokens:0` (vision cassée).
## Ce qui a été migré
| Cible | Avant | Après | Clé |
|---|---|---|---|
| **hermes-tt** (config.yaml) | deepseek-v4-flash | défaut `deepseek-v4-pro`, fallback `deepseek-v4-flash`, délégation (data-engineer) `deepseek-v4-pro` | HERMES_TT_OPENCODE_KEY (provider `opencode-go`) |
| **hermes-nyora** | deepseek-v4-flash | défaut `glm-5.1`, fallback `qwen3.7-plus` | HERMES_NYORA_OPENCODE_KEY |
| **hermes-perso** | deepseek-v4-flash | défaut `qwen3.7-plus`, fallback `deepseek-v4-flash` | HERMES_PERSO_OPENCODE_KEY |
| **Bifrost** | — | provider `opencode` route `glm-5.1, deepseek-v4-pro, qwen3.7-plus, kimi-k2.6, minimax-m3` ; alias `claude-*→deepseek-v4-flash` (openrouter) conservé | BIFROST_OPENCODE_KEY |
| **Open WebUI** | Bifrost seul | 2e connexion directe OpenCode Go (`OPENAI_API_BASE_URLS` pluriel) | BIFROST_OPENCODE_KEY |
| **family-help** | OpenRouter (modèle unique) | routing par skill : medical/nutrition `glm-5.1`, homework `qwen3.7-plus`, legal_admin `deepseek-v4-pro`, tech/general `deepseek-v4-flash` ; fallback OpenRouter (web + erreur) | OPENCODE_API_KEY (=BIFROST_OPENCODE_KEY) |
| **n8n actifs** | commentaires/refs OpenRouter | nettoyés (NABIL.md Quotidien, Monitoring sources IA, Ingest Opportunités) | — |
## Hermes — config.yaml
Modèle défini dans `/volume1/docker/hermes-platform/hermes-{tt,nyora,perso}/data/config.yaml` :
`model.default` + `model.provider: opencode-go`, `fallback_providers[0]`, `fallback_model`.
Hermes **réécrit config.yaml au shutdown** → procédure : `docker stop` → éditer → `docker start`
(éditer container arrêté pour éviter le clobber). Healthcheck port 8642, API OpenAI-compat
(`/v1/chat/completions`, modèle proxy `hermes-agent`).
## Bifrost — PIÈGE MAJEUR (voir mémoire bifrost-keys-config-json)
Bifrost v1.5.13 **ne recharge PAS les clés des providers au redémarrage** (elles ne vivaient
qu'en mémoire). Fix durable = **`/volume1/docker/bifrost/data/config.json`** (providers + clés,
chargé au boot) + `allow_all_keys=1` dans `governance_virtual_key_provider_configs`.
- Providers dans config.json NE doivent PAS être aussi dans le store (`sqlite3 config.db "DELETE FROM config_providers; DELETE FROM config_keys;"`, bifrost stoppé).
- `sqlite3 config.db "UPDATE governance_virtual_key_provider_configs SET allow_all_keys=1;"`.
- ⚠️ éditer providers/clés/VK via l'UI Bifrost peut re-casser (reset allow_all_keys / conflit config.json).
- Backup config.db pré-migration : `/tmp/config.db.backup-*` (NAS).
## n8n — workflows AO inactifs : NON migrés (à faire délibérément)
Les 15 workflows AO/veille contenant encore OpenRouter sont **archivés** (`isArchived=true`) →
l'API n8n refuse de les éditer (`Cannot update an archived workflow`). Le pipeline AO **actif**
(`AO — Insertion Baserow FINAL`, hisVAANSYpixR4Si) est déjà propre.
Pour réutiliser un workflow AO archivé : le désarchiver (UI), migrer son Code node
(`openrouter.ai/api/v1/chat/completions` → `opencode.ai/zen/go/v1/chat/completions`, clé sk-or →
OpenCode, retirer HTTP-Referer/X-Title, modèle → `deepseek-v4-pro`), re-tester, ré-archiver.
Règle Code node n8n : `require('https')` + parsing manuel d'URL, jamais `fetch`/`new URL`/`$helpers`.
Liste des archivés concernés : edFMGtI2HHWW72aT, JTwurk7XVBUXSHKn, BCgZYRJcxoHOMDhm, iuxVgZFfpKdYFNqG,
xJtW4algsBcx6r1E, EEDr0xx9krRq2nwN, 7zWWJhP2aQbzQhZG, QALWT3NwMQjOuY6u, N3yQWk0XyhyS5wZX,
hcOmozHadfBnHzri, nZiXRcwSAXsoj2M6, Mdl5SRcT9rYw48VZ, dPnpoHkc6hEXdsFF, wS3SzRFfcaDDD34g, xu4smQdEGrHFx1zK, RRKUk3GvnULj7edE.
## Hors scope (laissés sur OpenRouter, actifs/famille — à migrer sur décision)
Workflows n8n actifs encore sur OpenRouter en direct (endpoint+clé) : `Mode-nedya`,
`FAMILLE | Recettes Weekend`, `Labellisation Auto`.

View File

@ -0,0 +1,39 @@
# Bifrost — Incidents VK & fallback (consolidé)
**Date** : 2026-07-09 (fusionne BIFROST-VK-OPENCODE-FIX.md 23/06 + bifrost-vk-stale-cache-et-fallback-opencode.md 06/07)
**Tags** : infra, bifrost, vk, opencode, openrouter, cout
Guide d'accès général : common/bifrost-access.md.
## Règles durables (à retenir avant tout debug)
1. Auth Bifrost = header `x-bf-vk`, JAMAIS `Authorization: Bearer` → 401.
2. Bifrost ne hot-reload NI les clés provider NI le VK store → **restart du container = premier réflexe** sur tout `401 virtual_key_not_found` inexpliqué (cache VK désynchronisé de la DB).
3. config.json chargé au boot = source providers ; `allow_all_keys=1` en DB ; ne pas dupliquer providers entre config.json et le store ; l'UI peut re-casser ces réglages.
4. Fallbacks Hermes → **opencode-go** (forfait), plus jamais openrouter (facturation réelle à chaque échec du modèle primaire).
5. Auditer périodiquement les règles de routing : le NOM d'une règle peut ne pas correspondre à sa cible réelle en base (désync vue sur la règle Haiku).
6. Portainer : l'ID container change après recreate → toujours le re-résoudre avant stop/start.
7. n8n PUT /workflows : payload strict {name, nodes, connections, settings} → 400 sinon.
## Incident 23/06/2026 — « Résumé indisponible » veille bolbol.tn
- `could not auto resolve a provider` : la VK Nabil-Key (bfk-e5832bfe…) n'avait pas OpenCode dans `governance_virtual_key_provider_configs` → deepseek-v4-flash introuvable. Fix : INSERT provider opencode (weight 1.0, allowed_models deepseek-v4-flash/pro, glm-5.1, kimi-k2.6, allow_all_keys=1) + clé persistée dans `config_keys` + restart bifrost.
- `GoUsageLimitError` : job cron hermes-nyora orchestrateur avec model/provider null → OpenCode direct, quota hebdo épuisé. Fix : jobs.json → model openrouter/deepseek-v4-flash pour l'orchestrateur ; workflow n8n 9378593adccf42dc → retry gemini-2.5-flash sur GoUsageLimitError.
- Architecture VK Nabil-Key finale : openrouter (modèles :free), google (gemma-4, gemini-2.5-flash/lite), nvidia_nim, opencode (deepseek-v4-flash/pro, glm-5.1, kimi-k2.6).
## Incident 06/07/2026 — VK stale-cache + fallbacks payants
1. 401 `virtual_key_not_found` répétés sur « VEILLE | Ingest Opportunités » alors que la VK était exacte en base → cache VK désynchronisé, **un simple restart bifrost a suffi**.
2. hermes-nyora (pilote mimo-v2.5) a basculé 2× sur son fallback natif openrouter (bypass Bifrost, coût réel facturé) → les 3 config.yaml migrés vers fallback `opencode-go/deepseek-v4-flash`, `key_env: OPENCODE_GO_API_KEY` (nom réel du compose top-level, PAS OPENCODE_API_KEY). Restart des 3 agents (les appels restart API peuvent timeout côté client → vérifier l'état, ne pas re-tenter en boucle ; start manuel parfois requis).
3. Règle routing « Haiku → Gemini 2.5 Flash » pointait en réalité vers openrouter/deepseek-v4-flash payant → `routing_targets` corrigé vers google/gemini-2.5-flash. Backups config.db pris avant chaque édit.
## Pilote mimo-v2.5 (contexte)
Bilan J+1 (06/07) : 389 appels, 0,5% d'échec (réponse vide = reasoning épuisant max_tokens) → fix `model.max_tokens: 8192` sur hermes-nyora. **Verdict final 08/07 : GARDER mimo, V4 Flash en fallback** — détails : hermes-nyora/verdict-pilote-mimo-v25.md.
## Vérification type
```bash
curl -X POST http://bifrost:8080/v1/chat/completions -H 'x-bf-vk: <Nabil-Key>' \
-d '{"model":"deepseek-v4-flash","max_tokens":30,"messages":[{"role":"user","content":"dis OK"}]}'
# 200 + routing_info.provider=opencode attendu
```

View File

@ -1,95 +0,0 @@
# Bifrost : VK stale-cache + migration fallback OpenRouter -> OpenCode Go
**Instance auteur** : Claude (via mcp-nas)
**Date** : 2026-07-06
**Tags** : infra, bifrost, hermes, opencode, openrouter, cout
**Statut** : valide
## Probleme observe
1. Pipeline nyora-veille (n8n workflow "VEILLE | Ingest Opportunites", node "Enrichir via Bifrost")
en echec repete (401 virtual_key_not_found) le 06/07 a 07:34 et 13:29-13:30 UTC, alors que le
x-bf-vk hardcode dans le node correspond exactement a la valeur Nabil-Key en base
(bfk-e5832bfebd22e9d8252a426d0734ed5f2d923204c8033d6d). Aucun cout facture (echec avant tout
routage provider).
2. hermes-nyora (mimo-v2.5, pilote 01-08/07) a bascule 2x le 05/07 (~21:38 et 21:48 UTC) sur son
fallback natif `fallback_providers: openrouter` (bypass Bifrost, cle OPENROUTER_API_KEY en
.env) suite a des reponses vides du pilote sur OpenCode. Cout reel facture sur OpenRouter,
hors quota epuise.
3. Bifrost logs.db (depuis 06/06) : 1370 appels reussis, 17,43$, VK non identifiee, modele
deepseek/deepseek-v4-flash sur OpenRouter -> trace de sessions Claude Cowork/Claude Code
routees via Bifrost et interceptees par une regle de routing.
## Cause racine
- Point 1 : cache Bifrost desynchronise (VK valide en base mais rejetee en memoire) -> **un simple
restart du container bifrost recharge correctement le VK store**. Meme famille de piege que
celui deja connu pour les cles provider (config.json au boot) : Bifrost ne recharge pas
systematiquement son etat interne sans redemarrage explicite.
- Point 2 : `fallback_providers` des 3 instances Hermes pointait vers `openrouter` (paye a l'usage)
au lieu de `opencode-go` (deja couvert par le forfait Go). Design d'origine (voir
migration-provider-opencode-go.md, 14/06) : a l'epoque volontaire comme filet de secours large,
mais genere une facturation reelle des qu'un modele opencode echoue (meme hors quota).
- Point 3 : regle de routing Bifrost `Haiku -> Gemini 2.5 Flash` (id
f5f03c54-049a-4f53-8590-7392730f42e0) avait un NOM ne correspondant pas a sa cible reelle en
base (deepseek/deepseek-v4-flash payant sur openrouter au lieu de gemini-2.5-flash gratuit sur
Google AI Studio). Les 4 autres regles Opus/Sonnet/Catch-all pointent, elles, vers des modeles
`:free` OpenRouter et sont correctes.
## Solution appliquee (06/07/2026)
1. `routing_targets` (config.db Bifrost) : rule f5f03c54... -> provider=google,
model=gemini-2.5-flash (etait openrouter/deepseek-v4-flash). Backup pris avant edit
(config.db.bak-<timestamp>). Restart container bifrost pour charger.
2. Les 3 `data/config.yaml` Hermes (hermes-tt, hermes-nyora, hermes-perso) :
`fallback_providers: openrouter/deepseek-v4-flash` -> `opencode-go/deepseek-v4-flash`,
`key_env: OPENCODE_GO_API_KEY` (nom reel de la var injectee par le compose top-level, pas
OPENCODE_API_KEY comme indique dans l'ancien runbook de migration). Backup des 3 fichiers pris
avant edit. Restart des 3 containers hermes-agent-* (perso a eu besoin d'un start manuel apres
le restart, le call restart API ayant timeout cote client -> verifier l'etat plutot que
de re-tenter en boucle).
3. Aucun changement necessaire sur le node n8n "Enrichir via Bifrost" : le restart bifrost a
suffi a corriger le probleme de VK stale.
## Verification
```
curl -s --unix-socket /var/run/docker.sock http://localhost/containers/<c>/json | jq .State
# bifrost, hermes-agent-tt/nyora/perso : running + healthy apres restart
curl -X POST http://bifrost:8080/v1/chat/completions -H 'x-bf-vk: <Nabil-Key>' \
-d '{"model":"deepseek-v4-flash","max_tokens":30,"messages":[{"role":"user","content":"dis OK"}]}'
# HTTP 200, routing_info.provider=opencode -> confirme
```
## A surveiller
- Si un 401 virtual_key_not_found reapparait sans changement de config -> suspecter a nouveau le
cache VK, restart bifrost avant toute autre investigation.
- Fiabilite mimo-v2.5 (reponses vides) non resolue en soi ; le fallback pointant desormais vers
opencode-go, tout echec futur du pilote restera gratuit (dans le forfait) au lieu d'etre facture.
- Auditer les 4 autres regles Opus/Sonnet/Catch-all : noms vs cibles reelles a revalider
periodiquement (meme type de desync que la regle Haiku).
## References
- migration-provider-opencode-go.md (14/06/2026)
- llm-audit-register.md (24/06/2026), item "N8n Ingest Opportunites"
## Addendum 06/07/2026 — pilote mimo-v2.5 sur hermes-nyora
Migration mimo-v2.5 confirmee active depuis le 05/07 20h01 (decision : tester un modele de
raisonnement sur Nyora uniquement, controler la conso, decider ensuite de generaliser ou non aux
3 instances). Bilan a J+1 : 389 appels, ~11,65M tokens entrants (tres majoritairement cache),
~182K tokens sortants, 5 incidents "reponse vide/pensee sans contenu", 2 fallbacks (meme session
courte 21h47-21h48 du 05/07). Taux d'echec 0,5%, isole a un cas de contexte court (in=631) ou le
raisonnement interne du modele epuisait le budget max_tokens avant d'emettre le contenu visible
(meme piege documente pour family-help dans migration-provider-opencode-go.md).
Fix applique : `model.max_tokens` 4096 -> 8192 dans data/config.yaml hermes-nyora (backup pris),
restart hermes-agent-nyora (start manuel necessaire, l'appel restart API a timeout cote client
comme pour hermes-agent-perso plus tot). Container reparti healthy, mimo-v2.5 toujours model
par defaut.
Point de decision (generaliser mimo-v2.5 aux 3 instances ou rester DeepSeek V4 Flash) a reprendre
en fin de semaine de pilote, sur la base de la conso reelle et du taux d'incidents mesures ici.

View File

@ -1,6 +1,14 @@
Runbook: Nettoyage Stack Documentaire
Date: 21 juin 2026
Services: gotenberg/pandoc/carbone/document-factory tous desinstallés
Portainer REST API utilisée pour stop+delete containers et images
Piege: rm blocked par mcp-nas, utiliser shutil.rmtree
Futur: API doc Nyora a construire from scratch
# Nettoyage stack documentaire (historique)
**Date** : 21/06/2026, complété 09/07/2026
**Tags** : infra, cleanup, doc-stack
## Ce qui a été retiré (ne pas réinstaller, ne pas proposer)
gotenberg, pandoc, carbone, document-factory, pptx-tt-api, tika — désinstallés le 21/06 via API Portainer (stop + delete containers et images). open-webui, paperless, familyspace retirés lors de l'audit stack de juin (58 → 43 containers).
Piège : `rm` bloqué par la denylist mcp-nas de l'époque → `shutil.rmtree` en Python.
## Remplacement
**nyora-doc-api (port 3050)** est depuis le seul moteur documentaire : DOCX/XLSX/PPTX/PDF, charte Nyora centralisée dans formatting.py. Guide : common/nyora-doc-api-hermes-guide.md · Rebuild : common/nyora-doc-api-rebuild.md.

View File

@ -1,25 +0,0 @@
# GOTENBERG-PDF — HTML → PDF (piège police web)
Note partagée aux 3 instances Hermes. Source : projet gsparc-mezzouna, 2026-06-14.
Gotenberg convertit du HTML en PDF. Conteneur `gotenberg` sur le réseau **n8n**, port **3000**.
`POST http://gotenberg:3000/forms/chromium/convert/html` (champ `files` = index.html).
## PIÈGE — police web manquante sur pages lourdes
Sur une page **lourde** (grosse image base64 en ligne), Chromium **imprime avant que la police web** (`@import` Google Fonts) soit appliquée → **texte manquant ou rendu incohérent** d'un document à l'autre. C'est **déterministe selon le poids** : les pages légères passent, les lourdes échouent (piège : on croit à un aléa).
## SOLUTION
- Champ form **`waitDelay: "1.5s"`** → laisse charger les ressources async (police) avant impression.
- **Alléger** la page : redimensionner les images embarquées.
- Pile de polices de secours avec une Arabe quasi toujours présente dans Chromium :
`font-family: Cairo,"Noto Sans Arabic","Noto Naskh Arabic",Tahoma,Arial,sans-serif;`
## Exemple (paysage A4 pleine page)
```bash
curl -s http://gotenberg:3000/forms/chromium/convert/html \
-F "files=@index.html" \
-F "paperWidth=11.69" -F "paperHeight=8.27" \
-F "marginTop=0.2" -F "marginBottom=0.2" -F "marginLeft=0.2" -F "marginRight=0.2" \
-F "landscape=true" -F "printBackground=true" -F "waitDelay=1.5s" -o out.pdf
```
Implémentation de référence : `gsparc-mezzouna/app/routes/export.py` (`_fiche_pdf_bytes`).

View File

@ -1,45 +1,20 @@
# HTML vers PNG : Rendu headless Puppeteer / Chromium
# HTML vers PNG : rendu headless Puppeteer / Chromium
**Contexte** : html2canvas echoue dans les iframes sandbox (Claude.ai, widgets).
Polices Google Fonts et SVG complexes bloques par CORS.
**Solution** : rendu serveur avec Chromium headless.
**Date** : 2026-06-21, révisé 09/07/2026 (retrait de l'approche Gotenberg — container désinstallé)
---
**Contexte** : html2canvas échoue dans les iframes sandbox (Claude.ai, widgets). Polices Google Fonts et SVG complexes bloqués par CORS.
**Solution** : rendu serveur avec Chromium headless via Puppeteer (bash_tool Claude).
## Approche 1 - Claude bash_tool
## Pièges critiques
### Installation (une seule fois par session)
### Script render.mjs
**Pieges critiques :**
- Entry point : lib/puppeteer/puppeteer.js (pas lib/esm/)
- page.waitForTimeout() supprime en v25+ => setTimeout natif
- page.waitForTimeout() supprimé en v25+ → setTimeout natif
- --no-sandbox obligatoire dans container Claude
- networkidle0 + 2s = polices externes chargees
- networkidle0 + attente 2 s = polices externes chargées
## Cas validé (2026-06-21)
Carte félicitations Bac 2026 — HTML/SVG 680×680 px + Google Fonts → PNG 1360×1360 px (137 Ko), upload Facebook direct.
---
## Approche 2 - NAS via Gotenberg (port 3001, deja deploye)
Gotenberg embarque Chromium. HTML -> PDF puis PDF -> PNG Pillow.
Ou via noeud HTTP Request n8n (multipart/form-data vers Gotenberg).
---
## Cas valide (2026-06-21)
Carte felicitations Bac 2026 - HTML/SVG 680x680px + Google Fonts.
Resultat : PNG 1360x1360px (137 Ko), upload Facebook direct.
**Regle absolue** : html2canvas = NON iframe sandbox.
Puppeteer (Claude) ou Gotenberg (NAS) = OUI.
**Règle absolue** : html2canvas = NON en iframe sandbox. Puppeteer = OUI.
**Note** : l'ancienne « Approche 2 » via Gotenberg (HTML→PDF→PNG) n'existe plus — gotenberg a été désinstallé le 21/06/2026 (cf. cleanup-stack-documentaire.md).

View File

@ -0,0 +1,46 @@
# mcp-nas — Référence opérationnelle (consolidée)
**Date** : 2026-07-09 (fusionne MCP-NAS-SCRIPTING.md 2026-06-23 + mcp-nas-run-command-v2.md 2026-07-04, + contraintes post-audit 2026-07-08)
**Tags** : infra, mcp-nas, scripting, securite
## Environnement du container (vérifié 09/07/2026, image post-audit)
| Propriété | Valeur |
|-----------|--------|
| Shell | `/bin/bash`, user root uid=0, **cap_drop: [ALL]** + no-new-privileges |
| Python | 3.11 — requests, sqlite3, json, urllib, subprocess |
| `git` | **ABSENT** (retiré au rebuild post-audit) → API HTTP Gitea obligatoire |
| `docker` CLI / docker.sock | **ABSENTS** (socket retiré P0 audit 08/07) → API Portainer |
| `/mnt/docker` | = /volume1/docker, RW |
| Réseau | host via `172.17.0.1` ou alias `nas.internal` (extra_hosts). 192.168.100.33 **inaccessible** |
## run_command v2 (P0 du 04/07, commit 30560984fa)
La commande est écrite dans un script par Python (zéro parsing shell) puis sourcée dans tmux :
- Heredocs natifs (`<<'EOF'`, quotes, `$VAR`, backticks) ; testé 5 250 chars en un appel.
- Busy-check : pane occupé → refus propre (options : capture_pane, send_keys, reset_session).
- Timeout intelligent : Ctrl-C + sonde ; session préservée si le shell répond.
- `reset_session` : reprise d'une session bloquée SANS destruction (vim : `send_keys ':q!'` d'abord).
- Cleanup au boot : sessions tmux orphelines + `/tmp/mcp_*` purgés.
- Denylist ancrée (P1, commit 7fb13c5) : patterns ancrés en début de segment, heredocs exclus. Défense en profondeur, PAS une frontière de sécurité.
- Interdits toujours actifs : reboot, mkfs, dd of=/dev/*, rm -rf racines critiques, docker rm -f, syno*…
**Ne plus utiliser** : workaround base64 2 appels, découpage printf-append, limite 350 chars — tout cela date de la v1.
## Contraintes post-audit sécurité (08/07/2026) — vérifiées le 09/07
1. **`cap_drop: [ALL]` → pas de CAP_DAC_OVERRIDE** : les dossiers `0700` appartenant à uid 1026 (ex. `hermes-*/data/`) sont **illisibles même en root**. C'est voulu. Lecture des data/ Hermes → passer par un autre canal (Mac, ou décision Nabil).
2. **`~/.ssh` du container vidé au rebuild** : plus de clé pour `ssh Best0f@172.17.0.1:22222`. SSH host depuis mcp-nas = indisponible tant que la clé n'est pas re-provisionnée (décision Nabil — l'audit recommandait justement de sortir les clés).
3. **docker.sock retiré** → gestion containers via **API Portainer** (`http://nas.internal:9000`, POST /api/auth → jwt, endpoint_id=2 ; l'ID container change après recreate, toujours le re-résoudre).
4. **Gitea** : API HTTP avec `GITEA_DEPLOY_TOKEN` (repo-scopé, dans hermes-platform/.env) — **jamais** le mot de passe bolbol dans une URL (fuite audit.log + ps). Lire le token dans une variable depuis le fichier, pas en clair dans la commande.
5. Rebuild du container : **depuis le Mac** (`ssh -p 22222 Best0f@192.168.100.33`, `cd /volume1/docker/linux-mcp-nas && sudo docker compose build && up -d --force-recreate`), jamais depuis mcp-nas lui-même.
## Services internes depuis mcp-nas
`nas.internal` (= 172.17.0.1) : Gitea `:3232`, Portainer `:9000`, NyoraNotes `:8787`, nyora-doc-api `:3050`, Bifrost `:3085` (LAN) / `http://bifrost:8080` (réseau n8n), context-hub `:3093`.
## Bonnes pratiques
- Scripts Python : heredoc `cat <<'EOF' > /tmp/s.py … EOF` puis `python3 /tmp/s.py`.
- Session par défaut `claude` fiable ; `reset_session` avant de créer une session neuve.
- Secrets : toujours via variable lue depuis .env (`export GT=$(grep … | cut -d= -f2)`), jamais inline — audit.log journalise chaque commande.

View File

@ -1,84 +0,0 @@
# MCP NAS — run_command v2 (P0) : heredocs, commandes longues, reset_session
**Date** : 2026-07-04 | Commit `30560984fa` sur `bolbol/linux-mcp-nas@main` | Testé et validé le jour même.
> **Ce runbook remplace les RÈGLES 13 de [MCP-NAS-SCRIPTING.md](MCP-NAS-SCRIPTING.md).**
> Le chunking base64, la limite ~350 chars et l'interdiction de heredoc n'existent plus.
> La section « Services internes (172.17.0.1) » de l'ancien runbook reste valide.
---
## Ce qui a changé
Avant, `run_command` envoyait la commande brute à tmux via `send-keys` : le parsing shell
cassait sur les quotes, les heredocs déclenchaient un timeout tueur de session, et au-delà
de ~350 caractères la commande était tronquée — d'où le workaround base64 en 2 appels.
Depuis le patch P0, le serveur **écrit la commande dans un fichier script depuis Python**
(`open(f"/tmp/mcp_{uid}.sh","w").write(command)` — zéro parsing shell) et n'envoie au pane que :
```
. /tmp/mcp_XXX.sh > /tmp/mcp_XXX.out 2>&1; echo $? > /tmp/mcp_XXX.rc
```
via `send-keys -l` (mode littéral). Conséquences :
| Avant (v1) | Maintenant (v2) |
|------------|-----------------|
| Heredoc → timeout 120 s, session morte | Heredocs natifs, y compris `<<'EOF'` avec quotes/`$VAR`/backticks |
| Limite ~350 chars, base64 obligatoire | Testé 5 250 chars en un appel, intégrité parfaite |
| Quote simple `'` → troncature silencieuse | Quotes arbitraires OK (aucun parsing shell) |
| Prompt de continuation `>` empoisonnait la session | Mécaniquement impossible |
| Empilement sur pane occupé (vim/ssh/pager) | **Busy-check** : refus propre avec message d'options |
| Sessions poisonnées → new_session en chaîne | **reset_session** : reprise sans destruction |
## Nouveaux comportements
- **Busy-check** : si le pane exécute déjà quelque chose, `run_command` renvoie
`[SESSION OCCUPÉE] 'x' exécute actuellement 'sleep'…` au lieu d'empiler. Options proposées :
`capture_pane`, `send_keys`, `reset_session`, ou une autre session.
- **Timeout intelligent** : à expiration, le serveur tente un Ctrl-C puis sonde le shell.
S'il répond → session préservée (cwd/env conservés). Sinon → session recréée dans le même cwd.
- **`reset_session(session)`** : envoie Ctrl-C, `q` (pager), Ctrl-U, vérifie que le shell répond.
Reprend la main sur une session bloquée SANS la détruire. Pour vim : `send_keys ':q!'` d'abord.
- **Cleanup au démarrage** : sessions tmux orphelines et fichiers `/tmp/mcp_*` purgés au boot
du container (les 24 sessions zombies accumulées ont disparu au premier rebuild).
## Tests de validation (2026-07-04)
1. **Heredoc** avec quotes simples/doubles, `$VAR`, backticks, `$(subshell)`, `!#&*(){}[]|;<>`
→ contenu intact, zéro expansion, exit code correct.
2. **Commande de 5 250 caractères** (heredoc 50 lignes × 100 chars + vérifications)
→ 5 050 octets écrits, 50/50 lignes conformes au motif.
3. **Busy-check + reset_session** : `sleep 300` lancé via send_keys → `run_command` refusé
proprement → `reset_session` → « shell réactif, cwd/env conservés (cwd: /tmp) ».
## Bonnes pratiques v2
- Écrire les scripts Python directement en heredoc : `cat <<'EOF' > /tmp/s.py … EOF` puis `python3 /tmp/s.py`.
- Ne plus jamais utiliser le workaround base64 (2 appels) ni le découpage printf-append.
- Session par défaut `claude` fiable ; `reset_session` avant de créer une session neuve.
- Le rebuild du container se fait **depuis le Mac** (`ssh nas`), jamais depuis mcp-nas lui-même :
```
ssh -p 22222 Best0f@192.168.100.33
cd /volume1/docker/linux-mcp-nas
sudo docker compose build && sudo docker compose up -d --force-recreate
curl -s http://127.0.0.1:3042/health
```
## P1 — denylist ancrée + nas.internal (2026-07-04, commit `7fb13c5`, déployé et testé)
- **Denylist ancrée** : les patterns ne sont plus cherchés n'importe où dans la chaîne brute.
La commande est découpée en segments (`;` `&` `|` retours ligne), les préfixes neutres
(`sudo`, `env`, `VAR=…`, chemin `/sbin/…`) sont retirés, et les patterns sont ancrés sur le
**début de chaque commande**. Les **corps de heredoc sont exclus** de l'analyse.
- Fini les faux positifs : `grep reboot /var/log`, `echo "ne pas faire reboot"`, un heredoc
de doc contenant « mkfs » → **acceptés**.
- Toujours refusés : `reboot`, `/sbin/reboot`, `echo ok && reboot`, `VAR=1 sudo shutdown`,
`rm -rf /volume*|/opt|/mnt|/`, `mkfs.*`, `dd of=/dev/*`, fork bomb, `> /dev/sd*`,
`docker rm -f`, `fdisk`, `parted`, `syno*`, `chmod -R 777 /`. (30/30 tests unitaires.)
- Changement assumé : `rm -rf /tmp/x` est désormais **autorisé** (avant, tout chemin absolu
était bloqué) ; les racines critiques restent protégées.
- **`nas.internal`** : `extra_hosts: nas.internal:host-gateway` dans le compose → depuis toute
session, `nas.internal` = l'hôte NAS (172.17.0.1). Utiliser `http://nas.internal:3232` (Gitea),
`:9000` (Portainer), `:8787` (NyoraNotes)… au lieu de mémoriser 172.17.0.1.

View File

@ -1,106 +0,0 @@
# Migration provider IA → OpenCode Go (+ fallback OpenRouter)
**Instance auteur** : hermes-perso (transverse aux 3)
**Date** : 2026-06-14
**Tags** : infra, opencode, hermes, family-help, llm, fallback
**Statut** : valide
---
## Probleme
Basculer le provider IA par defaut de OpenRouter vers OpenCode Go (endpoint
`zen/go/v1`), tout en gardant DeepSeek V4 Flash et un fallback OpenRouter.
Concerne les 3 agents Hermes (gateway) + l'app family-help (module medical).
---
## Contexte et contraintes
- Image `nousresearch/hermes-agent:latest`, source montee dans `/opt/hermes`.
- Les 3 Hermes sont des **stacks Portainer** : 291=nyora, 292=perso (path-based,
compose sur le FS), 294=TT (compose **inline** dans Portainer). Le
`docker-compose.yml` top-level de `hermes-platform/` est OBSOLETE.
- 1 seul abonnement OpenCode Go, plusieurs cles tirant du meme pool (~60$/mois).
- `/Volumes/docker` (Mac) = mount SMB du NAS `/volume1/docker`.
---
## Ce qui NE fonctionne PAS
| Tentative | Erreur obtenue | Raison de l'echec |
|-----------|----------------|-------------------|
| `docker compose up` depuis `hermes-platform/` (top-level) | `Conflict. The container name is already in use` | Les containers appartiennent aux stacks per-instance, pas au compose top-level |
| `hermes model` / `hermes fallback add` en SSH | `requires an interactive terminal` | Pickers interactifs → editer le YAML directement |
| Provider custom dans `providers:` | inutile | `opencode-go` est deja BUILT-IN (models.dev) |
| family-help medical `max_tokens: 512` | `finish_reason=length`, `content` VIDE | Modele de raisonnement : reasoning_content mange le budget avant le content |
---
## Solution validee
Provider built-in `opencode-go` : base_url `https://opencode.ai/zen/go/v1`,
cle via env var **`OPENCODE_API_KEY`**, model `deepseek-v4-flash` (sans prefixe).
OpenRouter (fallback) garde `deepseek/deepseek-v4-flash`.
```yaml
# data/config.yaml (gateway) — pour chaque instance
model:
default: deepseek-v4-flash
provider: opencode-go
fallback_providers:
- provider: openrouter
model: deepseek/deepseek-v4-flash
key_env: OPENROUTER_API_KEY
```
```bash
# perso / nyora (stacks path-based) : ajouter OPENCODE_API_KEY au .env + au compose
# - OPENCODE_API_KEY=${OPENCODE_API_KEY}
cd /volume1/docker/hermes-platform/hermes-perso
docker compose up -d --force-recreate hermes-agent-perso
# TT (stack 294 inline) : via API Portainer
# GET /api/stacks/294/file → inserer "- OPENCODE_API_KEY=<cle>" → PUT /api/stacks/294?endpointId=2
```
family-help : `medical_service.py` → helper `_llm_complete()` (OpenCode primaire,
OpenRouter fallback), **`max_tokens: 2048`**, cle `BIFROST_OPENCODE_KEY`.
`docker compose build --no-cache && docker compose up -d --force-recreate`.
---
## Verification
```bash
docker exec hermes-agent-<inst> hermes fallback ls
# Attendu : Primary deepseek-v4-flash (via opencode-go)
# Test end-to-end
docker exec hermes-agent-<inst> curl -s -H "Authorization: Bearer <API_SERVER_KEY>" \
-H 'Content-Type: application/json' \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"dis OK"}],"max_tokens":40}' \
http://localhost:8642/v1/chat/completions
# Attendu : HTTP 200, content non vide
# Test fallback : pointer OPENCODE_GO_BASE_URL vers un hote injoignable → reponse via OpenRouter (200)
```
---
## Pieges specifiques DSM / NAS
- `docker` n'est PAS dans le PATH SSH → utiliser `/usr/local/bin/docker`.
- Ne jamais editer le docker-compose top-level (obsolete) ; identifier la vraie source
via `docker inspect <c> --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'`.
- TT = stack inline Portainer → API Portainer, pas le FS (sudo requis sinon).
- DeepSeek V4 Flash (OpenCode) = reasoning model → `max_tokens` >= 2048 pour les
apps maison qui parsent du JSON (Hermes gere nativement).
---
## References
- https://opencode.ai/docs/zen
- https://hermes-agent.nousresearch.com/docs/user-guide/features/fallback-providers
- NyoraNotes : note 416da848 (capitalisation), note 26c38f8c (missions)

View File

@ -1,42 +0,0 @@
# nyora-doc-api — Footer Nyora jamais implémenté pour DOCX
**Date** : 2026-07-03
## Constat
Confirmé sur 3 générations réelles consécutives (PMI_Infinity_Formation v1, v2, v3,
via Perso) : le DOCX produit par `nyora-doc-api` n'a jamais eu qu'un footer
"Page X / Y". Le footer Nyora obligatoire (liseré or, "· NYORA ·", tagline
"Crafted with precision · Built for excellence", "© 2026") n'existe que côté
PPTX/PDF (`_wrap_html_with_nyora_theme`, `_get_nyora_pdf_css`) — jamais côté DOCX.
Vérifié dans le `.pyc` compilé avant le "premium upgrade" du 01/07 (commit
cbe8cf1) : la fonction n'y était pas non plus. Ce n'est donc pas une régression
du upgrade, c'est un trou jamais comblé depuis la création du service.
## Fix
`/mnt/docker/nyora-doc-api/app/services.py`, fonction
`_add_docx_page_number_footer` : ajout de 3 paragraphes avant la pagination
existante — bordure supérieure de paragraphe couleur `B8862A` (simule le liseré
or), "· NYORA ·" gras or 8pt, tagline slate italique 7pt, "© 2026" slate 7pt.
Backup pris avant patch : `services.py.bak_<timestamp>`.
## Bloquant — PAS ENCORE ACTIF
`/app` n'est **pas** bind-mounté dans le container `nyora-doc-api` (seul `/data`
l'est) — le code est baké dans l'image `nyora-doc-api:latest` au build. Un
`docker restart` ne suffit pas (vérifié en conditions réelles : patch appliqué
sur le host, container redémarré, footer toujours absent en test `/v1/generate`
direct).
## Reste à faire
`docker compose build` (Dockerfile présent dans `/mnt/docker/nyora-doc-api/`)
puis recréer le container. Jamais fait sans accord explicite (service qui sert
TT et Nyora en production). Tester ensuite avec un appel `/v1/generate` direct
(format docx, `data` minimal) et vérifier `word/footer1.xml` contient bien les
runs "NYORA" / tagline / copyright avant de considérer le correctif déployé.
Étape finale une fois validé : `git add . && git commit && git push` depuis le
compte bolbol sur le repo `bolbol/nyora-doc-api`.

View File

@ -1,30 +0,0 @@
# Runbook — Rebuild & déploiement nyora-doc-api (footer Nyora DOCX)
**Date** : 04/07/2026 · **Statut** : validé en production
## Problème
Le footer Nyora (liseré or → · NYORA · → tagline → © 2026) n'a jamais existé dans les DOCX générés par nyora-doc-api. Le fix était écrit dans `app/services.py` (`_add_docx_page_number_footer`) mais inactif : **`/app` est cuit dans l'image Docker, pas bind-mounté** — toute modification de code exige un rebuild.
## Procédure validée (depuis mcp-nas)
1. **Docker indisponible dans le container mcp-nas** → passer par SSH host : `ssh -p 22222 Best0f@172.17.0.1` (clé ed25519 en place dans ~/.ssh du container). Sur le host : docker = `/usr/local/bin/docker`, **sans sudo** (Best0f dans le groupe docker ; sudo échoue, pas de TTY).
2. Build : `cd /volume1/docker/nyora-doc-api && /usr/local/bin/docker compose build` (~2 min, pip timeout 180 déjà dans le Dockerfile).
3. Déploiement : `docker stop nyora-doc-api && docker rm nyora-doc-api && docker compose up -d` — jamais de simple restart, l'image ne serait pas rechargée.
4. Health : `curl http://172.17.0.1:3050/health` → 200.
## Test /v1/generate — pièges
- Endpoint **multipart/form-data**, pas JSON : `curl -F "format=docx" -F "data=</tmp/data.json"` + header `X-API-Key` (clé dans hermes-platform/.env). Un POST -d JSON → 422 "body.format missing".
- Payload avec apostrophes françaises : toujours l'écrire dans un fichier, jamais inline.
## Vérification du footer (sans ouvrir Word)
```python
import zipfile, re
xml = zipfile.ZipFile('doc.docx').read('word/footer1.xml').decode()
re.findall(r'<w:t[^>]*>([^<]*)</w:t>', xml) # textes du footer
'B8862A' in xml # liseré + NYORA doré
```
Attendu : `· NYORA ·`, `Crafted with precision · Built for excellence`, `© 2026`, pagination.
## Notes
- Couleur or : **#B8862A (Or Bruni, charte doc-api WCAG AAA)**, pas le #d4a01a de la règle générale footer — divergence assumée, à arbitrer.
- **Git existe sur le host NAS** (`/usr/bin/git`) — l'ancienne consigne « git depuis le Mac uniquement » est périmée. Push : `git push http://bolbol:PWD@127.0.0.1:3232/bolbol/REPO.git HEAD` depuis le host.
- Heredoc contenant du python multi-lignes dans mcp-nas → hang/timeout. Transférer les fichiers en base64 chunké (~290 chars) et décoder sur place.

View File

@ -0,0 +1,28 @@
# nyora-doc-api — Procédure de rebuild & déploiement
**Date** : 2026-07-09 (généralise nyora-doc-api-rebuild-footer-docx.md 04/07 ; historique footer clos)
**Tags** : infra, nyora-doc-api, docker, rebuild
## Règle de base
**`/app` est cuit dans l'image Docker, pas bind-monté** → toute modification de code dans `/mnt/docker/nyora-doc-api/app/` exige un **rebuild + recreate**. Un simple restart ne recharge rien.
## Procédure validée (depuis mcp-nas ou Mac)
1. Docker indisponible dans mcp-nas (socket retiré, audit 08/07) → passer par le Mac : `ssh -p 22222 Best0f@192.168.100.33`. Sur le host : docker = `/usr/local/bin/docker`, **sans sudo** (Best0f dans le groupe docker ; sudo échoue, pas de TTY).
2. Build : `cd /volume1/docker/nyora-doc-api && /usr/local/bin/docker compose build` (~2 min, pip timeout 180 déjà dans le Dockerfile).
3. Déploiement : `docker stop nyora-doc-api && docker rm nyora-doc-api && docker compose up -d`**jamais un simple restart**, l'image ne serait pas rechargée. Alternative sans SSH : `nohup` côté host (cf. session 08/07).
4. Health : `curl http://172.17.0.1:3050/health` → 200.
5. Vérifier code container == disque == Gitea : `docker exec nyora-doc-api cat /app/services.py | diff - /volume1/docker/nyora-doc-api/app/services.py`.
## Test /v1/generate — pièges
- Endpoint **multipart/form-data**, pas JSON : `curl -F "format=docx" -F "data=</tmp/data.json"` + header `X-API-Key` (clé dans hermes-platform/.env). Un POST -d JSON → 422 "body.format missing".
- Payload avec apostrophes françaises : toujours dans un fichier, jamais inline.
## Historique (clos)
- 03-04/07 : footer Nyora ajouté aux DOCX (n'avait jamais existé) puis déployé.
- **08/07 (commits a7380268 + f7353419) : footers retirés de TOUS les formats** (DOCX/PPTX/PDF/XLSX) sur décision Nabil, et option `restyle=full` implémentée pour le mode template (voir common/nyora-doc-api-template-restyle-cause-racine.md). Les vérifications XML de footer des anciennes versions ne s'appliquent plus.
Guide d'usage API : common/nyora-doc-api-hermes-guide.md.

View File

@ -0,0 +1,65 @@
# Migration provider → OpenCode Go (consolidé)
**Date** : 2026-07-09 (fusionne migration-provider-opencode-go.md 14/06 + OPENCODE-GO-MIGRATION.md 16/06 ; état mis à jour)
**Tags** : infra, opencode, hermes, family-help, bifrost, fallback
## État actuel des modèles (09/07/2026)
| Instance | model.default | Fallback |
|---|---|---|
| hermes-tt | deepseek-v4-flash (opencode-go) | opencode-go/deepseek-v4-flash |
| hermes-nyora | **mimo-v2.5** (verdict pilote 08/07 : GARDER — voir hermes-nyora/verdict-pilote-mimo-v25.md) | opencode-go/deepseek-v4-flash |
| hermes-perso | deepseek-v4-flash (opencode-go) | opencode-go/deepseek-v4-flash |
⚠️ Depuis le 06/07, les fallbacks pointent vers **opencode-go** (forfait) et non plus openrouter (payant) — voir common/bifrost-vk-incidents.md.
**Source de vérité compose** : `/volume1/docker/hermes-platform/docker-compose.yml` (top-level), confirmé par le fix DNS du 09/07 (recreate des 3 agents). Les compose per-instance sont en `.disabled` ; les mentions historiques « stacks Portainer 291/292/294, top-level obsolète » ne sont plus valables.
## Endpoint & modèles OpenCode Go
Provider built-in `opencode-go` : base_url `https://opencode.ai/zen/go/v1`, auth `Authorization: Bearer <clé>` uniquement (pas de x-bf-vk, pas de HTTP-Referer/X-Title). IDs **sans préfixe** (`deepseek-v4-flash`, `glm-5.1`, `mimo-v2.5`…), jamais `openrouter/` ni `deepseek/`.
Utilisables en OpenAI-compat : deepseek-v4-flash/pro, glm-5/5.1, qwen3.6/3.7-plus, kimi-k2.6, kimi-k2.7-code, minimax-m3, mimo-v2.5(-pro).
**NE FONCTIONNE PAS** :
- `qwen3.7-max``Model not supported for format oa-compat` (dispo seulement format Anthropic). Consommateurs OpenAI-compat → `glm-5.1`.
- MiniMax M2.7 vision = `prompt_tokens:0` (vision cassée). Vision/OCR → Gemini via Bifrost.
## config.yaml Hermes
`/volume1/docker/hermes-platform/hermes-{tt,nyora,perso}/data/config.yaml` :
```yaml
model:
default: <modele>
provider: opencode-go
fallback_providers:
- provider: opencode-go
model: deepseek-v4-flash
key_env: OPENCODE_GO_API_KEY # nom réel injecté par le compose top-level (PAS OPENCODE_API_KEY)
```
Hermes **réécrit config.yaml au shutdown** → toujours `docker stop` → éditer → `docker start` (jamais éditer à chaud). Healthcheck port 8642, API `/v1/chat/completions`, modèle proxy `hermes-agent`.
⚠️ data/ en 0700 uid 1026 : illisible depuis mcp-nas post-hardening — édition via Mac ou canal autorisé.
## family-help
`medical_service.py` → helper `_llm_complete()` (OpenCode primaire, OpenRouter fallback web/erreur), routing par skill : medical/nutrition glm-5.1, homework qwen3.7-plus, legal_admin deepseek-v4-pro, tech/general deepseek-v4-flash. **`max_tokens ≥ 2048`** obligatoire (modèles de raisonnement : le reasoning mange le budget avant le content → `finish_reason=length`, content vide). Même piège vu sur mimo-v2.5 (fix : max_tokens 8192 sur hermes-nyora).
## Bifrost (rappel)
Bifrost ne recharge PAS les clés provider au restart → `config.json` chargé au boot + `allow_all_keys=1` en DB. Providers dans config.json ≠ store (`DELETE FROM config_providers/config_keys`, bifrost stoppé). Éditer via l'UI peut re-casser. Détails : common/bifrost-access.md et common/bifrost-vk-incidents.md.
## n8n
- Code nodes LLM → Bifrost obligatoire (common/runbook-n8n-llm-bifrost.md). `require('https')` + parsing manuel, jamais fetch/new URL/$helpers.
- 15 workflows AO/veille archivés contiennent encore OpenRouter : l'API n8n refuse d'éditer un archivé. Pour réutiliser : désarchiver (UI) → migrer le Code node (endpoint zen/go/v1, clé OpenCode, retirer HTTP-Referer/X-Title) → re-tester → ré-archiver.
- Restent volontairement sur OpenRouter direct : `Mode-nedya`, `FAMILLE | Recettes Weekend`, `Labellisation Auto`.
## Pièges DSM/NAS
- `docker` hors PATH SSH → `/usr/local/bin/docker` (Best0f groupe docker, sans sudo).
- `hermes model` / `hermes fallback add` en SSH → « requires an interactive terminal » → éditer le YAML.
- Vérif : `docker exec hermes-agent-<i> hermes fallback ls` + test curl `localhost:8642/v1/chat/completions`.
## Références
- https://opencode.ai/docs/zen · hermes-agent.nousresearch.com/docs (fallback-providers)
- hermes-nyora/verdict-pilote-mimo-v25.md · common/bifrost-vk-incidents.md

View File

@ -1 +0,0 @@

View File

@ -1 +0,0 @@
- vps-contabo-reinstall-tailscale-07-07.md — Réinstallation VPS + bascule wg-admin custom → Tailscale, pièges mcp-nas/tailnet et tailscale up non-interactif

View File

@ -1 +0,0 @@

View File

@ -1,238 +0,0 @@
# Ports Registry — NAS Synology DS920+
# Derniere mise a jour : 4 juillet 2026
# LIRE CE FICHIER AVANT TOUT NOUVEAU DEPLOIEMENT
# Mettre a jour apres chaque ajout/suppression de service
---
## Regle absolue
Aucun nouveau service ne doit utiliser un port deja occupe.
Choisir un port libre et l'inscrire ici avant de deployer.
---
## SERVICES ACTIFS — Etat au 4 juillet 2026
Cette section est la source de verite sur ce qui tourne reellement.
Mise a jour obligatoire a chaque deploiement ET a chaque suppression.
| Service | Port | URL / Domaine | Statut | Notes |
|----------------------|-------|------------------------------|----------|------------------------------------|
| n8n | 5678 | n8n.bolbol.tn | ACTIF | Orchestration centrale |
| Baserow | 3888 | baserow.bolbol.tn | ACTIF | Base de donnees metier |
| Gitea | 3232 | gitea.bolbol.tn | ACTIF | Versioning (compte bolbol) |
| Portainer | 9000 | portainer.bolbol.tn | ACTIF | Gestion containers |
| NyoraNotes | 8787 | - | ACTIF | Memoire inter-sessions Hermes |
| linux-mcp-nas | 3042 | mcp-nas.nd.i234.me | ACTIF | MCP shell NAS |
| Bifrost | 3085 | bifrost.bolbol.tn | ACTIF | Gateway LLM |
| bifrost-proxy | 3086 | - | ACTIF | Auth rewrite + cap 16384 tokens |
| hermes-workspace-tt | 3010 | hermes-tt.bolbol.tn | ACTIF | Hermes TT workspace |
| hermes-workspace-nyora| 3020 | hermes-nyora.bolbol.tn | ACTIF | Hermes Nyora workspace |
| hermes-workspace-perso| 3030 | hermes-perso.bolbol.tn | ACTIF | Hermes Perso workspace |
| hermes-agent-tt | 8650 | interne Docker | ACTIF | Agent TT |
| hermes-agent-nyora | 8660 | interne Docker | ACTIF | Agent Nyora |
| hermes-agent-perso | 8670 | interne Docker | ACTIF | Agent Perso |
| gsparc-mezzouna | 3040 | gsparc-mezzouna.bolbol.tn | ACTIF | OCR carburant kimi-k2.6 |
| family-help | 3041 | help.bolbol.tn | ACTIF | Assistant famille |
| hermes-mail-proxy | 3060 | - | ACTIF | Proxy mail Hermes |
| nyora-doc-api | 3050 | - | ACTIF | API doc DOCX/XLSX/PPTX/PDF/HTML/CSV|
| pptx-tt-api | 8015 | - | ACTIF | PPTX charte TT |
| Tika | 9998 | - | ACTIF | Extraction documents |
| Paperless | 8021 | paperless.bolbol.tn | ACTIF | GED |
| Trilium | 4292 | trilium.bolbol.tn | ACTIF | Notes |
| Pingvin-Share | 6090 | share.bolbol.tn | ACTIF | Partage fichiers |
| WireGuard (wg-easy) | 51820 | - | ACTIF | VPN UDP |
| wg-easy UI | 51821 | vpn.bolbol.tn | ACTIF | Interface WireGuard |
| Family Help | 3041 | help.bolbol.tn | ACTIF | IA familiale FastAPI+SQLite |
| nyora-veille | 3055 | veille.bolbol.tn | ACTIF | Veille IA vanilla JS/nginx |
| veille-backend | 8000 | interne Docker | ACTIF | Backend veille FastAPI |
| gsparc-mezzouna | — | gsparc-mezzouna.bolbol.tn | ACTIF | Gestion carburant fleet |
| rla-api | 3005 | - | ACTIF | RLA contrats TT |
| document-factory | 3015 | - | ACTIF | Usine documentaire |
| Plex | 32400 | - | ACTIF | Media |
| Radarr | 7878 | - | DESINSTALLÉ 04/07/2026 | Supprimé avec media-stack |
| Sonarr | 8989 | - | DESINSTALLÉ 04/07/2026 | Supprimé avec media-stack |
| Prowlarr | 9696 | - | DESINSTALLÉ 04/07/2026 | Supprimé avec media-stack |
| Open WebUI | 3091 | — | DESINSTALLE | |
| panda-dashboard | 3021 | panda.bolbol.tn | ACTIF | Dashboard Fiat Panda nginx:alpine |
| redaction-pro | 3092 | llm.bolbol.tn | ACTIF | Assistant redaction LLM (proxy Bifrost) |
---
## Hermes Platform
| Port | Service | Reseau | Exposition |
|------|--------------------------|---------|---------------------------------------------------|
| 3010 | hermes-workspace-tt | n8n | 0.0.0.0 |
| 3020 | hermes-workspace-nyora | n8n | 0.0.0.0 |
| 3030 | hermes-workspace-perso | n8n | 0.0.0.0 |
| 8650 | hermes-agent-tt | n8n | interne Docker uniquement |
| 8660 | hermes-agent-nyora | n8n | interne Docker uniquement |
| 8670 | hermes-agent-perso | n8n | interne Docker uniquement |
> Maintenance Hermes : apres CHAQUE mise a jour des images, executer
> `/usr/local/bin/docker image prune -f` (builds :latest quotidiens empilent ~3.3GB).
> `scripts/cleanup-backups.sh` pour rotation data.bak (garde 2 derniers jeux).
---
## Stack Documentaire
| Port | Service | Reseau | Exposition |
|------|--------------------------|---------|---------------|
| 3001 | gotenberg | n8n | 0.0.0.0 |
| 3002 | pandoc | n8n | 0.0.0.0 |
| 3003 | docx-generator | n8n | 127.0.0.1 |
| 3005 | rla-api | n8n | 0.0.0.0 |
| 3015 | document-factory | n8n | 0.0.0.0 |
| 4000 | carbone | n8n | 0.0.0.0 |
| 5099 | reglement-definitif-api | n8n | 0.0.0.0 |
| 8002 | document-factory-api | n8n | 0.0.0.0 |
| 8015 | pptx-tt-api | n8n | 0.0.0.0 |
| 9998 | tika | n8n | 0.0.0.0 |
---
## AI Gateway
| Port | Service | Reseau | Exposition | Notes |
|------|--------------------------|---------|---------------|------------------------------------|
| 3085 | bifrost | n8n | 0.0.0.0 | Gateway LLM multi-modeles |
| 3086 | bifrost-proxy | n8n | 0.0.0.0 | Auth rewrite + cap max_tokens |
---
## Applications
| Port | Service | Reseau | Exposition |
|-------|--------------------------|---------|---------------|
| 3041 | family-help | n8n | 0.0.0.0 |
| 3042 | linux-mcp-nas | n8n | 0.0.0.0 |
| 3055 | nyora-veille frontend | n8n | 0.0.0.0 |
| 3232 | gitea | bridge | 0.0.0.0 |
| 3888 | Baserow | n8n | 0.0.0.0 |
| 4292 | Trilium | n8n | 0.0.0.0 |
| 4501 | Obsidian-Remote | bridge | 0.0.0.0 |
| 5678 | n8n | n8n | 0.0.0.0 |
| 6090 | Pingvin-Share | bridge | 0.0.0.0 |
| 8000 | veille-backend | n8n | interne |
| 8021 | paperless | n8n | 127.0.0.1 |
| 8085 | dashboard-terrain | n8n | 0.0.0.0 |
| 8787 | nyora-notes | n8n | 0.0.0.0 |
| 9000 | portainer | bridge | 0.0.0.0 |
| 9443 | portainer (https) | bridge | 0.0.0.0 |
| 51820 | wg-easy (WireGuard) | host | 0.0.0.0 UDP |
| 51821 | wg-easy UI | host | 0.0.0.0 |
| 27123 | Obsidian-Remote sync | bridge | 0.0.0.0 |
| 27124 | Obsidian-Remote sync | bridge | 0.0.0.0 |
---
## Media
| Port | Service | Reseau | Exposition |
|-------|--------------------------|--------------------|---------------|
| 6881 | qbittorrent | media-stack_default| 0.0.0.0 |
| 7878 | radarr | — | DESINSTALLÉ |
| 8191 | flaresolverr | media-stack_default| 0.0.0.0 |
| 8989 | sonarr | — | DESINSTALLÉ |
| 9696 | prowlarr | — | DESINSTALLÉ |
| 9866 | qbittorrent UI | media-stack_default| 0.0.0.0 |
| 32400 | Plex | media-stack_default| local |
---
## Bases de donnees (internes uniquement)
| Port | Service | Exposition |
|-------|--------------------------|---------------|
| 5432 | postgres (multiple DBs) | 127.0.0.1 |
| 6379 | redis (multiple) | local |
---
## DSM Systeme
| Port | Service | Exposition |
|-------|--------------------------|---------------|
| 80 | DSM HTTP | 0.0.0.0 |
| 222 | DSM SSH alternatif | 0.0.0.0 |
| 443 | DSM HTTPS | 0.0.0.0 |
| 2222 | Gitea SSH | 0.0.0.0 |
| 6690 | DSM Cloud Sync | 0.0.0.0 |
| 8080 | DSM / watchtower | 0.0.0.0 |
| 22222 | NAS SSH (port principal) | 0.0.0.0 |
---
## Plages libres recommandees
| Plage | Usage suggere |
|-------------|--------------------------------------|
| 3021 | OCCUPE - panda-dashboard (depuis 20/06/2026) |
| 3040-3099 | Extensions Hermes / nouveaux agents |
| 3091 | LIBRE (Open WebUI desinstalle 23/06/2026 + 29/06/2026 confirm) |
| 3092 | OCCUPE - redaction-pro (depuis 23/06/2026) |
| 3093 | OCCUPE - context-hub (depuis 24/06/2026) |
| 3013 | LIBRE (rayhan-frontend desinstalle 29/06/2026) |
| 3001 | LIBRE (Gotenberg desinstalle 21/06/2026) |
| 3002 | LIBRE (Pandoc desinstalle 21/06/2026) |
| 3015 | LIBRE (document-factory desinstalle 21/06/2026) |
| 7878 | LIBRE (Radarr desinstalle 04/07/2026) |
| 8989 | LIBRE (Sonarr desinstalle 04/07/2026) |
| 9696 | LIBRE (Prowlarr desinstalle 04/07/2026) |
| 8015 | LIBRE (pptx-tt-api desinstalle 29/06/2026) — remplace par nyora-doc-api port 3050 |
| 3100-3199 | APIs internes |
| 8800-8899 | UIs web supplementaires |
| 8900-8999 | Services experimentaux |
---
## Ports a ne JAMAIS utiliser
- 8787 : nyora-notes (conflit hermes-webui par defaut)
- 3000 : port interne Docker (ne pas exposer)
- 5432 : postgres (interne uniquement)
- 22 : SSH DSM interne (utiliser 22222)
---
## Historique des modifications
| Date | Action | Port | Service |
|------------|-------------------------------------|-------|--------------------------|
| 2026-05-28 | Creation initiale du registre | — | — |
| 2026-05-28 | Deploiement hermes-nyora-webui | 3021 | hermes-nyora-webui |
| 2026-06-05 | Deploiement linux-mcp-nas | 3042 | linux-mcp-nas |
| 2026-06-05 | Migration WireGuard VPN vers NAS | 51820 | wg-easy |
| 2026-06-05 | Migration WireGuard UI vers NAS | 51821 | wg-easy UI |
| 2026-06-08 | Deploiement dashboard-terrain | 8085 | dashboard-terrain |
| 2026-06-09 | Deploiement Open WebUI | 3091 | open-webui |
| 2026-06-09 | Deploiement hermes-dashboard | 3092 | hermes-dashboard |
| 2026-06-11 | Deploiement nyora-veille | 3055 | veille-frontend |
| 2026-06-11 | Deploiement veille-backend | 8000 | veille-backend (interne) |
| 2026-06-15 | DESINSTALLATION hermes-nyora-webui | 3021 | LIBRE |
| 2026-06-15 | DESINSTALLATION hermes-dashboard | 3092 | LIBRE |
| 2026-06-16 | Deploiement Bifrost + bifrost-proxy | 3085 | bifrost |
| 2026-06-16 | Deploiement bifrost-proxy | 3086 | bifrost-proxy |
| 2026-06-16 | Ajout section Services Actifs | — | ports-registry.md v2 |
| 2026-06-20 | Deploiement panda-dashboard | 3021 | panda-dashboard nginx |
| 2026-06-21 | DESINSTALLATION document-factory | 3015 | LIBRE |
| 2026-06-21 | DESINSTALLATION pandoc | 3002 | LIBRE |
| 2026-06-21 | DESINSTALLATION gotenberg | 3001 | LIBRE |
| 2026-06-21 | DESINSTALLATION carbone | 4000 | LIBRE |
| 2026-06-21 | DESINSTALLATION document-factory-api| 8002 | LIBRE |
| 2026-06-23 | Deploiement redaction-pro | 3092 | redaction-pro |
| 2026-06-23 | DESINSTALLATION Open WebUI | 3091 | LIBRE — remplace par redaction-pro |
| 2026-06-23 | Deploiement redaction-pro FINAL | 3092 | llm.bolbol.tn |
| 2026-06-24 | Deploiement context-hub | 3093 | context-hub (context.bolbol.tn) |
| 2026-06-27 | Deploiement paperclip | 3094 | paperclip (paperclip.bolbol.tn) |
| 2026-06-29 | DESINSTALLATION rayhan-frontend | 3013 | LIBRE — projet clos |
| 2026-06-29 | DESINSTALLATION rayhan-mysql | 3306 | LIBRE — volume mysql_data supprime|
| 2026-06-29 | DESINSTALLATION pptx-tt-api | 8015 | LIBRE — remplace par nyora-doc-api (3050) |
| 2026-06-29 | Images Docker supprimees | — | -4.6 GB (open-webui:4.5GB + rayhan-frontend:95MB) |
| 2026-06-29 | DESINSTALLATION open-webui (DEFINITIF)| 3091 | LIBRE — remplace par redaction-pro (3092) |
| 2026-07-04 | DESINSTALLATION Radarr | 7878 | LIBRE — supprime avec media-stack |
| 2026-07-04 | DESINSTALLATION Sonarr | 8989 | LIBRE — supprime avec media-stack |
| 2026-07-04 | DESINSTALLATION Prowlarr | 9696 | LIBRE — supprime avec media-stack |
| 2026-07-04 | Images Docker supprimees | — | -585 MB (sonarr:193MB + prowlarr:184MB + radarr:208MB) |