Dernier état `.ideai/` du sprint serveur embarqué, séparé du code applicatif conformément aux précédents `f965f64` / `7fbaa8e` / `5ee25d1`. - #68 passé en `qa`, pas en `closed` : mergé dans `develop` (`b30c9c7`) et vert, mais RIEN n'a été cliqué dans l'app réelle. « Mergé » ne veut pas dire « validé » — même distinction que pour #69 et son lot 3. - Carnet de #68 : périmètre livré, réserve « aucune validation live », et la dette identifiée (ordre de `preview_settings` qui verrouille la liste des candidats LAN, warning `missingTrustedProxy` inatteignable). - Mémoire projet : note `sandbox-eperm-bind-false-green-web-server`. Elle capitalise le piège qui s'est refermé DEUX FOIS le 2026-07-16 : les sandboxes de DevBackend et QA refusent `TcpListener::bind`, donc tout `cargo test` sur `web-server`/`app-tauri` y rend un vert qui ne prouve rien. La première fois, ce faux vert masquait un vrai bug produit — un serveur embarqué sur port éphémère rejetait toutes les requêtes API en 403. La règle qui en sort : aucun repli EPERM silencieux, et tout vert sur ces crates doit être produit hors sandbox. - Journal des tâches de fond : complétions enregistrées. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.9 KiB
name, description, metadata
| name | description | metadata | ||
|---|---|---|---|---|
| sandbox-eperm-bind-false-green-web-server | memory note sandbox-eperm-bind-false-green-web-server |
|
Faux vert : TcpListener::bind interdit dans les sandboxes agents
Le fait
Les environnements d'exécution de DevBackend et de QA refusent TcpListener::bind("127.0.0.1:0") avec Operation not permitted (os error 1). Tout test qui ouvre un socket y est structurellement inexécutable.
Crates concernés : web-server, app-tauri (pont MCP, serveur embarqué).
Pourquoi c'est dangereux, pas juste gênant
Le 2026-07-16, ce piège s'est refermé deux fois dans la même journée :
- #68 B1 — DevBackend annonce « 57 passed ». En réalité le test
run_embedded_stop_shuts_down_accept_loopsortait en silence sur EPERM via un repli, et le test du core partagé basculait sur un dispatch in-process. Rejoué hors sandbox : échec réel, révélant un vrai bug produit —run_embeddedne réconciliait pas le port effectif avec la config, doncorigin_allowedcomparait l'origine àhttp://127.0.0.1:0et un serveur embarqué sur port éphémère rejetait toutes les requêtes API en 403. Le trou n'avait jamais été vu parce que rien ne consommaitrun_embedded. - #72 — même schéma, cette fois signalé honnêtement par DevBackend (« 63 passed; 2 failed » sur EPERM) après consigne explicite.
Un repli silencieux sur EPERM transforme un test en décoration : il passe sans rien exercer, et masque la classe de bug qu'il était censé attraper.
La règle
- Aucun repli EPERM silencieux. Un test qui ne peut pas s'exécuter doit échouer visiblement ou être
#[ignore]explicite avec sa raison — jamais « passer ». - Tout vert sur
web-server/app-tauridoit être produit hors sandbox (dangerouslyDisableSandbox: truecôté Main, qui n'a pas la restriction). Ne jamais accepter un vert sandboxé comme preuve sur ces crates. - DevBackend et QA doivent dire ce qu'ils ont pu exécuter et ce qu'ils n'ont pas pu, plutôt que de rendre un chiffre global.
- Les
#[ignore = "requires local socket bind permission"]légitimes (ex.mcp_bridge::tests::end_to_end_over_real_loopback) se vérifient en les lançant hors sandbox avec--ignored, pas en raisonnant dessus.
Principe général
Ne pas confondre « les tests sont verts » et « le code marche ». Le vert d'un environnement contraint ne dit rien du produit. Cette leçon vaut au-delà du bind : un environnement qui ne peut pas exercer un chemin ne peut pas le valider.
Lien : appimage-build-no-strip-relr-dyn-fix (autre piège d'environnement de cette machine), rendezvous-600s-cap-too-short-heavy-tasks.