4e23828dae
Stacks gitea (1.26.4, git.pogoo.app) et n8n-chlova (2.20.8, n8n-chlova.pogoo.app) déployés via Portainer sur l'hôte local (réseau proxy), versionnés dans infra/. docker-compose.prod.yml recâblé pour le tout-local (MCP_N8N_URL n8n-chlova, PORTAINER_URL interne, sidecar sur proxy). Runbook deploy.md réécrit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016w5jRe87MGdd6AMvXQcHNi
327 lines
17 KiB
Markdown
327 lines
17 KiB
Markdown
# Changelog
|
|
|
|
Format [Keep a Changelog](https://keepachangelog.com/), versioning [SemVer](https://semver.org/).
|
|
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.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ôte
|
|
`local` (réseau `proxy`, `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) sur
|
|
`local` (`n8n-chlova.pogoo.app`), MCP natif interne `http://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éseau
|
|
`proxy`, joignable en interne par nom de conteneur.
|
|
- `docker-compose.prod.yml` : `MCP_N8N_URL` → `n8n-chlova`, `PORTAINER_URL` →
|
|
interne `http://portainer:9000` (même hôte), sidecar `mcp-portainer` ajouté au
|
|
réseau `proxy` (pour joindre le serveur Portainer).
|
|
- `docs/deploy.md` réé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. Sans `env_file` (secrets via variables de stack), réseau Traefik
|
|
réel `proxy` (external), certresolver `letsencrypt`, backend joint `proxy`
|
|
pour atteindre n8n en interne. Cible : env `vps-pogoo-002`.
|
|
- **`docs/deploy.md`** : runbook Phase 1 — dépôt git, génération secrets,
|
|
users restreints `chlova` (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** (`telegramBotToken` optionnel ;
|
|
`index.ts` ne démarre la surface que si le token est présent). Permet le
|
|
déploiement **UI-only** voulu. `.env.example` documenté 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 en `expo-secure-store`, thème dark HUD, `EXPO_PUBLIC_API_BASE` configurable.
|
|
`tsc --noEmit` vert. STT mobile reporté (lib native) ; TTS OK.
|
|
- README racine : entrées `web/` et `mobile/`.
|
|
|
|
## [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
|
|
- `Review` consomme `appdata` (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 (jamais
|
|
`git 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) → alerte `asset_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/static` 9.1.3 + fallback routes
|
|
client) si `CHLOVA_WEB_ROOT` présent ; config `webRoot`.
|
|
### Changed
|
|
- Dockerfile multi-stage : build **web + API** (contexte = racine dépôt), image
|
|
embarque le SPA (`/app/web`, `CHLOVA_WEB_ROOT` par défaut). Compose : contexte
|
|
`..`, `dockerfile: orchestrator/Dockerfile`, image `chlova/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 via
|
|
`POST /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 build` OK, 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-public` externe,
|
|
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éutilise `ChatService` + `ReviewService`.
|
|
- Config auth API (`CHLOVA_ADMIN_USER/_PASSWORD_HASH/_TOTP_SECRET/_JWT_SECRET`,
|
|
`CHLOVA_WEB_ORIGIN`) + helper `apiAuth()` ; 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`), `login` tout-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 `jose` 6.2.3, `otplib` 13.4.1 (`npm audit` 0 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) — palier `privileged`.
|
|
### Changed
|
|
- `.env.example` + compose : variable `ALERT_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`,
|
|
sinon `NullAlertSender`.
|
|
- Gatekeeper : hook `onFirstProvisionalExec` (alerte immédiate à la 1ʳᵉ exécution
|
|
d'un asset PROVISOIRE) ; `onBlockedAttempt` route 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 purs `buildDailyDigest` / `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-n8n` du compose ; `MCP_N8N_URL` pointe 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.example`
|
|
mis à 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` : variable `CHLOVA_PHASE` (défaut 1),
|
|
note `PORTAINER_READ_ONLY` selon 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. Refactor `collect()` partagé.
|
|
- `buildSystemPrompt(phase)` : prompt phase-aware (lecture seule vs écriture sous
|
|
review), conserve le cadrage anti-prompt-injection.
|
|
- Câblage `index.ts` par phase : Phase 1 = read-only + `ReadOnlyGuard` ; Phase 2 =
|
|
tous outils + `GatekeeperGuard` sur `AssetRepository` (hook d'alerte sur asset
|
|
bloqué), `/health` reflète la phase, fermeture propre du repo.
|
|
|
|
## [0.11.0] — 2026-06-23
|
|
### Added
|
|
- `src/gatekeeper/gatekeeper.ts` : service `Gatekeeper` (vérifie le statut AVANT
|
|
chaque exécution) + `GatekeeperGuard`. Privilégié inconnu → enregistré BLOQUÉ,
|
|
refusé jusqu'à review, hook d'alerte `onBlockedAttempt` ; 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
|
|
- `assertReadOnlyPhase` devient phase-aware : Phase 1 exige read-only ; Phase 2
|
|
autorise `PORTAINER_READ_ONLY=false`.
|
|
|
|
## [0.10.0] — 2026-06-23 — début Phase 2 (écriture + need-review)
|
|
### Added
|
|
- `src/gatekeeper/repository.ts` : `AssetRepository` SQLite (`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 Dockerfile `node:24.13`,
|
|
`@types/node` 24, copie `tsconfig.build.json` dans l'image. `npm audit` 0 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é,
|
|
`assertNoEscalation` anti-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` (emit `dist/`, rootDir `src`).
|
|
|
|
## [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 que `reversible`+`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 build` vert.
|
|
|
|
## [0.7.0] — 2026-06-23
|
|
### Added
|
|
- `src/mcp/readonly-filter.ts` : barrière lecture seule — n'expose que les outils
|
|
`readOnlyHint === 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 en `ToolHandle`, sérialise les résultats.
|
|
### Changed
|
|
- `tsconfig` : retrait de `exactOptionalPropertyTypes` (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, `Guard` injecté
|
|
(abstraction prête pour le gatekeeper Phase 2). `ToolHandle` indé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.ts`
|
|
fail-closed (zod, verrou `assertReadOnlyPhase`, `redactedConfig`),
|
|
`audit/log.ts` (pino + journal d'exécutions), `index.ts` (bootstrap +
|
|
healthcheck interne), `Dockerfile` multi-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éseaux
|
|
`chlova-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/`.
|