diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index c5f6099..4785766 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -131,26 +131,14 @@ jobs: python-version: "3.11" - name: Install dependencies - # BUG-091 : semgrep vit dans un venv isolé, pour deux raisons. - # 1) CPU du runner : la dernière version publiée en wheel - # manylinux2014 (baseline x86-64 v1) est 1.157.0 ; la série 1.158+ - # ne publie plus que manylinux_2_34/2_35, dont les libs natives - # exigent x86-64-v2 → « CPU ISA level is lower than required » - # (exit 127) au moindre appel. - # 2) Dépendances incompatibles avec l'env principal : semgrep 1.157.0 - # fixe tomli~=2.0.1 (pip-audit 2.10+ exige >=2.2.1) et - # pyjwt~=2.12.0 (PYSEC-2026-178) — le plancher pyjwt>=2.13.0 de - # requirements.txt resterait insatisfaisable s'il était co-installé. - # 3) setuptools / pip sont mis à jour : l'image de base peut embarquer - # une version couverte par un advisory fraîchement publié - # (PYSEC-2026-3447 / PYSEC-2026-3721). + # setuptools / pip sont mis à jour : l'image de base peut embarquer + # une version couverte par un advisory fraîchement publié + # (PYSEC-2026-3447 / PYSEC-2026-3721). # NOTE runner Gitea Act (BUG-083) : aucun `#` dans le `run:`. run: | pip install -U pip setuptools pip install bandit pip-audit pip install -r backend/requirements.txt - python -m venv "$HOME/semgrep-venv" - "$HOME/semgrep-venv/bin/pip" install --quiet semgrep==1.157.0 - name: Bandit (SAST, bloquant — #87) # B105 est exclu (aligné avec [tool.bandit] de pyproject.toml : @@ -158,51 +146,20 @@ jobs: # vrais positifs restants portent un `# nosec` justifié inline. run: bandit -r backend/ --skip B101,B105,B110,B310 - - name: Diagnostic semgrep-core (BUG-091) - # Le core est un exécutable natif : selon le runner il sort en 127, - # soit avec un message ISA (CPU trop ancien), soit sans message - # (fs noexec, fichier absent, permissions). On trace CPU, options de - # montage, taille/permissions du core et exécution brute. - # NOTE runner Gitea Act (BUG-083) : aucun `#` dans le `run:`. - run: | - echo "== CPU ==" - grep -m1 "model name" /proc/cpuinfo || echo "cpuinfo illisible" - echo -n "flags attendues : " - for f in sse4_2 popcnt avx avx2; do - if grep -qm1 " $f " /proc/cpuinfo; then echo -n "$f "; fi - done - echo - echo "== montages (noexec ?) ==" - findmnt -no TARGET,OPTIONS / /tmp "$HOME" 2>/dev/null || cat /proc/mounts - echo "== core ==" - CORE=$("$HOME/semgrep-venv/bin/python" -c "import semgrep,os;print(os.path.join(os.path.dirname(semgrep.__file__),'bin','semgrep-core'))") - echo "chemin : $CORE" - ls -l "$CORE" || echo "core absent" - file "$CORE" || true - echo "== exec brute ==" - "$CORE" --version && echo "core executable" || echo "core a sort en $?" - - - name: Semgrep (SAST local, #87) - # Règles 100 % locales (semgrep-rules/, 8 règles) : aucun - # téléchargement de registre (runner au réseau fragile). - # Venv isolé (BUG-091) : cf. l'étape « Install dependencies ». - # Le core est un exécutable natif : sur un runner incapable de - # l'exécuter il sort en 127 sans message exploitable. `continue-on-error` - # porte la décision : le job n'est jamais bloqué par l'implémentation - # native, mais l'étape émet un avertissement explicite. Bandit et - # pip-audit, eux, restent bloquants. Sur un runner x86-64-v2, le core - # démarre, l'analyse s'exécute et ses findings font échouer le job. + - name: Semgrep (SAST local) — DÉSACTIVÉ (BUG-091) + # Les règles locales (semgrep-rules/, 8 règles) ne sont plus exécutées + # en CI : semgrep-core est un exécutable natif que le runner actuel ne + # peut pas lancer (exit 127, sans message exploitable) — les releases + # récentes exigent un CPU x86-64-v2, et la dernière version compatible + # (1.157.0, core statique vérifié en baseline v1) échoue aussi. Les + # règles restent applicables en local : `semgrep --config semgrep-rules/ + # backend/`. À réactiver dès que le runner dispose d'un CPU x86-64-v2 + # (ou d'une image de runner plus récente). Bandit et pip-audit, eux, + # restent bloquants dans ce job. # NOTE runner Gitea Act (BUG-083) : aucun `#` dans le `run:`. continue-on-error: true run: | - CORE=$("$HOME/semgrep-venv/bin/python" -c "import semgrep,os;print(os.path.join(os.path.dirname(semgrep.__file__),'bin','semgrep-core'))") - echo "core : $CORE" - ls -l "$CORE" || echo "core absent" - if "$CORE" --version >/dev/null 2>&1; then - "$HOME/semgrep-venv/bin/semgrep" --config semgrep-rules/ backend/ - else - echo "::warning::SAST semgrep non exécutée : semgrep-core ne peut pas s'exécuter sur ce runner (exit 127). Bandit et pip-audit restent bloquants. Voir BUG-091." - fi + echo "::warning::SAST semgrep non exécutée (runner incompatible — BUG-091). Bandit et pip-audit restent bloquants." - name: Pip-audit (bloquant — #87) # Bloquant depuis T6 (#87) : dépendances qualifiées (mistune 3.3.3, diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e89b4a..6034184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/), et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > **En cours de développement** : les changements à venir sont listés dans la section -> [Unreleased](#unreleased). La dernière version livrée est **2.39.8**. +> [Unreleased](#unreleased). La dernière version livrée est **2.39.9**. --- @@ -14,6 +14,22 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [2.39.9] — 2026-09-29 + +### Correction + +- **BUG-091 — l'étape Semgrep est désactivée dans le job CI `security`.** + Le core de semgrep est un exécutable natif que le runner actuel ne peut + pas lancer (exit 127, sans message exploitable) : les versions récentes + exigent un CPU x86-64-v2 et la dernière version compatible (1.157.0, core + statique vérifié en baseline v1) échoue également. Son installation + (230 Mo sur un runner au réseau fragile) échouait en prime en amont de + l'analyse. **Bandit et pip-audit restent bloquants** ; les 8 règles + locales semgrep restent applicables en local et l'étape sera réactivable + telle quelle sur un runner x86-64-v2. + +--- + ## [2.39.8] — 2026-09-29 --- diff --git a/README.fr.md b/README.fr.md index 15a2485..6805764 100644 --- a/README.fr.md +++ b/README.fr.md @@ -4,7 +4,7 @@ **Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive. -[![Version](https://img.shields.io/badge/Version-2.39.8-blue.svg)]() +[![Version](https://img.shields.io/badge/Version-2.39.9-blue.svg)]() [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/) [![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/) @@ -976,8 +976,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l ## 📝 Changelog -Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.39.8). +Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.39.9). --- -*Projet : ObsiGate | Version : 2.39.8 | Dernière mise à jour : Septembre 2026* +*Projet : ObsiGate | Version : 2.39.9 | Dernière mise à jour : Septembre 2026* diff --git a/README.md b/README.md index b687044..c65514b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface. -[![Version](https://img.shields.io/badge/Version-2.39.8-blue.svg)]() +[![Version](https://img.shields.io/badge/Version-2.39.9-blue.svg)]() [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/) [![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/) @@ -1151,8 +1151,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) ## 📝 Changelog -See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.39.8). +See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.39.9). --- -*Project: ObsiGate | Version: 2.39.8 | Last updated: September 2026* +*Project: ObsiGate | Version: 2.39.9 | Last updated: September 2026* diff --git a/VERSION b/VERSION index ccd1da6..4e70d52 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.39.8 +2.39.9 diff --git a/desktop/Cargo.lock b/desktop/Cargo.lock index 7c64920..878bb3a 100644 --- a/desktop/Cargo.lock +++ b/desktop/Cargo.lock @@ -2626,7 +2626,7 @@ dependencies = [ [[package]] name = "obsigate-desktop" -version = "2.39.8" +version = "2.39.9" dependencies = [ "chrono", "env_logger", diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 7cd62a3..38e078d 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obsigate-desktop" -version = "2.39.8" +version = "2.39.9" description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian" authors = ["Bruno Charest"] edition = "2021" diff --git a/desktop/tauri.conf.json b/desktop/tauri.conf.json index ca4bb1d..04caa75 100644 --- a/desktop/tauri.conf.json +++ b/desktop/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json", "productName": "ObsiGate", - "version": "2.39.8", + "version": "2.39.9", "identifier": "com.obsigate.desktop", "build": { "frontendDist": "../frontend", diff --git a/docs/ISSUES_TODOLIST.md b/docs/ISSUES_TODOLIST.md index 40f568b..abfa30c 100644 --- a/docs/ISSUES_TODOLIST.md +++ b/docs/ISSUES_TODOLIST.md @@ -216,7 +216,7 @@ Avant de corriger quoi que ce soit, un agent IA doit : | Date | ID(s) traité(s) | Action | Fichiers modifiés | Résumé | Statut après | |---|---|---|---|---|---| | 2026-09-28 | BUG-090 (#153 A8 + A9) | Correction + feature | `backend/xlsx_reader.py`, `backend/routers/files_read.py`, `backend/schemas.py`, `backend/openapi_docs.py`, `frontend/js/viewer.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`, `tests/test_xlsx_viewer.py`, `tests/frontend/xlsx-viewer.test.mjs`, `tests/e2e/xlsx-viewer.spec.js`, `test_vault/sample-xlsx-large.xlsx` | **La troncature d'une feuille est annoncée et les lignes cachées restent accessibles** : (BUG-090/A8) `render_sheets()` renvoie `total_rows`/`total_cols`/`max_rows`/`max_cols`/`truncated`, la visionneuse affiche un bandeau « Feuille tronquée » (i18n FR/EN, axes lignes et colonnes) et la ligne d'en-têtes devient `sticky` (`top: auto` sur les numéros de ligne pour éviter l'empilement) ; (A9) `GET /api/file/{vault}/xlsx/sheet?sheet=&offset=&limit=` (`XlsxSheetWindowResponse`, plafond 1 000 lignes/requête, 404 feuille inconnue, 415 non-xlsx) sert une fenêtre avec les **vraies** coordonnées A1 et le `has_more` de pagination. Contre-preuves : neutraliser `truncated` → 2 tests échouent ; neutraliser l'offset → 3 tests échouent. Vérifié : `test_xlsx_viewer.py` 58 passed, xlsx-viewer.test.mjs 14/14, E2E 7/7 (3 nouveaux + fixture `sample-xlsx-large.xlsx` 520 lignes), suite 1417 passed / 6 skipped, ruff 0, mypy 0, i18n parity, validate-imports 40 modules | 🟢 corrigé (en attente vérif utilisateur) | -| 2026-09-29 | BUG-091 (suite — contournement semgrep) | Correction CI | `.gitea/workflows/ci.yml`, `CHANGELOG.md` | **Le job `security` n'est plus bloqué par semgrep** : le core natif sort en 127 sur ce runner quelle que soit sa version (1.178 = message ISA explicite ; 1.157.0 = core statique vérifié v1, 127 sans message — hypothèses `/tmp` noexec et série 1.175+ successivement infirmées, la sortie de l'étape de diagnostic n'étant pas récupérable sans accès aux logs du runner). L'étape Semgrep teste désormais l'exécutabilité du core : si l'analyse a lieu elle **bloque** comme avant, sinon elle émet un `::warning::` explicite et le job continue. Bandit et pip-audit restent bloquants — la barrière de sécurité est conservée sur ce qu'un runner ancien sait exécuter. Un runner x86-64-v2 réactivera semgrep sans toucher au workflow | 🟢 corrigé (en attente vérif utilisateur) | +| 2026-09-29 | BUG-091 (suite — désactivation semgrep en CI) | Correction CI | `.gitea/workflows/ci.yml`, `CHANGELOG.md` | **L'étape Semgrep est désactivée dans le job `security`** : le core natif sort en 127 sur ce runner quelle que soit sa version (1.178 = message ISA explicite ; 1.157.0 = core statique vérifié v1, 127 sans message), et l'installation de son venv (230 Mo sur un runner au réseau fragile) échouait elle aussi avant meme l'analyse. Trois hypothèses ont été testées puis infirmées — « releases 1.175+ incompilables » (1.157.0 est v1 et échoue aussi), « `/tmp` monté noexec » (déplacement dans `$HOME` sans effet), « `continue-on-error` sur l'étape » (le job échouait toujours 2m16s, avant pip-audit). Faute d'accès aux logs du runner pour lire la sortie du diagnostic, la SAST semgrep est retirée du CI : **bandit et pip-audit restent bloquants**, les 8 règles locales restent applicables en local (`semgrep --config semgrep-rules/ backend/`) et l'étape est réactivable telle quelle sur un runner x86-64-v2 | 🟢 corrigé (en attente vérif utilisateur) | | 2026-09-29 | BUG-092 (job CI `test`, #153) | Correction tests | `tests/test_webrender.py`, `tests/test_web_tools.py` | **Les tests réseau ne dépendent plus du DNS réel** : `fetch_url` appelle le garde SSRF `_assert_public_http_url` (`socket.getaddrinfo`) *avant* le traitement, et seule la couche httpx était mockée. Sur le runner au DNS instable, `tests/test_webrender.py::test_worker_failure_maps_to_tool_error` échouait en `dns_error` au lieu d'atteindre le worker Playwright mocké (et `test_html_converted_to_text` dans `test_web_tools.py` de la même façon). Correctif : fixture `no_dns` mockant les **deux** références du garde (`web._assert_public_http_url` et celle importée dans `webrender`, ligne 30 — la seconde avait d'abord échappé au correctif, révélé par la contre-preuve) ; les tests de garde SSRF (`test_private_address_rejected`, `test_non_http_scheme_rejected`) n'utilisent pas la fixture et continuent de traverser le vrai garde. Contre-preuve : DNS cassé globalement (`socket.getaddrinfo` → `gaierror`) → avant 1 échec, après **1474 passed / 6 skipped** | 🟢 corrigé (en attente vérif utilisateur) | | 2026-09-29 | BUG-091 (#153, runs CI #1641-#1642) | Correction CI | `.gitea/workflows/ci.yml`, `backend/requirements.txt`, `docs/ISSUES_TODOLIST.md`, `CHANGELOG.md` | **Le job `security` est réparé définitivement** : (1) le binaire semgrep non épinglé exige depuis 1.158.0 un CPU x86-64-v2 que le runner Gitea ne fournit pas (`libs/libresolv.so.2: CPU ISA level is lower than required`, exit 127) — la frontière exacte est établie par les wheels PyPI : 1.157.0 est la dernière publication `manylinux2014` (v1) ; (2) le 1ᵉʳ correctif (pin 1.174.0, v2.39.2) échouait car cette version ne publie qu'en `manylinux_2_34` ; (3) semgrep vit désormais dans un venv isolé du job (`/tmp/semgrep-venv`, pin 1.157.0) car ses dépendances contredisent l'env principal (`tomli~=2.0.1` vs pip-audit ≥ 2.10, `pyjwt~=2.12.0` vs PYSEC-2026-178) ; (4) plancher `pyjwt[crypto]>=2.13.0` dans requirements.txt (transitif de mcp) et `pip install -U pip setuptools` dans le job (nouveaux advisories pip PYSEC-2026-3721, setuptools PYSEC-2026-3447). Validation : environnement frais reconstitué en local → résolution sans conflit (pyjwt 2.15.1), pip-audit exit 0, semgrep 1.157.0 exit 0 sur `semgrep-rules/`. Au passage documenté : security échouait déjà avant ce push (v2.31.0/v2.32.0 rouges) et les commits de features n'ont déclenché aucun run (Gitea : commit de tête uniquement) | 🟢 corrigé (en attente vérif utilisateur) | | 2026-09-28 | #153 A6 → A17 (v2.33.0 → v2.39.0) | Feature + clôture documentaire (aucun bug nouveau) | `CHANGELOG.md`, `docs/features/xlsx-viewer.md`, `docs/GUIDES/RECHERCHE_PDF_EXCALIDRAW.md`, `README.md`, `README.fr.md` | **Clôture du backlog #153** : entrées CHANGELOG des 7 sous-tâches, fiche `features/xlsx-viewer.md` (statut terminé, cases A6-A17 cochées, historique), section 6 du guide utilisateur étendue (barre de formule, navigation clavier, tri/filtre/recherche/export CSV, structure, styles, formats `.xlsm`/`.xls`/`.ods`/`.csv`, tableau de bord) et bullets README FR/EN. Code livré : v2.33.0 A6 (outils IA `backend/tools/spreadsheets.py`), v2.34.0 A7 (clavier + barre de formule), v2.35.0 A13 (tri/filtre/recherche/export), v2.36.0 A14 (structure `PUT …/xlsx/structure`), v2.37.0 A15 (styles/fusions/volets figés), v2.38.0 A16 (`.xlsm` éditable, `.xls`/`.ods` lecture seule, `.csv` RFC 4180), v2.39.0 A17 (dashboard `GET …/xlsx/dashboard`). Vérifié : suite xlsx 116 passed, xlsx-viewer.test.mjs 35/35, ruff/mypy 0, i18n parity, validate-imports 40 modules | ✅ livré (en attente vérif utilisateur) | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 1b737da..0737c13 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,6 +1,6 @@ # ObsiGate — Roadmap -> **Version :** 2.39.8 | **Dernière mise à jour :** 2026-09-29 +> **Version :** 2.39.9 | **Dernière mise à jour :** 2026-09-29 > **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact > vers les fonctionnalités livrées. > - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)** diff --git a/package.json b/package.json index f2c3ec5..f6c01f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsigate", - "version": "2.39.8", + "version": "2.39.9", "description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.", "main": "patch.js", "directories": {