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>
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>
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>