Commit Graph

4 Commits

Author SHA1 Message Date
cb2d0c2d44 feat(app-tauri): option de lancement auto du serveur web au démarrage
Ajoute le déclenchement du serveur embarqué dès le démarrage d'IdeA
selon la préférence utilisateur, sans action manuelle requise.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:32:03 +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
166adc3c4b feat(app-tauri): packager les assets web en ressource et les résoudre depuis le resource dir (#68)
L'AppImage ne pouvait pas servir d'assets web : `resolve_web_root` ne
connaissait que `IDEA_WEB_ROOT`, le dossier de l'exécutable et le cwd —
aucun ne pointe vers un bundle packagé.

- `bundle.resources` embarque les assets sous `web/`, `beforeBuildCommand`
  déclenche le build du frontend.
- Le resource dir Tauri descend de `lib.rs` jusqu'à `EmbeddedServerController`
  via `AppState::build_with_resource_dir`, en gardant les constructeurs
  historiques comme façade.
- `resolve_web_root` insère le candidat packagé juste après `IDEA_WEB_ROOT`,
  qui garde donc la priorité pour le développement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 08:54:15 +02:00
49e1d5a157 feat(app-tauri): cycle de vie du serveur embarqué et persistance de l'exposition (#68 B2)
Permet d'activer le serveur web depuis l'app desktop — la fonctionnalité
demandée à l'origine du ticket.

- `embedded_server.rs` : `EmbeddedServerController` porté par `AppState`, avec
  les commandes `embedded_server_start` / `stop` / `status` et
  `get` / `save` / `preview_server_exposure_settings`.
- `FsServerExposureSettingsStore` : écrit `<app-data-dir>/deployment/server-exposure.json`.
  C'est de la config de sécurité, pas une préférence d'UI — d'où l'app-data-dir
  global plutôt que `localStorage`. Écriture atomique : temporaire, `0600` posé
  AVANT le `rename`, donc le fichier final n'est jamais brièvement lisible par
  tous.
- Arrêt du serveur câblé sur la sortie de l'app (`lib.rs`), aux côtés des autres
  nettoyages.

Le serveur embarqué appelle `run_embedded_with_core` avec le `BackendCore`
partagé du desktop, jamais `run_embedded` — c'est tout l'intérêt du seam ouvert
par B1 : une seule composition root dans le processus, pas deux.

DETTE CONNUE, consignée au carnet, non bloquante :
- `preview_settings` valide avant de prévisualiser (`embedded_server.rs:211`),
  ce qui verrouille la liste des candidats : un brouillon en mode
  `remoteProxyOtherMachine` ne peut pas être prévisualisé tant qu'il n'a pas le
  `lanBindAddress` que cette liste doit justement fournir. Contourné côté
  frontend par une sonde `localOnly` toujours valide. Défaut d'ordonnancement,
  pas une fatalité.
- Le warning `missingTrustedProxy` (`embedded_server.rs:452`) est du code mort :
  `validate_settings` rejette les `trustedProxies` vides en mode 3 avant que
  `preview_settings` ne puisse le produire.

QA ré-exécutée par Git HORS SANDBOX (DevBackend et QA sont bloqués par EPERM sur
`bind` ; un vert sandboxé ne prouve rien sur ces crates) : `cargo test -p
app-tauri` 43 passed, 1 ignored · `-p web-server` 66 passed, 0 échec.
Le test ignoré `mcp_bridge::tests::end_to_end_over_real_loopback` est
PRÉEXISTANT sur `develop` et non touché par ce lot ; lancé explicitement hors
sandbox avec `--ignored`, il passe. C'est une garde d'environnement, pas un faux
vert — distinction qui nous a déjà coûté deux fois aujourd'hui.

Invariants vérifiés par Git : appelant `run_embedded_with_core` confirmé, aucune
fuite d'`EmbeddedServer*`/`ServerExposure*` dans `domain` ni `application`,
ordre chmod/rename correct, `stop()` bien appelé à la fermeture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:43:24 +02:00