2d3c944699
Image portainer-mcp 0.6.0 (inexistant) -> 2.42.6. Passerelle HTTP :17717/mcp attend Bearer (secret passerelle) + X-Portainer-API-Key (clé API restreinte chlova) : ajout config.portainerApiKey + McpServerConfig.extraHeaders, backend envoie les deux. socket-proxy supprimé (plus de socket monté). Compose prod, .env.example, deploy.md à jour. Typecheck + 78 tests verts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016w5jRe87MGdd6AMvXQcHNi
19 KiB
19 KiB
Changelog
Format Keep a Changelog, versioning SemVer.
Tant que le projet est en 0.x, chaque mineur peut introduire des changements
incompatibles. Chaque ligne renvoie à un commit dédié (un artefact = un commit).
[Unreleased]
[0.34.0] — 2026-06-23 — intégration réelle passerelle MCP Portainer
Fixed
- Image MCP Portainer :
portainer/portainer-mcp:0.6.0(tag inexistant) →2.42.6(confirmé Docker Hub). Découvert au déploiement réel (pull 404). - Modèle d'auth de la passerelle MCP Portainer corrigé : le serveur HTTP
(port 17717, endpoint
/mcp) attendAuthorization: Bearer <secret de passerelle>etX-Portainer-API-Key: <clé API restreinte>. Le backend n'envoyait que le Bearer.
Added
config.portainerApiKey(PORTAINER_API_KEY, SECRET) : clé API Portainer restreinte dechlova, envoyée enX-Portainer-API-Key— c'est elle qui cloisonne l'accès.PORTAINER_MCP_AUTH_TOKENdevient le secret de passerelle.McpServerConfig.extraHeaders: headers additionnels par serveur MCP.
Changed
docker-compose.prod.yml:mcp-portainerreconfiguré (2.42.6, :17717,PORTAINER_MCP_ALLOWED_HOSTS, plaintext HTTP interne,PORTAINER_TLS_VERIFY=0,PORTAINER_READ_ONLY).socket-proxysupprimé (la passerelle parle à l'API Portainer, plus aucun socket Docker monté = surface réduite).MCP_PORTAINER_URL→:17717/mcp. Backend reçoitPORTAINER_API_KEY..env.example+docs/deploy.md(§3a, tableau variables) mis à jour.- Typecheck vert, 78 tests verts.
[0.33.0] — 2026-06-23 — infra locale déployée (gitea + n8n-chlova)
Added
infra/gitea/docker-compose.yml: serveur git Gitea 1.26.4 sur l'hôtelocal(réseauproxy,git.pogoo.app), source du GitOps de CHLOVA. Déployé via Portainer (stack id 6, running).infra/n8n-chlova/docker-compose.yml: n8n dédié à CHLOVA (2.20.8) surlocal(n8n-chlova.pogoo.app), MCP natif internehttp://n8n-chlova:5678. Déployé via Portainer (stack id 7, running healthy).
Changed
- Topologie cible repliée sur un seul hôte (
local) : tout sur le réseauproxy, joignable en interne par nom de conteneur. docker-compose.prod.yml:MCP_N8N_URL→n8n-chlova,PORTAINER_URL→ internehttp://portainer:9000(même hôte), sidecarmcp-portainerajouté au réseauproxy(pour joindre le serveur Portainer).docs/deploy.mdréécrit pour la topologie locale (DNS, gitea, push, users restreints, déploiement GitOps, vérif).
[0.32.0] — 2026-06-23 — prêt au déploiement (GitOps Portainer, Phase 1)
Added
infra/docker-compose.prod.yml: compose de PRODUCTION pour GitOps Portainer. Sansenv_file(secrets via variables de stack), réseau Traefik réelproxy(external), certresolverletsencrypt, backend jointproxypour atteindre n8n en interne. Cible : envvps-pogoo-002.docs/deploy.md: runbook Phase 1 — dépôt git, génération secrets, users restreintschlova(Portainer + n8n, étapes UI), variables de stack, déploiement, vérification, rollback, bascule Phase 2.config.assertHasSurface(): refuse de démarrer si aucune surface (Telegram OU API/UI) n'est configurée. 3 tests (11 au total dans config).
Changed
- Surface Telegram rendue optionnelle (
telegramBotTokenoptionnel ;index.tsne démarre la surface que si le token est présent). Permet le déploiement UI-only voulu..env.exampledocumenté en conséquence. - Typecheck vert, 78 tests verts.
[0.31.0] — 2026-06-23 — app mobile (React Native / Expo)
Added
- Package
mobile/: app Expo SDK 56 (expo-router) réutilisant l'API backend. Écrans Login (mdp + TOTP), Chat (+ TTS expo-speech), Review (approuver/refuser). JWT enexpo-secure-store, thème dark HUD,EXPO_PUBLIC_API_BASEconfigurable.tsc --noEmitvert. STT mobile reporté (lib native) ; TTS OK. - README racine : entrées
web/etmobile/.
[0.30.0] — 2026-06-23 — polish UI
Added
- Icônes Lucide (SVG) partout (chat, voix, review, nav) — fini le texte/emoji.
- Contexte
appdata: état backend (phase/outils) + assets en attente partagés ; header affiche phase·outils, badge de review dans la nav, refresh après décision.
Changed
Reviewconsommeappdata(plus de fetch local). Build OK, 0 vuln.
[0.29.0] — 2026-06-23 — fin Phase 6 (voix v1)
Added
useSpeech: mode mains-libres + wake-word « CHLOVA » (extractCommand), écoute en boucle, micro en pause pendant le TTS (anti auto-écoute).- Chat : bouton "Libre" (mains-libres) ; en mains-libres les réponses sont lues d'office. Indicateur d'écoute. Build OK. (README web : section voix.)
[0.28.0] — 2026-06-23 — début Phase 6 (voix)
Added
web/src/useSpeech.ts: hook voix 100 % navigateur (Web Speech API), STT (push-to-talk, fr-FR) + TTS, dégrade proprement si non supporté. Zéro backend/GPU.- Chat : bouton micro (dicter → envoyer), bascule "Voix ON/OFF" (persistée) qui lit les réponses à voix haute. Pas d'emoji comme icône (texte). Build OK.
[0.27.0] — 2026-06-23 — fin Phase 5 (auto-extension v1)
Added
- Outil local
chlova.propose_asset(src/autoext/tool.ts) exposé à l'agent : propose un asset → write+commit+doc → need-review. Notion d'outil sanctionné (ToolSpec.sanctioned) autorisé par le gatekeeper mais audité. - Config
CHLOVA_AUTOEXT_ENABLED(défaut false) +CHLOVA_REPO_ROOT. Câblage Phase 2 + flag. Prompt système Phase 2 mis à jour (palier honnête imposé). - Tests (2) : gatekeeper autorise un outil sanctionné ; tool propose. 75 tests.
Changed
.env.example+ compose : flag autoext + montage dépôt (commenté).docs/need-review.md: section auto-extension. Compose revalidé, 0 vuln.
[0.26.0] — 2026-06-23
Added
src/autoext/git-committer.ts:GitCommitter— commits ciblés (jamaisgit add -A), auteur CHLOVA, renvoie le SHA.src/autoext/auto-extension.ts:AutoExtensionService.propose— write+doc → commit+version → enregistre l'asset en need-review (privilégié = BLOQUÉ, aucun sursis) → alerteasset_created(version + commit + doc). N'exécute jamais l'asset.- Alerte
asset_created. 3 tests (dépôt git temp). 73 tests, 0 vuln.
[0.25.0] — 2026-06-23 — début Phase 5 (auto-extension)
Added
src/autoext/artifact-writer.ts: écriture d'un asset auto-créé (artefact + doc générée depuis le gabarit), chemins sanitizés (anti-traversée), version semver validée.slugify,artifactRelPath,docRelPath,renderDoc,writeArtifact. 5 tests (dépôt temp).
[0.24.0] — 2026-06-23 — fin Phase 4 (UI v1 : chat + review)
Added
- UI : vue Review (
web/src/pages/Review.tsx) — liste des assets en attente, approuver / refuser (confirmation sur refus, palier coloré), refresh, 401→logout. - Backend sert le SPA same-origin (
@fastify/static9.1.3 + fallback routes client) siCHLOVA_WEB_ROOTprésent ; configwebRoot.
Changed
- Dockerfile multi-stage : build web + API (contexte = racine dépôt), image
embarque le SPA (
/app/web,CHLOVA_WEB_ROOTpar défaut). Compose : contexte..,dockerfile: orchestrator/Dockerfile, imagechlova/backend:0.2.0. Compose revalidé. 65 tests, 0 vuln.
[0.23.0] — 2026-06-23
Added
- UI : vue Chat (
web/src/pages/Chat.tsx) — conversation avec l'agent viaPOST /api/chat, bulles user/assistant, état "réfléchit", auto-scroll, gestion d'erreur, déconnexion auto sur 401. Build OK.
[0.22.0] — 2026-06-23
Added
- Package
web/: scaffold UI (React 19 + Vite 8 + Tailwind 4 + react-router 7, PWA). Tokens dark HUD "Jarvis-red" (docs/ui-design.md), client API (api.ts), contexte auth JWT (auth.tsx), shell + garde de route, écran Login (mdp + TOTP). Pages Chat/Review en stubs (v0.23/0.24).npm run buildOK, 0 vuln.
[0.21.0] — 2026-06-23
Added
orchestrator/scripts/provision-auth.ts(+npm run provision-auth) : génère hash mdp scrypt + secret TOTP + otpauth:// + JWT secret pour.env.- Compose : backend exposé via Traefik + TLS (réseau
traefik-publicexterne, labels router/tls),CHLOVA_DOMAIN. Surface unique exposée. .env.example: section API/UI (admin/hash/TOTP/JWT/web-origin/domaine).docs/security.md: section surface exposée Phase 4 (login fort, rate-limit, CORS, fail-safe). Compose revalidé.
[0.20.0] — 2026-06-23
Added
src/api/routes.ts: API HTTP (registerApi) —POST /api/auth/login(rate-limit serré), JWT Bearer sur le reste,POST /api/chat,GET /api/review,POST /api/review/:id/{approve,refuse},GET /api/state. CORS restreint + rate-limit global. RéutiliseChatService+ReviewService.- Config auth API (
CHLOVA_ADMIN_USER/_PASSWORD_HASH/_TOTP_SECRET/_JWT_SECRET,CHLOVA_WEB_ORIGIN) + helperapiAuth(); API activée seulement si configurée. - Câblage
index.ts(API montée si auth présente). Deps@fastify/cors,@fastify/rate-limitépinglées. 5 tests API (inject). 65 tests, 0 vuln.
[0.19.0] — 2026-06-23 — début Phase 4 (UI : auth + service chat)
Added
src/api/auth.ts: auth surface exposée — mot de passe scrypt (node:crypto), TOTP 2FA (otplib), JWT HS256 (jose),logintout-ou-rien. 10 tests.src/agent/chat-service.ts:ChatService(un tour d'agent par message), partagé par toutes les surfaces. Telegram refactoré pour l'utiliser.- Deps épinglées
jose6.2.3,otplib13.4.1 (npm audit0 vuln).
[0.18.0] — 2026-06-23 — fin Phase 3 (alertes)
Added
workflows-n8n/chlova-alerts.v1.0.0.json: workflow n8n webhook → mail (formate selon le type d'alerte). Exporté en JSON (le dépôt fait foi).docs/assets/workflow-chlova-alerts.md: doc d'asset (rôle, IO, deps, sécurité, rollback) — palierprivileged.
Changed
.env.example+ compose : variableALERT_WEBHOOK_URL(vide = log-only).docs/need-review.md: section alertes marquée implémentée. Compose revalidé.
[0.17.0] — 2026-06-23
Added
- Config
ALERT_WEBHOOK_URL(optionnel, traité comme secret) →HttpAlertSender, sinonNullAlertSender. - Gatekeeper : hook
onFirstProvisionalExec(alerte immédiate à la 1ʳᵉ exécution d'un asset PROVISOIRE) ;onBlockedAttemptroute désormais vers une vraie alerte. src/alerts/scheduler.ts:runAlertCycleOnce+startAlertScheduler(digest quotidien + rappel J-1). Câblé en Phase 2 (cron + alertes), arrêt propre.- Tests (3) : émission 1ʳᵉ exéc unique, cycle J-1 + digest.
[0.16.0] — 2026-06-23 — début Phase 3 (alertes)
Added
- Module
src/alerts/:AlertEvent(blocked / first-exec / J-1 / digest sans secret),HttpAlertSender(POST webhook n8n, fail-soft) +NullAlertSender(log-only fail-safe), builders pursbuildDailyDigest/selectExpiringSoon. - Tests alerts (6) : payload, fail-soft, digest, fenêtre J-1.
[0.15.1] — 2026-06-23
Changed
- Fige le chemin de l'endpoint MCP natif n8n :
MCP_N8N_URL = …/mcp-server/http(hôte interne préféré, URL publique TLS possible). Note egress (networks.md).
[0.15.0] — 2026-06-23
Changed
- MCP n8n = natif (instance n8n ≥ 2.18.4) au lieu d'un conteneur dédié :
suppression du service
mcp-n8ndu compose ;MCP_N8N_URLpointe vers l'endpoint MCP de l'instance n8n, auth par "MCP Access Token" (Bearer). MCP Portainer reste un sidecar officiel. Aucun changement de code (le registry parle déjà HTTP+Bearer). Docs (CLAUDE.md, architecture, networks) +.env.examplemis à jour. Compose revalidé (services : ollama, socket-proxy, mcp-portainer, backend).
[0.14.0] — 2026-06-23 — fin Phase 2 (écriture + need-review)
Added
docs/need-review.md: documentation complète du cycle (états, sursis, gatekeeper, cron, review, gate de phase, rollback).
Changed
.env.example+infra/docker-compose.yml: variableCHLOVA_PHASE(défaut 1), notePORTAINER_READ_ONLYselon phase.docs/risk-tiers.md,orchestrator/README.md: application par phase (P1 read-only / P2 gatekeeper). Compose revalidé.
[0.13.0] — 2026-06-23
Added
src/gatekeeper/review.ts:ReviewService(approuver/refuser/lister),runExpiryOnce+startExpiryCron(cron horaire PROVISOIRE→BLOQUÉ).src/surfaces/commands.ts: commandes owner Telegram/pending,/approve,/refuse,/help(hors boucle agent — le LLM n'y a pas accès).- Câblage Phase 2 : review + cron démarrés, routage commande/agent dans Telegram, arrêt propre du cron. 10 tests (review + commandes + cron).
[0.12.0] — 2026-06-23
Added
registry.listAllTools(): expose tous les outils (mutants inclus) en Phase 2, contrôle d'exécution délégué au gatekeeper. Refactorcollect()partagé.buildSystemPrompt(phase): prompt phase-aware (lecture seule vs écriture sous review), conserve le cadrage anti-prompt-injection.- Câblage
index.tspar phase : Phase 1 = read-only +ReadOnlyGuard; Phase 2 = tous outils +GatekeeperGuardsurAssetRepository(hook d'alerte sur asset bloqué),/healthreflète la phase, fermeture propre du repo.
[0.11.0] — 2026-06-23
Added
src/gatekeeper/gatekeeper.ts: serviceGatekeeper(vérifie le statut AVANT chaque exécution) +GatekeeperGuard. Privilégié inconnu → enregistré BLOQUÉ, refusé jusqu'à review, hook d'alerteonBlockedAttempt; approuvé → exécutable- incrément du compteur. Lecture seule → autorisée sans asset.
- Gate de phase
CHLOVA_PHASE(défaut 1, fail-safe) dans la config. - Tests gatekeeper service (5) + phase config (2).
Changed
assertReadOnlyPhasedevient phase-aware : Phase 1 exige read-only ; Phase 2 autorisePORTAINER_READ_ONLY=false.
[0.10.0] — 2026-06-23 — début Phase 2 (écriture + need-review)
Added
src/gatekeeper/repository.ts:AssetRepositorySQLite (node:sqlite, zéro dépendance native) — schema table assets, CRUD,listByStatus,incrementExec,setRiskTier(anti-escalade),expireProvisional(cron PROVISOIRE→BLOQUÉ).- Tests repository (6) : persistance, anti-escalade, expiration du sursis.
Changed
- Node 24 (sqlite natif stable) :
engines, base Dockerfilenode:24.13,@types/node24, copietsconfig.build.jsondans l'image.npm audit0 vuln.
[0.9.0] — 2026-06-23 — fin Phase 1 (cerveau lecture seule)
Added
src/gatekeeper/assets.ts: interfaces du cycle "need review" posées pour la Phase 2 (table Asset, sursis 7 j réversible / blocage immédiat privilégié,assertNoEscalationanti-escalade,canExecute). Non câblé au runtime P1.- Tests Vitest (22) :
readonly-filter(fail-safe + tiers),gatekeeper(Guard read-only, sursis par palier, invariant anti-escalade, canExecute),config(fail-closed, verrou lecture seule, masquage des secrets).
Changed
- Split TS config :
tsconfig.json(typecheck+tests, noEmit) /tsconfig.build.json(emitdist/, rootDirsrc).
[0.8.0] — 2026-06-23
Added
src/surfaces/telegram.ts: surface Telegram long-polling (zéro port publié), allowlist d'IDs obligatoire, backoff sur erreur.src/gatekeeper/guard.ts:ReadOnlyGuard(barrière n°2, défense en profondeur) — n'autorise quereversible+readOnly.src/agent/system-prompt.ts: cadrage anti-prompt-injection (données ≠ instructions).src/index.ts: câblage complet Phase 1 (MCP read-only → cerveau → Telegram), arrêt propre SIGTERM/SIGINT.npm run buildvert.
[0.7.0] — 2026-06-23
Added
src/mcp/readonly-filter.ts: barrière lecture seule — n'expose que les outilsreadOnlyHint === true(fail-safe : absence d'annotation ⇒ écarté) ; déduit le palier de risque (jamais déclaré par le LLM).src/mcp/registry.ts: connexion MCP HTTP authentifiée (n8n + Portainer), liste + filtre les outils read-only enToolHandle, sérialise les résultats.
Changed
tsconfig: retrait deexactOptionalPropertyTypes(interop SDK MCP) ; reste strict (strict,noUncheckedIndexedAccess,noImplicitOverride).
[0.6.0] — 2026-06-23
Added
- Client Ollama
/api/chat(src/llm/ollama.ts) : modèles cloud via proxy, auth Bearer, timeout, tool-calling, erreurs sans fuite de secret. - Boucle agent (
src/agent/loop.ts+types.ts) : comprendre → outil → observer → répondre, garde-fou anti-boucle, audit par appel,Guardinjecté (abstraction prête pour le gatekeeper Phase 2).ToolHandleindépendant de MCP.
[0.5.0] — 2026-06-23 — début Phase 1 (cerveau lecture seule)
Added
- Squelette orchestrateur TS (Node 22, ESM strict, Fastify) :
config.tsfail-closed (zod, verrouassertReadOnlyPhase,redactedConfig),audit/log.ts(pino + journal d'exécutions),index.ts(bootstrap + healthcheck interne),Dockerfilemulti-stage (base épinglée, user non-root),vitest.config.ts,orchestrator/README.md. - Dépendances épinglées,
npm audità 0 vulnérabilité.
[0.4.0] — 2026-06-23 — fin Phase 0 (socle)
Added
infra/docker-compose.yml: stack CHLOVA — Ollama (proxy cloud, interne + egress, aucun port publié), socket-proxy (lecture seule), MCP n8n + MCP Portainer (read-only), backend (seule surface, aucun port publié en P1). Images à tags épinglés (digests à confirmer avant déploiement réel), réseauxchlova-internal(internal) /chlova-egress. Config validée (compose config).
[0.3.0] — 2026-06-23
Added
- Socle sécurité :
docs/security.md(modèle de menace prompt-injection + défenses par couche + invariants testés),infra/networks.md(réseaux interne vs egress, ports, egress filtréollama.com),infra/socket-proxy/README.md(filtrage des endpoints Docker, lecture seule P1). .gitattributes: normalisation LF (scripts/compose en LF strict).
[0.2.0] — 2026-06-23
Added
- Conventions versioning/doc :
docs/versioning.md(SemVer, un-artefact-un-commit, pinning images, export workflows n8n),docs/asset-template.md(gabarit doc),docs/risk-tiers.md(réversible vs privilégié, invariant anti-escalade),docs/architecture.md(schéma + invariants + composants).
Changed
.gitignore: ignore.claude/settings.local.json(réglages locaux).
[0.1.0] — 2026-06-23
Added
- Scaffold du dépôt :
CLAUDE.md(architecture + règles non négociables),README.md,CHANGELOG.md,.env.example,.gitignore. - Squelette d'arborescence :
docs/,infra/,orchestrator/,workflows-n8n/.