L'édition d'un .xlsx pouvait détruire une partie du classeur, le
concurrencer en silence, ou diffuser une injection de formule.
- BUG-085 : inspect_workbook() détecte ce qu'un round-trip openpyxl perd
(valeurs calculées en cache, slicers, contrôles, connexions, custom
XML, signature, commentaires enrichis, macros) → xlsx_lossy_features
exposé en lecture, bandeau FR/EN, et 409 xlsx_lossy_content sans
`force` (confirmation explicite puis reprise). Périmètre réel
revalidé : graphiques, images et TCD survivent au round-trip.
- BUG-086 : écriture atomique (fichier .tmp + os.replace) : un plantage
ne peut plus tronquer le classeur, le backup reste intact.
- BUG-087 : verrou par fichier autour du read-modify-write (timeout 15 s,
409 conflict) ; endpoint xlsx/save devenu synchrone pour que
l'attente s'exécute dans le threadpool.
- BUG-088 : une saisie en '=' ou '@' est stockée en texte, sauf opt-in
`allow_formula` ou le bouton f(x) de la visionneuse. Le handler
ServiceError expose désormais code + details, que api() propage.
- BUG-084 : la suppression d'une vault purge enfin l'index inversé
(documents fantômes qui continuaient de matcher) et is_stale() devient
is_ready(), le nom étant trompeur (la staleness n'existe plus).
Tests : 1390 pytest, 10 JSDOM (xlsx-viewer.test.mjs, branché au CI),
3 E2E Playwright, suite E2E complète verte, ruff/mypy 0.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
- obsigate.spec.ts : searchFor appuie sur Entree (la recherche se declenche au keydown Enter, l autocomplete s affiche pendant la frappe)
- test_vault : ajout note1.md et note2.md (requis par les tests split-view)
- viewer.js : initialise la barre de filtres saved searches meme quand la liste est vide (sinon clics sans effet)
- test_vault/ et test_dir/ : fixtures markdown pour les tests E2E Playwright (22 fichiers, .obsigate-backup ignore)
- ci.yml e2e : health check et BASE_URL via IP passerelle docker (localhost du job container ne voit pas le port publie sur l hote)
- ci.yml e2e : l etape Start ObsiGate echoue explicitement si l app n est pas joignable