Commit Graph

10 Commits

Author SHA1 Message Date
60f4b33e53 feat(backend): guard de fermeture "travail en cours" (#83)
Expose l'état du guard de sortie applicative (GetAppExitWorkGuardState) :
agents busy + tâches d'arrière-plan actives à travers tous les projets
ouverts, avec détails compacts pour la popup de confirmation. Le handler
CloseRequested d'app-tauri interroge ce guard avant de laisser la fenêtre
se fermer, et respecte la confirmation explicite de l'utilisateur
(EXIT_GUARD_CONFIRMED) pour ne pas la redemander en boucle.

QA vert (backend + frontend).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 19:18:39 +02:00
ef84d5cc49 feat(backend): MCP d'édition de templates (#81)
Ajoute le MCP dédié à l'édition de templates : catalogue et classification
des templates (mcp/templates.rs infrastructure + app-tauri), use cases et
provider (application/template), enforcement de la policy des tools (mod.rs,
server.rs, tools.rs), avec la parité côté chemin OpenAI-compatible
(openai_tools.rs x2).

Lots B1 (catalogue/classification), B2 (use cases/provider) et B3
(enforcement policy) livrés en un seul commit cohérent.

QA vert (seul l'échec de bind loopback #80, connu et non-régression, écarté).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 18:45:02 +02:00
c84a66f4e8 feat(backend): API Tauri pour la gestion des permissions tools MCP (#82 lot B4)
Expose au niveau application/DTO/commandes Tauri le catalogue et les
permissions des tools MCP (application/mcp_tool_permissions.rs, dto.rs,
commands.rs) pour une future UI de gestion.

Lot B4 du ticket #82, dernier lot backend : ferme la boucle sur B1
(domaine/store) + B2 (enforcement MCP stdio) + B3 (parité
OpenAI-compatible).

QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:15:05 +02:00
eeba0ddb46 feat(backend): parité enforcement des permissions tools sur le chemin OpenAI-compatible (#82 lot B3)
backend/src/openai_tools.rs et app-tauri/src/openai_tools.rs appliquent
désormais les mêmes règles de permission du domaine mcp_tool_permissions
(B1) et le même enforcement que le serveur MCP natif (B2), pour fermer
l'écart de parité sur le chemin OpenAI-compatible.

Lot B3 du ticket #82 : parité posée sur B1+B2, l'API backend pour la future
UI suit en B4 sur la même branche.

QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:03:33 +02:00
37ead61911 feat(backend): enforcement des permissions tools MCP au serveur (#82 lot B2)
orchestrator/mcp/server.rs applique désormais les règles de permission du
domaine mcp_tool_permissions (lot B1) à l'invocation d'un tool, y compris
le cas requester vide.

Lot B2 du ticket #82 : ferme la boucle enforcement sur le socle B1, la
parité OpenAI-compatible suit en B3 sur la même branche.

QA vert (32 tests dont le nouveau cas requester vide).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 22:54:42 +02:00
b4a34b40e5 fix(backend): identité requester explicite + policy des tools OpenAI-compatible (#62)
AgentSessionFactory::start propage désormais l'identité du requester aux
sessions structurées ; OpenTicketAssistant et LaunchAgent la portent
correctement de bout en bout. ToolPolicyRegistry est branché sur
AppOpenAiToolInvoker pour combler le trou de parité : TicketToolProvider
n'appliquait pas la policy des tools sur le chemin OpenAI-compatible,
contrairement au chemin structuré natif.

QA vert (échecs de bind loopback écartés comme non-régression préexistante,
tracés en #80).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 22:35:17 +02:00
8fe93d1652 feat(backend): appareils appairés persistants, révocables et code éphémère (#77 B1-B4)
L'appairage ne survivait pas au redémarrage et son code, permanent, était
imprimé sur la sortie standard. Un appareil appairé devient une entité
persistante, nommée et révocable, derrière un code désormais éphémère.

- B1 : port DeviceSessionStore et adapter FsDeviceSessionStore, entités de
  domaine (PairedDevice, DeviceId, SessionTokenHash, DeviceName). Les tokens
  sont hachés en SHA-256 et comparés en temps constant (subtle) : le store
  ne peut pas rejouer une session qu'il a servie. Cookie Max-Age 400 j à
  renouvellement glissant, lastSeenAtMs throttlé.
- B2 : code éphémère en mémoire, TTL 10 min et usage unique, toute
  génération invalidant la précédente. POST /api/pairing-code authentifiée,
  flag --new-code. Le code est retiré du boot et l'eprintln! qui l'imprimait
  est supprimé.
- B3 : endpoints devices (list/rename/revoke/revoke-all/logout), event
  DeviceRevoked et ActiveConnectionRegistry par device_id, fermant sans
  délai les WebSockets d'un appareil révoqué.
- B4 : port PairAttemptLimiter et adapter mémoire, rate-limit par origine et
  global sur horloge injectée, donc testable sans attente réelle.

La normalisation du code passe côté serveur : elle absorbe la dette #76, que
la seule normalisation frontend de #75 ne faisait que masquer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 13:26:56 +02:00
0e15482ce2 feat(web-server): extraire le serveur headless idea-serve du binaire Tauri (#65)
Sort le serveur HTTP/WS de `app-tauri` vers un crate `web-server` autonome,
exposant le binaire `idea-serve` qui sert le client web sans aucune dépendance
GUI. Le cœur (use cases, DTO, events) devient partagé entre deux driving
adapters : le desktop Tauri et le serveur headless.

Structure :
- `crates/web-server` : lib + bin `idea-serve`, consomme `backend::{dto, events}`.
- `crates/backend` : `dto.rs` et `events.rs` deviennent le propriétaire canonique
  des DTO/events transport-neutres (arbitrage Architect : pas de crate contrat
  dédié, `backend` est déjà le composition root transport-neutre).
- `crates/app-tauri` : `dto.rs` réduit à un shim de ré-export, `events.rs` réduit
  au relais Tauri (souscription au bus + emit), `server.rs` vidé au profit du
  crate partagé.
- `Cargo.toml`/`Cargo.lock` : `web-server` ajouté aux membres du workspace.

Frontière respectée : les DTO de `backend` ne tirent ni Tauri, ni HTTP/WS, ni
Axum/Hyper, ni UI ; `domain`/`application` n'en dépendent pas. Le frontend est
inchangé (`git diff 506d589...HEAD -- frontend` vide).

`web_server::run_embedded(...)` est le point d'extension prévu pour #68 (le
desktop consommera `web-server` comme lib plutôt que d'en forker le serveur).

QA (exécution réelle, re-vérifiée avant merge) :
- `cargo test -p backend` 41 passed · `-p web-server` 55 passed · `-p app-tauri`
  35 passed, 0 échec.
- Invariant headless : `ldd target/debug/idea-serve` ne tire aucun
  webkit/javascriptcore/gtk/gdk/soup/tauri/wry, là où `app-tauri` les tire bien.
- Validation live utilisateur : `idea-serve` démarre, sert le SPA, le contrôle
  d'origine strict tient, accès distant OK via reverse proxy.
- Les 10 échecs `openai_compat` de `cargo test --workspace` sont préexistants sur
  `506d589` (bind réseau interdit par la sandbox), hors périmètre.

Squash de `82e8e77` (commit de sûreté « état intermédiaire non figé », qui
rapatriait le travail réalisé par erreur sur la branche de #69) et de `ddbea7b`
(déduplication des DTO events, comblant l'écart annoncé par le premier). Les deux
n'avaient de sens qu'ensemble : ce commit fige le contrat que le premier laissait
explicitement ouvert. Arbre identique bit pour bit à `ddbea7b` ; historique
d'origine conservé sur `backup/ticket65-pre-squash-ddbea7b`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:01:18 +02:00
c8fef2a76a refactor(backend): abstraire le sink de stream hors de tauri::ipc::Channel (#13)
Lot B2 du chantier server/client mode : le cœur backend émet désormais ses
flux via une abstraction de sink agnostique, sans dépendre directement de
tauri::ipc::Channel, préalable au futur serveur web + PTY WebSocket.

- crates/backend : abstraction de sink (stream.rs) câblée dans lib.rs.
- crates/app-tauri : implémentation Tauri du sink (stream.rs) et adaptation
  des surfaces lib.rs, pty.rs, chat.rs.
- Nettoyage clippy des 2 warnings B2.

Validé : cargo check --workspace vert, tests backend/app-tauri verts,
cœur agnostique Tauri, clippy B2 propre.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 12:50:29 +02:00
955db79e97 refactor(backend): extraire le cœur backend commun hors Tauri (#13)
Lot B1 du chantier server/client mode : création de la crate `backend`
qui héberge le cœur commun (endpoint MCP, outils OpenAI) indépendant de
Tauri, préalable au futur serveur web + PTY WebSocket.

- crates/backend : nouvelle crate (lib.rs, mcp_endpoint.rs, openai_tools.rs).
- crates/app-tauri : câblage sur la crate backend (state.rs, mcp_bridge.rs,
  Cargo.toml, tests/orchestrator_wiring.rs).
- Cargo.toml / Cargo.lock racine : ajout de la crate au workspace.

Validé : cargo check --workspace vert, tests backend/app-tauri verts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:50:17 +02:00