docling-studio/docs/audit/reports/release-0.5.0/summary.md
Pier-Jean Malandrino efc27932dd refactor(audit): remediate 0.5.0 audit findings — clean architecture, security, DRY, SOLID, perf
Closes the 12 MAJ raised by the release/0.5.0 audit pipeline (cf.
docs/audit/reports/release-0.5.0/summary.md → summary-reaudit.md).

Volet 1 — Reasoning architecture (audits 01/02/06/07 strengthening)
  * Domain ports: LLMProvider, ReasoningRunner, ReasoningParseError
  * Domain DTOs: LLMProviderType, ReasoningResult, ReasoningIteration
  * infra/llm/ollama_provider.py — OllamaProvider with health_check
  * infra/docling_agent_reasoning.py — runner adapter, encapsulates the
    private _rag_loop call (tracked at docling-project/docling-agent#26),
    commits OLLAMA_HOST once at boot (eliminates the per-request env race),
    translates upstream IndexError into ReasoningParseError
  * api/reasoning.py — zero coupling to docling-agent / mellea / docling-core,
    consumes app.state.reasoning_runner via the port
  * main.py — DI wires OllamaProvider + DoclingAgentReasoningRunner at boot
    when REASONING_ENABLED=true and deps are importable
  * Rename RAG_* env vars → REASONING_*, endpoint /rag → /reasoning,
    type RAGResult → ReasoningResult, frontend feature flag wiring,
    i18n strings, tests, docs (BREAKING — pre-1.0 surface, no external
    consumers in production)
  * 17 new tests: adapter unit tests with sys.modules stubs, OllamaProvider
    httpx tests, R3 concurrent-host isolation, R6 multi-iteration trace
    serialization, R13 Protocol conformance via isinstance
  * E2E Karate scenario: nav-reasoning hidden when REASONING_ENABLED=false
  * README — Live Reasoning section (env vars, archi, link to issue #26)

Bloc B — Security (audit 08, dev-only context)
  * docker-compose.yml — DEV DEFAULTS header, OpenSearch DISABLE_SECURITY_PLUGIN
    flagged as dev-only with link to OpenSearch security docs
  * main.py — boot warning if NEO4J_URI is set with the default 'changeme'
    password, so prod operators can't silently inherit it

Bloc C — DRY frontend (audit 05)
  * shared/storage/keys.ts — STORAGE_KEYS centralised (theme, locale)
  * features/settings/store.ts — dead apiUrl ref + orphan i18n keys removed
  * api/schemas.py — DOCUMENT_STATUS_UPLOADED constant

Bloc D — Quality (audits 02/06/07/09/10/12)
  * domain/ports.py — DocumentConverter.supports_page_batching property
    (LSP fix, replaces isinstance(ServeConverter) check)
  * domain/ports.py — VectorStore.ping() (encapsulation, replaces
    _vector_store._client.info() reach-around)
  * api/analyses.py + api/ingestion.py — path params {job_id} → {analysis_id}
    aligned with the user-facing terminology (URLs unchanged)
  * api/documents.py — Path.read_bytes() + generate_preview() wrapped in
    asyncio.to_thread, unblocks the FastAPI event loop on /preview
  * infra/docling_tree.py — PEP 604 union for isinstance (Ruff UP038)
  * src/__tests__/integration/ — cross-feature integration test relocated
    out of features/history/ so feature folders stay self-contained
  * Tightened terminal `assert X is not None` checks (isinstance(.., datetime),
    exact value comparisons)

Validation
  * 446 backend pytest, 202 frontend vitest — all green
  * ruff + ruff format + ESLint + Prettier + vue-tsc clean
  * Re-audit verdict: 0 CRIT / 0 MAJ, score ~94/100, GO

Closes #200
2026-04-29 14:00:00 +02:00

6.1 KiB

Synthese d'audit — Release 0.5.0

Date : 2026-04-28 Branche : release/0.5.0 Commit audite : b2e0af3 Auditeur : claude-code


Tableau de bord

# Audit Score CRIT MAJ MIN INFO Verdict
01 Clean Architecture 100 0 0 0 0 GO
02 DDD 91 0 1 1 0 GO
03 Clean Code 83 0 0 3 0 GO
04 KISS 87.5 0 0 1 2 GO
05 DRY 71 0 2 1 2 GO CONDITIONNEL
06 SOLID 85 0 1 1 0 GO
07 Decouplage 86 0 1 1 0 GO CONDITIONNEL
08 Securite 91 0 2 0 1 GO CONDITIONNEL
09 Tests 94 0 1 0 0 GO
10 CI / Build 91 0 1 0 0 GO CONDITIONNEL
11 Documentation 44 1 2 0 0 NO-GO
12 Performance 86.67 0 1 1 1 GO CONDITIONNEL

Score global (moyenne simple) : 84.2 / 100 Ecarts CRITICAL totaux : 1 Ecarts MAJOR totaux : 12 Ecarts MINOR totaux : 8 Ecarts INFO totaux : 6


Ecarts CRITICAL (tous audits confondus)

  1. [11] CHANGELOG.md sans section [0.5.0]CHANGELOG.md:7 La derniere section listee est ## [0.4.0] - 2026-04-13. Aucune entree [Unreleased] ni [0.5.0]. Tagger 0.5.0 depuis ce HEAD livrerait un changelog mensonger qui omet les nouveautes de la release (reasoning-trace viewer, Neo4j graph storage, RAG endpoints, feature flags). Bloquant absolu par regle master §3.

Top blockers (poids 3 / poids 2)

Bloquant (poids 3)

  • [11] CHANGELOG sans section 0.5.0CHANGELOG.md:7 Ajouter ## [0.5.0] - 2026-04-28 avec sous-sections Added / Changed / Fixed listant les changements depuis 0.4.0.

Majeurs (poids 2) — a remediar pour passer a GO

  • [11] frontend/package.json toujours a 0.4.0frontend/package.json:3 Bumper a "version": "0.5.0".
  • [11] Modifications de la release 0.5.0 non documenteesCHANGELOG.md Resolu en meme temps que le CRIT.
  • [08] Mot de passe Neo4j par defaut "changeme"document-parser/infra/settings.py:30,133 Forcer la lecture d'une variable d'environnement, supprimer le defaut, faire echouer le boot si absent en prod.
  • [08] OpenSearch security plugin desactivedocker-compose.yml:26 DISABLE_SECURITY_PLUGIN=true doit etre off pour tout deploiement non-dev ; documenter explicitement le perimetre.
  • [05] URL d'API hardcodee en frontendfrontend/src/features/settings/store.ts:23 Centraliser dans une constante API_BASE_URL lue depuis import.meta.env.
  • [05] Cles localStorage en clair, disperseesfrontend/src/features/settings/store.ts:24-27 Centraliser dans une enum/objet STORAGE_KEYS.
  • [02] Ubiquitous language "job" vs "analysis"document-parser/api/ingestion.py:49-67 Aligner le vocabulaire HTTP sur le langage du domaine.
  • [06] LSP — isinstance() sur adaptateurdocument-parser/services/analysis_service.py:356 Supprimer le check de type concret ou exposer la capacite via le port.
  • [07] Couplage inter-feature dans les testsfrontend/src/features/history/navigation.test.ts:30-31,67,82-83,143-144,169-170,188 Stubber les stores via injection au lieu d'imports directs.
  • [09] Assertions vagues assert X is not None — 18 occurrences en backend Ajouter une assertion sur la valeur attendue, pas seulement sur la presence.
  • [10] Ruff UP038 — syntaxe isinstance() uniondocument-parser/infra/docling_tree.py:101 Appliquer la suggestion pyupgrade.
  • [12] I/O synchrone dans endpoint asyncdocument-parser/api/documents.py:115-116 Wrapper l'acces fichier dans asyncio.to_thread(...) pour ne pas bloquer la loop FastAPI.

Quick wins (poids 1 — ameliorations rapides)

  • [03] Trois fichiers Vue > 300 lignesfrontend/src/views/StudioPage.vue (~1450L), frontend/src/.../ChunkPanel.vue (~801L), frontend/src/.../ResultTabs.vue (~690L). Extraire des sous-composants.
  • [03] Fonctions > 30 lignes (3 cas) et fonctions > 4 parametres (4 cas). Decoupage local.
  • [04] Wrapper trivial _to_response — utiliser Pydantic.model_validate() directement.
  • [04] Accessors redondants dans DocumentService.
  • [05] Magic string isoleedocument-parser/api/schemas.py:49.
  • [12] Polling avec setInterval/setTimeout imbriquesfrontend/src/features/settings/store.ts:27-39 et store analysis.

Verdict final : NO-GO

Justification : 1 ecart CRITICAL non resolu dans l'audit 11 (Documentation) → regle absolue du master.md §3 : tout ecart [CRIT] non resolu = NO-GO quel que soit le score.

Bien que le score global (84.2/100) soit confortablement au-dessus du seuil GO et que 11 audits sur 12 soient au moins en GO CONDITIONNEL, le release 0.5.0 ne peut pas etre tague dans cet etat.

Conditions pour passer a GO

Bloquant absolu (1 action) :

  1. Ajouter la section ## [0.5.0] - 2026-04-28 dans CHANGELOG.md avec Added / Changed / Fixed.

Pour passer de GO CONDITIONNEL a GO (4 actions, ~30 min) : 2. Bumper frontend/package.json a 0.5.0. 3. Remplacer "changeme" par lecture d'env var obligatoire (document-parser/infra/settings.py). 4. Documenter / corriger la desactivation du security plugin OpenSearch (docker-compose.yml). 5. Centraliser l'URL d'API et les cles localStorage du frontend (frontend/src/features/settings/store.ts).

Recommandation : apres remediation des 5 points ci-dessus, re-auditer uniquement les audits 11, 08 et 05 (commande : Re-audite uniquement les ecarts CRITICAL et MAJOR du rapport docs/audit/reports/release-0.5.0/summary.md). Les autres MAJ peuvent etre planifies pour 0.5.1 sans bloquer le tag.