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>
This commit is contained in:
2026-07-20 18:45:02 +02:00
parent 448edfc364
commit ef84d5cc49
17 changed files with 1171 additions and 49 deletions

View File

@ -18,8 +18,8 @@ use uuid::Uuid;
use application::{
CreateAgentFromTemplate, CreateAgentFromTemplateInput, CreateTemplate, CreateTemplateInput,
DetectAgentDrift, DetectAgentDriftInput, SyncAgentWithTemplate, SyncAgentWithTemplateInput,
UpdateTemplate, UpdateTemplateInput,
DetectAgentDrift, DetectAgentDriftInput, ReadTemplate, ReadTemplateInput,
SyncAgentWithTemplate, SyncAgentWithTemplateInput, UpdateTemplate, UpdateTemplateInput,
};
// ---------------------------------------------------------------------------
@ -224,6 +224,29 @@ async fn create_template_starts_at_initial_version() {
assert_eq!(store.list().await.unwrap().len(), 1);
}
#[tokio::test]
async fn read_template_returns_one_template_or_not_found() {
let existing = template(tid(7), "Base", "body", 3);
let store = FakeTemplates::with(vec![existing.clone()]);
let read = ReadTemplate::new(Arc::new(store));
let out = read
.execute(ReadTemplateInput {
template_id: existing.id,
})
.await
.unwrap();
assert_eq!(out.template, existing);
let err = read
.execute(ReadTemplateInput {
template_id: tid(8),
})
.await
.expect_err("unknown template should be not found");
assert_eq!(err.code(), "NOT_FOUND");
}
#[tokio::test]
async fn update_template_bumps_version_and_publishes_event() {
let store = FakeTemplates::with(vec![template(tid(1), "T", "v1", 1)]);