fix(docs): resolve mkdocs strict mode build failure (#145)

- Add all process docs to mkdocs.yml nav (15 missing pages)
- Replace relative links to files outside docs/ with absolute GitHub URLs
- Add docs/audit/ directory (templates + reports)
- Add validation config to allow unlisted audit reports as info-level
This commit is contained in:
Pier-Jean Malandrino 2026-04-10 15:11:29 +02:00
parent d8937ad916
commit f6030bb2f1
33 changed files with 1819 additions and 17 deletions

View file

@ -1,4 +1,4 @@
# Available Processes
****# Available Processes
Index of all documented processes in Docling Studio. Each process is a structured, repeatable workflow with a clear trigger and deliverable.
@ -30,9 +30,9 @@ Crée un ADR pour [la décision à documenter]
| # | Process | Trigger / Command | Doc | Output |
|---|---------|-------------------|-----|--------|
| 5 | **Full Release Audit** | Before merging `release/*` to `main` | [docs/audit/master.md](audit/master.md) | 12 audit reports + summary in `reports/release-X.Y.Z/` |
| 6 | **Single Audit** | Targeted check on one axis | [docs/audit/audits/*.md](audit/audits/) | Single audit report |
| 6 | **Single Audit** | Targeted check on one axis | [docs/audit/audits/*.md](audit/audits/01-clean-architecture.md) | Single audit report |
| 7 | **Re-Audit** | After fixing CRIT/MAJ findings | [docs/audit/master.md](audit/master.md) | Updated report |
| 8 | **Automated Checks** | Quick validation before audit | [profiles/fastapi-vue/commands.sh](../profiles/fastapi-vue/commands.sh) | PASS/WARN/FAIL per check |
| 8 | **Automated Checks** | Quick validation before audit | [profiles/fastapi-vue/commands.sh](https://github.com/scub-france/Docling-Studio/blob/main/profiles/fastapi-vue/commands.sh) | PASS/WARN/FAIL per check |
### How to invoke
@ -56,11 +56,11 @@ bash profiles/fastapi-vue/commands.sh
| # | Process | Trigger / Command | Doc | Output |
|---|---------|-------------------|-----|--------|
| 9 | **Release Gate** | Auto on push/PR `release/*``main` | [release-gate.yml](../.github/workflows/release-gate.yml) | GO / GO CONDITIONAL / NO-GO comment on PR |
| 10 | **Release** | Feature freeze on `release/*` | [CONTRIBUTING.md](../CONTRIBUTING.md#release-process) | Tag `vX.Y.Z`, Docker images on ghcr.io |
| 9 | **Release Gate** | Auto on push/PR `release/*``main` | [release-gate.yml](https://github.com/scub-france/Docling-Studio/blob/main/.github/workflows/release-gate.yml) | GO / GO CONDITIONAL / NO-GO comment on PR |
| 10 | **Release** | Feature freeze on `release/*` | [CONTRIBUTING.md](https://github.com/scub-france/Docling-Studio/blob/main/CONTRIBUTING.md#release-process) | Tag `vX.Y.Z`, Docker images on ghcr.io |
| 11 | **Deployment** | After release tag | [deployment-checklist.md](release/deployment-checklist.md) | Running instance at new version |
| 12 | **Rollback** | Post-deploy failure detected | [rollback-playbook.md](release/rollback-playbook.md) | Reverted to last known good version |
| 13 | **Hotfix** | Critical bug on released version | [CONTRIBUTING.md](../CONTRIBUTING.md#hotfix) | Patch release `vX.Y.Z+1` |
| 13 | **Hotfix** | Critical bug on released version | [CONTRIBUTING.md](https://github.com/scub-france/Docling-Studio/blob/main/CONTRIBUTING.md#hotfix) | Patch release `vX.Y.Z+1` |
### Release Gate details
@ -170,10 +170,10 @@ These are not processes but reference documents used by the processes above:
| Document | Purpose |
|----------|---------|
| [CONTRIBUTING.md](../CONTRIBUTING.md) | Dev setup, branching, release, versioning |
| [CONTRIBUTING.md](https://github.com/scub-france/Docling-Studio/blob/main/CONTRIBUTING.md) | Dev setup, branching, release, versioning |
| [coding-standards.md](architecture/coding-standards.md) | Naming, style, architecture rules |
| [e2e/CONVENTIONS.md](../e2e/CONVENTIONS.md) | Karate / Karate UI test conventions |
| [e2e/CONVENTIONS.md](https://github.com/scub-france/Docling-Studio/blob/main/e2e/CONVENTIONS.md) | Karate / Karate UI test conventions |
| [architecture.md](architecture.md) | System architecture (backend + frontend) |
| [CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md) | Community behavior standards |
| [SECURITY.md](../SECURITY.md) | Vulnerability reporting policy |
| [profiles/fastapi-vue/profile.md](../profiles/fastapi-vue/profile.md) | Stack layer mapping for audits |
| [CODE_OF_CONDUCT.md](https://github.com/scub-france/Docling-Studio/blob/main/CODE_OF_CONDUCT.md) | Community behavior standards |
| [SECURITY.md](https://github.com/scub-france/Docling-Studio/blob/main/SECURITY.md) | Vulnerability reporting policy |
| [profiles/fastapi-vue/profile.md](https://github.com/scub-france/Docling-Studio/blob/main/profiles/fastapi-vue/profile.md) | Stack layer mapping for audits |

View file

@ -79,7 +79,7 @@ Conventions for writing consistent, readable code across the Docling Studio code
## Karate (E2E — `e2e/`)
See [e2e/CONVENTIONS.md](../../e2e/CONVENTIONS.md) for detailed rules.
See [e2e/CONVENTIONS.md](https://github.com/scub-france/Docling-Studio/blob/main/e2e/CONVENTIONS.md) for detailed rules.
Key points:
- Use `data-e2e` selectors, never CSS classes

View file

@ -0,0 +1,68 @@
# Audit 01 — Clean Architecture
**Objectif** : verifier que le backend respecte le flux de dependances strict `api -> services -> domain` et que chaque couche a une responsabilite claire.
**Cible** : `document-parser/` (hors `.venv/`, `__pycache__/`, `tests/`)
---
## Checklist
### 1.1 Domain (couche pure)
| # | Item | Poids |
|---|------|-------|
| 1.1.1 | `domain/` n'importe ni FastAPI, ni aiosqlite, ni aucune lib infra | 3 |
| 1.1.2 | Les modeles, value objects et ports ne font aucun I/O (file, HTTP, DB) | 3 |
| 1.1.3 | Toute interaction avec l'exterieur passe par un protocole dans `domain/ports.py` | 3 |
| 1.1.4 | Pas de Pydantic dans domain — le domain utilise des dataclasses | 2 |
### 1.2 Services (orchestration)
| # | Item | Poids |
|---|------|-------|
| 1.2.1 | `services/` n'importe jamais `fastapi`, `Request`, `Response`, `Depends` | 3 |
| 1.2.2 | Les services appellent les repos, jamais de requetes SQL directes | 3 |
| 1.2.3 | Les regles metier vivent dans `domain/`, pas dans les services | 2 |
| 1.2.4 | Les services recoivent leurs dependances par injection, pas par import direct de concretions | 2 |
### 1.3 API (couche HTTP)
| # | Item | Poids |
|---|------|-------|
| 1.3.1 | Les routes n'importent pas `persistence/` directement | 3 |
| 1.3.2 | Les transformations camelCase/snake_case restent dans `api/schemas.py` | 1 |
| 1.3.3 | Les endpoints delegent toute la logique aux services | 2 |
### 1.4 Infra (adaptateurs)
| # | Item | Poids |
|---|------|-------|
| 1.4.1 | Chaque adaptateur dans `infra/` implemente un protocole de `domain/ports.py` | 3 |
| 1.4.2 | Les valeurs de config viennent de `infra/settings.py`, pas de constantes en dur | 2 |
---
## Commandes de verification
```bash
# 1.1.1 — Domain ne doit importer aucune lib infra
grep -rn "from fastapi\|from aiosqlite\|from pydantic\|import fastapi\|import aiosqlite" document-parser/domain/
# 1.2.1 — Services ne doivent pas importer FastAPI
grep -rn "from fastapi\|import fastapi" document-parser/services/
# 1.3.1 — API ne doit pas importer persistence
grep -rn "from persistence\|import persistence" document-parser/api/
# 1.4.2 — Constantes en dur dans infra (hors settings)
grep -rn "= ['\"]http\|= [0-9]\{4,\}" document-parser/infra/ --include="*.py" | grep -v settings.py
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,78 @@
# Audit 02 — Domain-Driven Design (DDD)
**Objectif** : verifier que le code respecte les principes DDD — bounded contexts clairs, entites et value objects bien definis, ubiquitous language coherent, et separation des responsabilites metier.
**Cible** : `document-parser/domain/`, `document-parser/services/`, `frontend/src/features/`, `frontend/src/shared/types.ts`
---
## Checklist
### 2.1 Bounded Contexts
| # | Item | Poids |
|---|------|-------|
| 2.1.1 | Les contextes metier sont clairement identifies et isoles (document, analysis, chunking) | 3 |
| 2.1.2 | Chaque contexte a ses propres modeles — pas de modele "god object" partage entre contextes | 3 |
| 2.1.3 | Les frontieres entre contextes sont explicites — la communication passe par des contrats definis (DTOs, events), pas par des imports directs de modeles internes d'un autre contexte | 2 |
| 2.1.4 | Le frontend respecte les memes bounded contexts (features = contextes) | 2 |
### 2.2 Entites et Value Objects
| # | Item | Poids |
|---|------|-------|
| 2.2.1 | Les entites ont une identite unique (`id`) et un cycle de vie (Document, AnalysisJob) | 2 |
| 2.2.2 | Les value objects sont immutables et definis par leurs attributs, pas par une identite (ConversionResult, ChunkingOptions, BoundingBox) | 2 |
| 2.2.3 | Les value objects ne contiennent pas de logique de persistence (pas de `save()`, `update()`) | 3 |
| 2.2.4 | Les entites ne sont pas de simples "sacs de donnees" — elles portent du comportement metier quand c'est pertinent | 1 |
### 2.3 Ubiquitous Language
| # | Item | Poids |
|---|------|-------|
| 2.3.1 | Le vocabulaire metier est coherent entre domain, services, API et frontend (ex: "analysis" partout, pas "job" d'un cote et "analysis" de l'autre) | 2 |
| 2.3.2 | Les noms de classes/fonctions/variables refletent le langage du domaine, pas des termes techniques generiques (pas de `DataProcessor`, `Handler`, `Manager` sans contexte) | 1 |
| 2.3.3 | Les statuts metier utilisent un vocabulaire explicite (PENDING, RUNNING, COMPLETED, FAILED) | 1 |
### 2.4 Agregats et invariants
| # | Item | Poids |
|---|------|-------|
| 2.4.1 | Chaque agregat a une racine claire (Document est la racine de son agregat, AnalysisJob de son agregat) | 2 |
| 2.4.2 | Les invariants metier sont proteges dans le domaine — pas de creation d'etats invalides depuis l'exterieur | 3 |
| 2.4.3 | Les modifications d'un agregat passent par sa racine, pas par manipulation directe de ses composants internes | 2 |
### 2.5 Repositories et anti-corruption
| # | Item | Poids |
|---|------|-------|
| 2.5.1 | Les repositories (`persistence/`) manipulent des entites du domaine, pas des dictionnaires bruts ou des Row objects | 2 |
| 2.5.2 | La couche anti-corruption (schemas Pydantic) transforme les donnees externes (HTTP) en objets du domaine | 2 |
| 2.5.3 | Les adaptateurs infra (`infra/`) ne leakent pas leurs types internes vers les services (pas de types Docling exposes aux services) | 3 |
---
## Commandes de verification
```bash
# 2.1.2 — Chercher un modele omniscient
wc -l document-parser/domain/models.py
# 2.2.2 — Value objects mutables (setters, attributs reassignes)
grep -rn "\..*=" document-parser/domain/value_objects.py | grep -v "self\." | grep -v "__"
# 2.3.1 — Incoherences de vocabulaire (job vs analysis)
grep -rni "\bjob\b" document-parser/api/ document-parser/services/ --include="*.py" | grep -v "AnalysisJob"
grep -rni "\bjob\b" frontend/src/ --include="*.ts" --include="*.vue" | grep -v "node_modules"
# 2.5.3 — Types Docling qui leakent vers services
grep -rn "from docling\|import docling" document-parser/services/ --include="*.py"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,69 @@
# Audit 03 — Clean Code
**Objectif** : verifier la lisibilite, la clarte et la maintenabilite du code.
**Cible** : `document-parser/` (hors `.venv/`, `__pycache__/`), `frontend/src/`
---
## Checklist
### 3.1 Nommage
| # | Item | Poids |
|---|------|-------|
| 3.1.1 | Les fonctions sont nommees avec des verbes d'action (`create_analysis`, `upload_document`) | 1 |
| 3.1.2 | Les variables expriment l'intention (`remaining_pages` et non `rp`) | 1 |
| 3.1.3 | Tout le code est en anglais — les traductions i18n sont dans `shared/i18n.ts` | 2 |
| 3.1.4 | Pas d'abbreviations ambigues sauf conventions etablies (`dto`, `bbox`, `id`, `url`) | 1 |
### 3.2 Fonctions
| # | Item | Poids |
|---|------|-------|
| 3.2.1 | Chaque fonction fait une seule chose (Single Responsibility) | 2 |
| 3.2.2 | Aucune fonction ne depasse 30 lignes (hors boilerplate inevitable) | 1 |
| 3.2.3 | Aucune fonction n'a plus de 4 parametres | 1 |
| 3.2.4 | Pas de flag arguments (booleen qui change le comportement) | 1 |
| 3.2.5 | Une fonction `get_*` ne modifie pas d'etat (pas de side-effects caches) | 2 |
### 3.3 Fichiers et structure
| # | Item | Poids |
|---|------|-------|
| 3.3.1 | Aucun fichier source ne depasse 300 lignes | 1 |
| 3.3.2 | Un seul concept par fichier — pas de fichier fourre-tout | 2 |
| 3.3.3 | Imports ordonnes : stdlib, deps externes, imports internes | 1 |
### 3.4 Commentaires
| # | Item | Poids |
|---|------|-------|
| 3.4.1 | Le code est auto-documentant — les commentaires expliquent le "pourquoi", pas le "quoi" | 1 |
| 3.4.2 | Pas de code commente laisse en place (dead code) | 1 |
---
## Commandes de verification
```bash
# 3.3.1 — Fichiers Python > 300 lignes
find document-parser -name "*.py" -not -path "*/.venv/*" -not -path "*/__pycache__/*" -not -path "*/tests/*" | xargs wc -l | sort -rn | head -20
# 3.3.1 — Fichiers Vue/TS > 300 lignes
find frontend/src -name "*.vue" -o -name "*.ts" | xargs wc -l | sort -rn | head -20
# 3.2.3 — Fonctions avec > 4 parametres (Python)
grep -rn "def .*,.*,.*,.*,.*," document-parser --include="*.py" --exclude-dir=.venv --exclude-dir=__pycache__ --exclude-dir=tests
# 3.4.2 — Code commente
grep -rn "^[[:space:]]*#.*=\|^[[:space:]]*#.*def \|^[[:space:]]*#.*return\|^[[:space:]]*//.*=\|^[[:space:]]*//.*function" document-parser --include="*.py" --exclude-dir=.venv frontend/src --include="*.ts" --include="*.vue"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,43 @@
# Audit 04 — KISS (Keep It Simple, Stupid)
**Objectif** : verifier que le code reste simple et ne contient pas de sur-ingenierie.
**Cible** : `document-parser/` (hors `.venv/`, `__pycache__/`), `frontend/src/`
---
## Checklist
| # | Item | Poids |
|---|------|-------|
| 4.1 | Pas de design pattern complexe la ou un simple `if` ou une fonction suffit (factory, strategy, observer superflus) | 2 |
| 4.2 | Le code resout le probleme actuel, pas un probleme hypothetique futur (pas de genericite prematuree) | 2 |
| 4.3 | Pas de fonction wrapper qui ne fait qu'appeler une autre fonction sans valeur ajoutee | 1 |
| 4.4 | Utilisation des outils standard (Python stdlib, Vue composables natifs) avant de creer des solutions maison | 1 |
| 4.5 | Configuration simple — pas de systeme de config complexe la ou une variable d'env suffit | 1 |
| 4.6 | Pas d'indirection inutile — le chemin d'execution d'une requete ne traverse pas plus de couches que necessaire | 2 |
| 4.7 | Pas de meta-programmation ou de magie (decorateurs complexes, metaclasses) sauf necessite avere | 2 |
| 4.8 | Les structures de donnees utilisees sont les plus simples possibles (liste plutot que arbre si la liste suffit) | 1 |
---
## Commandes de verification
```bash
# 4.1 — Patterns potentiellement superflus
grep -rn "class.*Factory\|class.*Strategy\|class.*Observer\|class.*Builder\|class.*Singleton" document-parser --include="*.py" --exclude-dir=.venv
# 4.7 — Meta-programmation
grep -rn "__metaclass__\|type(.*,.*,.*)\|__init_subclass__\|__class_getitem__" document-parser --include="*.py" --exclude-dir=.venv
# 4.3 — Fonctions tres courtes (potentiels wrappers inutiles, < 3 lignes)
# Verification manuelle recommandee sur les fonctions identifiees
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,45 @@
# Audit 05 — DRY (Don't Repeat Yourself)
**Objectif** : verifier l'absence de duplication significative dans le code.
**Cible** : `document-parser/` (hors `.venv/`, `__pycache__/`), `frontend/src/`
---
## Checklist
| # | Item | Poids |
|---|------|-------|
| 5.1 | Aucun bloc de code identique ou quasi-identique n'apparait 3+ fois sans etre factorise | 2 |
| 5.2 | Les interfaces/types partages sont centralises dans `shared/types.ts` (frontend) et `domain/models.py` (backend) | 2 |
| 5.3 | Pas de magic numbers ou magic strings eparpilles — les constantes sont nommees et centralisees | 2 |
| 5.4 | La logique reactive partagee est dans `shared/composables/` (frontend) | 1 |
| 5.5 | Les appels API ne dupliquent pas la config HTTP (base URL, headers) — centralises dans `shared/api/http.ts` | 2 |
| 5.6 | Les schemas Pydantic ne dupliquent pas les modeles du domain — ils transforment, ils ne redefinissent pas | 2 |
| 5.7 | Les regles de validation ne sont definies qu'a un seul endroit (schema Pydantic OU frontend, pas les deux en desaccord) | 1 |
---
## Commandes de verification
```bash
# 5.3 — Magic numbers (backend)
grep -rn "[^a-zA-Z_\"'][0-9]\{3,\}[^a-zA-Z_\"']" document-parser --include="*.py" --exclude-dir=.venv --exclude-dir=tests --exclude-dir=__pycache__
# 5.3 — Magic strings repetees (backend)
grep -rohn '"[a-z_]\{5,\}"' document-parser --include="*.py" --exclude-dir=.venv --exclude-dir=tests | sort | uniq -c | sort -rn | head -20
# 5.5 — Appels fetch en dehors du client HTTP centralise
grep -rn "fetch(" frontend/src/ --include="*.ts" --include="*.vue" | grep -v "http.ts\|api.ts\|node_modules"
# 5.6 — Champs dupliques entre schemas et models
diff <(grep -o "[a-z_]*:" document-parser/api/schemas.py | sort -u) <(grep -o "[a-z_]*:" document-parser/domain/models.py | sort -u)
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,72 @@
# Audit 06 — SOLID
**Objectif** : verifier le respect des 5 principes SOLID.
**Cible** : `document-parser/` (hors `.venv/`, `__pycache__/`), `frontend/src/`
---
## Checklist
### 6.1 S — Single Responsibility Principle
| # | Item | Poids |
|---|------|-------|
| 6.1.1 | Chaque service a une responsabilite unique (`document_service` = documents, `analysis_service` = analyses) | 2 |
| 6.1.2 | Chaque store Pinia gere un seul feature | 2 |
| 6.1.3 | Les routes API sont groupees par ressource (`documents.py`, `analyses.py`) | 1 |
| 6.1.4 | Aucune classe ou module ne cumule des responsabilites heterogenes (ex: un service qui fait du parsing ET de la persistence) | 2 |
### 6.2 O — Open/Closed Principle
| # | Item | Poids |
|---|------|-------|
| 6.2.1 | Les ports (`domain/ports.py`) permettent d'ajouter de nouveaux adaptateurs sans modifier le code existant | 2 |
| 6.2.2 | Le systeme local/remote est extensible via `_build_converter()` sans modifier les services | 2 |
| 6.2.3 | L'ajout d'un nouveau format d'export ne necessite pas de modifier les endpoints existants | 1 |
### 6.3 L — Liskov Substitution Principle
| # | Item | Poids |
|---|------|-------|
| 6.3.1 | `LocalConverter` et `ServeConverter` sont interchangeables (meme protocole, meme contrat de retour) | 3 |
| 6.3.2 | Les implementations de ports ne lancent pas d'exceptions non prevues par le contrat | 2 |
| 6.3.3 | Pas de `isinstance()` ou `type()` check pour differencier les implementations | 2 |
### 6.4 I — Interface Segregation Principle
| # | Item | Poids |
|---|------|-------|
| 6.4.1 | `DocumentConverter` et `DocumentChunker` sont des ports separes (pas une "god interface") | 2 |
| 6.4.2 | Aucun port ne force une implementation a definir des methodes qu'elle n'utilise pas | 2 |
### 6.5 D — Dependency Inversion Principle
| # | Item | Poids |
|---|------|-------|
| 6.5.1 | Les services dependent de protocoles abstraits (ports), pas d'implementations concretes | 3 |
| 6.5.2 | L'injection se fait dans `main.py` (composition root) | 2 |
| 6.5.3 | Pas d'instanciation directe d'adaptateurs dans les services (`LocalConverter()` dans un service = violation) | 3 |
---
## Commandes de verification
```bash
# 6.3.3 — isinstance checks sur les adaptateurs
grep -rn "isinstance\|type(" document-parser/services/ --include="*.py"
# 6.5.3 — Instanciation directe d'adaptateurs dans services
grep -rn "LocalConverter\|ServeConverter\|LocalChunker" document-parser/services/ --include="*.py"
# 6.5.1 — Imports directs d'infra dans services
grep -rn "from infra\.\|import infra\." document-parser/services/ --include="*.py"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,71 @@
# Audit 07 — Decouplage
**Objectif** : verifier le decouplage entre frontend et backend, entre features, et la clarte des contrats d'interface.
**Cible** : `document-parser/`, `frontend/src/`, `docker-compose.yml`, `nginx.conf`
---
## Checklist
### 7.1 Decouplage Frontend / Backend
| # | Item | Poids |
|---|------|-------|
| 7.1.1 | Le frontend communique avec le backend uniquement via l'API REST — pas de couplage par fichier partage, DB partagee, ou import croise | 3 |
| 7.1.2 | Le contrat API est stable — les types TypeScript frontend correspondent aux schemas Pydantic backend | 3 |
| 7.1.3 | Le frontend peut tourner avec un mock du backend (les appels API sont isoles dans des fichiers `api.ts` par feature) | 2 |
| 7.1.4 | Le backend peut etre teste sans le frontend (endpoints testables via `httpx` / `TestClient`) | 2 |
| 7.1.5 | Pas de logique metier dupliquee entre front et back (ex: validation faite cote back ET reinventee cote front) | 2 |
### 7.2 Decouplage inter-features (Frontend)
| # | Item | Poids |
|---|------|-------|
| 7.2.1 | Chaque feature (`features/analysis`, `features/document`, ...) a son propre store, API client et composants UI | 2 |
| 7.2.2 | Les features ne s'importent pas mutuellement — la communication passe par `shared/` ou par les props/events Vue | 3 |
| 7.2.3 | Les types partages entre features sont dans `shared/types.ts`, pas dans une feature specifique | 2 |
| 7.2.4 | Un store Pinia n'accede pas directement au state d'un autre store (sauf via des getters exposes) | 2 |
### 7.3 Decouplage inter-couches (Backend)
| # | Item | Poids |
|---|------|-------|
| 7.3.1 | Les repos (`persistence/`) retournent des objets du domaine, pas des dicts ou des Row SQLite | 2 |
| 7.3.2 | Les adaptateurs infra n'exposent pas les types de leurs libs internes aux services (pas de types `docling.*` dans les signatures de services) | 3 |
| 7.3.3 | Le changement de base de donnees (SQLite -> PostgreSQL) ne necessite de modifier que `persistence/` | 2 |
| 7.3.4 | Le changement de framework HTTP (FastAPI -> autre) ne necessite de modifier que `api/` et `main.py` | 2 |
### 7.4 Contrats et interfaces
| # | Item | Poids |
|---|------|-------|
| 7.4.1 | Les ports dans `domain/ports.py` definissent des signatures claires avec des types du domaine | 2 |
| 7.4.2 | Les schemas Pydantic (`api/schemas.py`) documentent le contrat HTTP — pas de `dict` ou `Any` dans les responses | 2 |
| 7.4.3 | Les reponses API ont un format coherent (enveloppe, codes d'erreur normalises) | 1 |
---
## Commandes de verification
```bash
# 7.2.2 — Imports croises entre features
grep -rn "from.*features/" frontend/src/features/ --include="*.ts" --include="*.vue" | grep -v "node_modules" | grep -v "__tests__"
# 7.2.4 — Store qui accede au state d'un autre store
grep -rn "useDocumentStore\|useAnalysisStore\|useChunkingStore\|useHistoryStore\|useSettingsStore" frontend/src/features/ --include="*.ts" | grep -v "index.ts"
# 7.3.2 — Types docling qui leakent
grep -rn "from docling\|import docling" document-parser/services/ --include="*.py"
# 7.4.2 — dict ou Any dans les reponses API
grep -rn "-> dict\|-> Any\|Dict\[str, Any\]" document-parser/api/ --include="*.py"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,87 @@
# Audit 08 — Securite
**Objectif** : verifier l'absence de vulnerabilites courantes (OWASP Top 10) et le respect des bonnes pratiques de securite.
**Cible** : tout le projet
---
## Checklist
### 8.1 Secrets et credentials
| # | Item | Poids |
|---|------|-------|
| 8.1.1 | Aucune cle API, token, ou mot de passe en dur dans le code source | 3 |
| 8.1.2 | Les fichiers `.env` sont dans `.gitignore` | 3 |
| 8.1.3 | Les secrets Docker sont passes par variables d'environnement, pas en build args | 2 |
### 8.2 Validation des entrees
| # | Item | Poids |
|---|------|-------|
| 8.2.1 | Toutes les entrees utilisateur sont validees par des schemas Pydantic | 3 |
| 8.2.2 | `MAX_FILE_SIZE_MB` est configuree et appliquee a l'upload | 3 |
| 8.2.3 | Les types de fichiers acceptes sont valides (pas d'upload de `.exe`, `.sh`, etc.) | 2 |
### 8.3 Injection
| # | Item | Poids |
|---|------|-------|
| 8.3.1 | Les requetes SQL utilisent des parametres lies (`?`), jamais de string formatting/f-strings | 3 |
| 8.3.2 | Pas de `eval()`, `exec()`, ou `os.system()` avec des entrees utilisateur | 3 |
| 8.3.3 | Le frontend utilise DOMPurify pour tout rendu de contenu HTML/Markdown | 3 |
### 8.4 CORS et reseau
| # | Item | Poids |
|---|------|-------|
| 8.4.1 | Les origines CORS autorisees sont configurees explicitement, pas de `*` en production | 3 |
| 8.4.2 | Le rate limiter est actif sur tous les endpoints sauf `/api/health` | 2 |
| 8.4.3 | Nginx ne sert que les fichiers statiques prevus — pas de directory listing | 2 |
### 8.5 Dependances
| # | Item | Poids |
|---|------|-------|
| 8.5.1 | Pas de dependance avec des CVE critiques connues | 3 |
| 8.5.2 | Les versions des dependances sont epinglees (pas de `>=` sans borne superieure) | 1 |
---
## Commandes de verification
```bash
# 8.1.1 — Secrets potentiels dans le code
grep -rni "password\s*=\|secret\s*=\|api_key\s*=\|token\s*=" document-parser --include="*.py" --exclude-dir=.venv --exclude-dir=tests
grep -rni "password\|secret\|api.key\|token" frontend/src/ --include="*.ts" --include="*.vue"
# 8.1.2 — .env dans gitignore
grep "\.env" .gitignore
# 8.3.1 — SQL injection (f-strings dans les requetes)
grep -rn 'f".*SELECT\|f".*INSERT\|f".*UPDATE\|f".*DELETE\|f".*DROP' document-parser --include="*.py" --exclude-dir=.venv
# 8.3.2 — eval/exec/os.system
grep -rn "eval(\|exec(\|os\.system(\|subprocess\.call(" document-parser --include="*.py" --exclude-dir=.venv
# 8.3.3 — DOMPurify usage
grep -rn "DOMPurify\|v-html\|innerHTML" frontend/src/ --include="*.vue" --include="*.ts"
# 8.4.1 — CORS wildcard
grep -rn 'allow_origins.*\*\|"*"' document-parser --include="*.py" --exclude-dir=.venv
# 8.5.1 — Audit npm
cd frontend && npm audit --production 2>&1 | tail -10
# 8.5.1 — Audit pip (si pip-audit installe)
cd document-parser && pip-audit 2>&1 | tail -10
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,67 @@
# Audit 09 — Tests
**Objectif** : verifier la couverture, la qualite et la fiabilite de la suite de tests.
**Cible** : `document-parser/tests/`, `frontend/src/**/*.test.*`, `e2e/`
---
## Checklist
### 9.1 Execution
| # | Item | Poids |
|---|------|-------|
| 9.1.1 | Tous les tests backend passent (`pytest tests/ -v`) | 3 |
| 9.1.2 | Tous les tests frontend passent (`npm run test:run`) | 3 |
| 9.1.3 | Les tests e2e Karate UI passent | 2 |
### 9.2 Couverture
| # | Item | Poids |
|---|------|-------|
| 9.2.1 | Chaque endpoint API a au moins un test (happy path) | 2 |
| 9.2.2 | Les cas d'erreur des endpoints sont testes (400, 404, 413, 429) | 2 |
| 9.2.3 | Les services ont des tests unitaires couvrant la logique d'orchestration | 2 |
| 9.2.4 | Les fonctions du domain (bbox, value objects) sont testees | 1 |
| 9.2.5 | Les composants Vue critiques ont des tests (stores, composables) | 2 |
### 9.3 Qualite des tests
| # | Item | Poids |
|---|------|-------|
| 9.3.1 | Pas de `.only` ou `fdescribe` ou `fit` laisse par accident | 3 |
| 9.3.2 | Pas de `@pytest.mark.skip` ou `.skip()` sans justification en commentaire | 1 |
| 9.3.3 | Les tests sont deterministes — pas de dependance a l'heure, au reseau, ou a l'ordre d'execution | 2 |
| 9.3.4 | Les tests d'integration testent le flux reel, pas un mock complet | 2 |
| 9.3.5 | Les assertions sont specifiques (pas juste `assert result is not None`) | 1 |
| 9.3.6 | Chaque test a un nom explicite qui decrit le comportement teste | 1 |
---
## Commandes de verification
```bash
# 9.1.1 — Tests backend
cd document-parser && python -m pytest tests/ -v --tb=short 2>&1 | tail -30
# 9.1.2 — Tests frontend
cd frontend && npm run test:run 2>&1 | tail -30
# 9.3.1 — .only / fdescribe / fit
grep -rn "\.only\|fdescribe\|fit(" frontend/src/ --include="*.test.*"
# 9.3.2 — Skip sans commentaire
grep -rn -B1 "@pytest.mark.skip\|\.skip(" document-parser/tests/ frontend/src/
# 9.3.5 — Assertions vagues
grep -rn "assert.*is not None$\|assert.*!= None$\|expect.*toBeTruthy()$" document-parser/tests/ frontend/src/ --include="*.test.*" --include="*.py"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,66 @@
# Audit 10 — CI / Build
**Objectif** : verifier que la pipeline CI est verte, que le build Docker fonctionne, et que les outils de qualite sont actifs.
**Cible** : `.github/`, `Dockerfile`, `docker-compose.yml`, `nginx.conf`
---
## Checklist
### 10.1 Pipeline CI
| # | Item | Poids |
|---|------|-------|
| 10.1.1 | Toutes les GitHub Actions passent sur la branche de release | 3 |
| 10.1.2 | Les warnings ESLint sont resolus (0 warning) | 1 |
| 10.1.3 | Les warnings Ruff sont resolus (0 warning) | 1 |
| 10.1.4 | Le type-check frontend passe (`vue-tsc --noEmit`) | 2 |
| 10.1.5 | Le formatting est conforme (`ruff format --check`, `prettier --check`) | 1 |
### 10.2 Build Docker
| # | Item | Poids |
|---|------|-------|
| 10.2.1 | `docker compose build` reussit sans erreur | 3 |
| 10.2.2 | Le container demarre et repond sur `/api/health` | 3 |
| 10.2.3 | Les deux variantes (local/remote) buildent correctement | 2 |
| 10.2.4 | Pas de fichier inutile dans l'image (node_modules frontend, .venv, .git) — `.dockerignore` est a jour | 1 |
### 10.3 Configuration
| # | Item | Poids |
|---|------|-------|
| 10.3.1 | Nginx route correctement `/api/*` vers le backend et sert le frontend sur `/` | 2 |
| 10.3.2 | Les variables d'environnement sont documentees et ont des valeurs par defaut coherentes | 1 |
---
## Commandes de verification
```bash
# 10.1.2 + 10.1.3 — Lint
cd document-parser && ruff check . 2>&1 | tail -5
cd frontend && npx eslint src/ 2>&1 | tail -5
# 10.1.4 — Type check
cd frontend && npx vue-tsc --noEmit 2>&1 | tail -5
# 10.1.5 — Formatting
cd document-parser && ruff format --check . 2>&1 | tail -5
cd frontend && npx prettier --check src/ 2>&1 | tail -5
# 10.2.1 — Build Docker
docker compose build 2>&1 | tail -10
# 10.2.4 — .dockerignore
cat .dockerignore 2>/dev/null || echo "ABSENT"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,63 @@
# Audit 11 — Documentation & Changelog
**Objectif** : verifier que la release est correctement documentee et versionnee.
**Cible** : `CHANGELOG.md`, `frontend/package.json`, `docs/`, code source
---
## Checklist
### 11.1 Changelog
| # | Item | Poids |
|---|------|-------|
| 11.1.1 | La section `[Unreleased]` a ete renommee en `[X.Y.Z] - YYYY-MM-DD` | 3 |
| 11.1.2 | Toutes les modifications significatives de la release sont listees dans le changelog | 2 |
| 11.1.3 | Les breaking changes sont clairement identifies | 3 |
| 11.1.4 | Le format respecte [Keep a Changelog](https://keepachangelog.com/) | 1 |
### 11.2 Versioning
| # | Item | Poids |
|---|------|-------|
| 11.2.1 | `frontend/package.json` contient la bonne version X.Y.Z | 2 |
| 11.2.2 | La version suit le Semantic Versioning | 2 |
### 11.3 Code propre
| # | Item | Poids |
|---|------|-------|
| 11.3.1 | Les `TODO` et `FIXME` restants sont volontaires et documentes (pas de TODO orphelin) | 1 |
| 11.3.2 | Pas de `console.log` de debug laisse dans le code frontend | 2 |
| 11.3.3 | Pas de `print()` de debug laisse dans le code backend (hors logging structure) | 2 |
---
## Commandes de verification
```bash
# 11.1.1 — Section Unreleased encore presente
grep -n "Unreleased" CHANGELOG.md
# 11.2.1 — Version dans package.json
grep '"version"' frontend/package.json
# 11.3.1 — TODOs restants
grep -rn "TODO\|FIXME\|HACK\|XXX" document-parser --include="*.py" --exclude-dir=.venv --exclude-dir=__pycache__
grep -rn "TODO\|FIXME\|HACK\|XXX" frontend/src --include="*.ts" --include="*.vue"
# 11.3.2 — console.log de debug
grep -rn "console\.log\|console\.debug\|console\.warn" frontend/src/ --include="*.ts" --include="*.vue" | grep -v "node_modules"
# 11.3.3 — print() de debug
grep -rn "^\s*print(" document-parser --include="*.py" --exclude-dir=.venv --exclude-dir=tests --exclude-dir=__pycache__
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

View file

@ -0,0 +1,61 @@
# Audit 12 — Performance & Ressources
**Objectif** : verifier l'absence de problemes de performance evidents et la bonne gestion des ressources.
**Cible** : `document-parser/` (hors `.venv/`), `frontend/src/`
---
## Checklist
### 12.1 Backend
| # | Item | Poids |
|---|------|-------|
| 12.1.1 | Pas de requete N+1 — les acces DB sont optimises (pas de boucle avec requete unitaire) | 2 |
| 12.1.2 | Les fichiers uploades temporaires sont supprimes apres traitement | 2 |
| 12.1.3 | `MAX_CONCURRENT_ANALYSES` est configuree et respectee (semaphore) | 2 |
| 12.1.4 | Les operations longues (conversion Docling) sont asynchrones et ne bloquent pas l'event loop | 3 |
| 12.1.5 | Pas de chargement de fichier entier en memoire sans necesssite (streaming si possible) | 2 |
### 12.2 Frontend
| # | Item | Poids |
|---|------|-------|
| 12.2.1 | Les watchers Vue ont leur cleanup (pas de memory leak) | 2 |
| 12.2.2 | Les event listeners sont supprimes dans `onUnmounted` | 2 |
| 12.2.3 | Les requetes API ont un mecanisme d'annulation ou de debounce quand pertinent | 1 |
| 12.2.4 | Pas de re-render excessif — les computed sont utilises plutot que des fonctions dans le template | 1 |
| 12.2.5 | Les assets lourds (images, fonts) sont optimises | 1 |
### 12.3 Infrastructure
| # | Item | Poids |
|---|------|-------|
| 12.3.1 | Nginx a une configuration de cache pour les fichiers statiques | 1 |
| 12.3.2 | Les reponses API sont de taille raisonnable (pas d'envoi de donnees inutiles) | 1 |
| 12.3.3 | Le health check est leger et ne charge pas le systeme | 1 |
---
## Commandes de verification
```bash
# 12.1.1 — Pattern N+1 (boucle avec requete DB)
grep -rn -A5 "for.*in.*:" document-parser/persistence/ --include="*.py" | grep -i "select\|fetch\|execute"
# 12.1.4 — Appels bloquants dans du code async
grep -rn "time\.sleep\|open(" document-parser/services/ --include="*.py"
# 12.2.1 + 12.2.2 — Watchers et listeners sans cleanup
grep -rn "addEventListener\|watch(\|watchEffect(" frontend/src/ --include="*.vue" --include="*.ts" | grep -v "node_modules"
grep -rn "onUnmounted\|onBeforeUnmount\|removeEventListener" frontend/src/ --include="*.vue" | grep -v "node_modules"
```
---
## Regles de notation
- Tout item de poids 3 non conforme = ecart `[CRIT]`
- Tout item de poids 2 non conforme = ecart `[MAJ]`
- Tout item de poids 1 non conforme = ecart `[MIN]`

206
docs/audit/master.md Normal file
View file

@ -0,0 +1,206 @@
# Audit Master — Release Branch Quality Gate
Referentiel central d'audit qualite pour les branches `release/X.Y.Z` de Docling Studio.
Ce document est le **chef d'orchestre** : il definit les regles, commandite les audits unitaires, et normalise les rapports.
---
## 1. Perimetre
L'audit s'execute sur une branche `release/X.Y.Z` **apres feature freeze**, avant le merge dans `main`.
**Cibles :**
| Cible | Chemin |
|-------|--------|
| Backend (Python/FastAPI) | `document-parser/` (hors `.venv/`, `__pycache__/`, `tests/`) |
| Frontend (Vue 3/TypeScript) | `frontend/src/` |
| Tests backend | `document-parser/tests/` |
| Tests frontend | `frontend/src/**/*.test.*` |
| Tests e2e | `e2e/` |
| Infrastructure | `Dockerfile`, `docker-compose.yml`, `nginx.conf`, `.github/` |
---
## 2. Niveaux de criticite
Chaque ecart trouve lors d'un audit est classe selon ces 4 niveaux :
| Niveau | Tag | Description | Impact sur le GO/NO-GO |
|--------|-----|-------------|------------------------|
| **CRITICAL** | `[CRIT]` | Violation bloquante — faille de securite, corruption de donnees, violation d'architecture majeure | **Bloquant** — le release ne peut pas partir |
| **MAJOR** | `[MAJ]` | Violation significative — couplage fort, dette technique importante, test manquant sur un chemin critique | Bloquant si > 3 ecarts MAJOR non resolus |
| **MINOR** | `[MIN]` | Ecart de qualite — nommage, taille de fichier, duplication legere | Non bloquant — a corriger dans le prochain cycle |
| **INFO** | `[INFO]` | Observation, suggestion d'amelioration, bonne pratique non respectee mais sans risque | Non bloquant — informatif |
---
## 3. Bareme de compliance
Chaque audit unitaire produit une **note de compliance sur 100**.
### Calcul
Chaque item de checklist a un **poids** defini dans la fiche d'audit :
| Poids | Signification |
|-------|---------------|
| 3 | Critique — violation = ecart CRITICAL |
| 2 | Important — violation = ecart MAJOR |
| 1 | Standard — violation = ecart MINOR |
**Formule :**
```
score = (somme des poids des items conformes / somme totale des poids) * 100
```
### Seuils de decision
| Score | Verdict | Action |
|-------|---------|--------|
| >= 80 | **GO** | Release autorisee |
| 60 - 79 | **GO CONDITIONNEL** | Release autorisee si 0 CRITICAL, plan de remediation pour les MAJOR |
| < 60 | **NO-GO** | Release bloquee corriger et re-auditer |
**Regle absolue** : tout ecart `[CRIT]` non resolu = **NO-GO** quel que soit le score.
---
## 4. Liste des audits
Les audits sont executes dans l'ordre ci-dessous. Chacun est une fiche autonome dans `audits/`.
| # | Audit | Fichier | Focus |
|---|-------|---------|-------|
| 01 | Clean Architecture | [01-clean-architecture.md](audits/01-clean-architecture.md) | Respect des couches, flux de dependances |
| 02 | DDD | [02-ddd.md](audits/02-ddd.md) | Bounded contexts, entites, value objects, ubiquitous language |
| 03 | Clean Code | [03-clean-code.md](audits/03-clean-code.md) | Nommage, taille, lisibilite |
| 04 | KISS | [04-kiss.md](audits/04-kiss.md) | Simplicite, pas de sur-ingenierie |
| 05 | DRY | [05-dry.md](audits/05-dry.md) | Duplication, factorisation |
| 06 | SOLID | [06-solid.md](audits/06-solid.md) | 5 principes SOLID |
| 07 | Decouplage | [07-decoupling.md](audits/07-decoupling.md) | Front/back, inter-features, contrats |
| 08 | Securite | [08-security.md](audits/08-security.md) | OWASP, secrets, injection, CORS |
| 09 | Tests | [09-tests.md](audits/09-tests.md) | Couverture, qualite, e2e |
| 10 | CI / Build | [10-ci-build.md](audits/10-ci-build.md) | Pipeline, Docker, health check |
| 11 | Documentation | [11-documentation.md](audits/11-documentation.md) | Changelog, version, TODOs |
| 12 | Performance | [12-performance.md](audits/12-performance.md) | N+1, memory, concurrence |
---
## 5. Format de rapport attendu
Chaque audit produit un rapport dans `reports/release-X.Y.Z/XX-nom.md` respectant ce format :
```markdown
# Rapport d'audit : [Nom de l'audit]
**Release** : X.Y.Z
**Date** : YYYY-MM-DD
**Auditeur** : [nom ou "claude-code"]
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | XX / YY |
| Score | XX / 100 |
| Ecarts CRITICAL | N |
| Ecarts MAJOR | N |
| Ecarts MINOR | N |
| Ecarts INFO | N |
---
## Ecarts constates
### [CRIT] Titre de l'ecart
- **Localisation** : `chemin/fichier.py:ligne`
- **Constat** : description factuelle
- **Regle violee** : reference a l'item de checklist
- **Remediation** : action corrective proposee
### [MAJ] Titre de l'ecart
...
### [MIN] Titre de l'ecart
...
### [INFO] Titre de l'ecart
...
---
## Points positifs
- ...
---
## Verdict partiel : GO / GO CONDITIONNEL / NO-GO
```
---
## 6. Rapport de synthese
Le fichier `reports/release-X.Y.Z/summary.md` consolide tous les audits :
```markdown
# Synthese d'audit — Release X.Y.Z
**Date** : YYYY-MM-DD
**Branche** : release/X.Y.Z
---
## Tableau de bord
| # | Audit | Score | CRIT | MAJ | MIN | INFO | Verdict |
|---|-------|-------|------|-----|-----|------|---------|
| 01 | Clean Architecture | XX | N | N | N | N | GO |
| 02 | DDD | XX | N | N | N | N | GO |
| ... | ... | ... | ... | ... | ... | ... | ... |
**Score global** : XX / 100 (moyenne ponderee)
**Ecarts CRITICAL totaux** : N
**Ecarts MAJOR totaux** : N
---
## Ecarts CRITICAL (tous audits confondus)
1. [audit] description — fichier:ligne
---
## Verdict final : GO / GO CONDITIONNEL / NO-GO
Conditions (si GO CONDITIONNEL) :
- ...
```
---
## 7. Execution
### Lancer un audit complet
```
Audite la branche release/X.Y.Z en suivant docs/audit/master.md
```
### Lancer un audit unitaire
```
Execute l'audit docs/audit/audits/02-ddd.md sur la branche courante
```
### Re-auditer apres correction
```
Re-audite uniquement les ecarts CRITICAL et MAJOR du rapport docs/audit/reports/release-X.Y.Z/summary.md
```

View file

View file

@ -0,0 +1,67 @@
# Rapport d'audit : Clean Architecture
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
**Derniere mise a jour** : 2026-04-10 (re-audit post PR #133)
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 13 / 13 |
| Score | 100 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts resolus (PR #133 — fix/clean-architecture-audit)
### [CRIT — RESOLU] Services importent directement les modules persistence (concretions)
- **Localisation** : `services/analysis_service.py`, `services/document_service.py`
- **Resolution** : `AnalysisService` et `DocumentService` recoivent `analysis_repo` et `document_repo` par injection dans leur constructeur. Plus aucun import direct de `persistence.*` au top-level des services.
### [CRIT — RESOLU] Services importent directement `infra.settings`
- **Localisation** : `services/analysis_service.py`, `services/document_service.py`
- **Resolution** : Les valeurs de configuration sont encapsulees dans des dataclasses `AnalysisConfig` et `DocumentConfig` injectees dans les constructeurs. Plus aucun import direct de `infra.settings` dans les services.
### [CRIT — RESOLU] Pas de protocol pour les repositories dans `domain/ports.py`
- **Localisation** : `domain/ports.py`
- **Resolution** : `DocumentRepository` et `AnalysisRepository` ajoutes comme `Protocol` dans `domain/ports.py`. Les services dependent maintenant de ces abstractions.
### [MAJ — RESOLU] `document_service` est un module procedural, non une classe injectable
- **Resolution** : `document_service` transforme en classe `DocumentService` avec injection du repository et de la config.
### [MAJ — RESOLU] Logique metier dans le service (`_classify_error`, `_merge_results`, validation)
- **Resolution** : `_merge_results` et `_classify_error` deplaces dans `domain/`. Validation de fichier encapsulee.
### [MIN — RESOLU] `api/documents.py` importe `infra.settings`
- **Resolution** : La valeur `max_file_size_mb` obtenue via le service, plus d'import direct dans la couche API.
---
## Points positifs
- Domain pur : `domain/models.py`, `domain/value_objects.py` et `domain/ports.py` n'importent aucune librairie externe. Les modeles sont des dataclasses pures avec des methodes de transition d'etat.
- Ports complets : `DocumentConverter`, `DocumentChunker`, `DocumentRepository` et `AnalysisRepository` couvrent toutes les interactions externes.
- Injection de dependances complete : services, repositories et config injectes via constructeur + `Depends` FastAPI.
- Pydantic confine a la couche API : Tous les schemas Pydantic sont dans `api/schemas.py`. Le domaine n'utilise que des dataclasses.
- Routes delegent aux services : Les endpoints se contentent de mapper les requetes/reponses et de deleguer.
- Configuration centralisee dans `infra/settings.py` et propagee par injection.
---
## Verdict : GO
Score 100/100 — 0 ecart critique. Toutes les non-conformites precedentes resolues via PR #133.

View file

@ -0,0 +1,57 @@
# Rapport d'audit : Domain-Driven Design (DDD)
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
**Derniere mise a jour** : 2026-04-10 (re-audit post PR #135)
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 16 / 16 |
| Score | 100 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts resolus (PR #135 — fix/ddd-audit)
### [CRIT — RESOLU] Invariants metier non proteges dans la state machine
- **Localisation** : `domain/models.py` (methodes `mark_running`, `mark_completed`, `update_progress`, `mark_failed`)
- **Resolution** : Guard clauses ajoutees dans les 4 methodes de transition. `mark_running` leve `ValueError` si status != PENDING. `mark_completed` leve si status != RUNNING. `update_progress` leve si status != RUNNING. `mark_failed` accepte PENDING ou RUNNING uniquement. 11 tests couvrent les transitions valides et invalides dans `TestAnalysisJobGuardClauses`.
### [MAJ — RESOLU] Value objects non immutables
- **Localisation** : `domain/value_objects.py`
- **Resolution** : `frozen=True` ajoute sur les 7 dataclasses : `PageElement`, `PageDetail`, `ConversionOptions`, `ConversionResult`, `ChunkingOptions`, `ChunkBbox`, `ChunkResult`. Les instances sont desormais immutables et hashables.
### [MAJ — RESOLU] Vocabulaire inconsistant "analysis" vs "job"
- **Resolution** : Le terme `analysis` unifie dans les couches exposees (API, frontend, store). `AnalysisJob` conserve en domaine interne pour sa semantique de job long-running, les interfaces publiques utilisent `analysis_id`.
---
## Points positifs
- Bounded contexts clairement identifies et isoles (Document, Analysis/Chunking) avec des modeles, services et repos separes
- `domain/models.py` compact avec deux entites bien definies, pas de "god object"
- `AnalysisJob` porte du comportement metier (state machine, progress tracking) avec invariants proteges
- State machine exhaustivement testee (11 tests de guard clauses)
- Value objects immutables et hashables (`frozen=True`)
- Les repositories retournent des entites du domaine, pas des dicts ou Row objects
- La couche anti-corruption (schemas Pydantic) transforme correctement les donnees HTTP en objets du domaine
- Les adaptateurs infra ne leakent pas les types Docling vers les services
- Le frontend respecte les memes bounded contexts (features = contextes)
---
## Verdict : GO
Score 100/100 — 0 ecart critique. Toutes les non-conformites precedentes resolues via PR #135.

View file

@ -0,0 +1,74 @@
# Rapport d'audit : Clean Code
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
**Derniere mise a jour** : 2026-04-10 (re-audit post PR #139)
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 12 / 14 |
| Score | 93 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 2 |
| Ecarts INFO | 0 |
---
## Ecarts resolus (PR #139 — fix/clean-code-audit)
### [MAJ — RESOLU] Code non entierement en anglais — mode strings en francais
- **Localisation** : `frontend/src/pages/StudioPage.vue`, `frontend/src/features/history/navigation.test.ts`
- **Resolution** : `configurer``configure`, `verifier``verify`, `preparer``prepare`. Toutes les valeurs d'etat internes sont en anglais.
### [MAJ — RESOLU] `_run_analysis_inner` viole le Single Responsibility
- **Localisation** : `services/analysis_service.py`
- **Resolution** : 3 sous-fonctions extraites : `_build_conversion_options()` (construit `ConversionOptions` avec table_mode par defaut), `_run_conversion()` (orchestre batched vs single), `_finalize_analysis()` (serialise, chunke, marque completed). `_run_analysis_inner` reduite a 20 lignes d'orchestration.
### [MAJ — RESOLU] `_get_default_converter()` modifie un etat global
- **Localisation** : `infra/local_converter.py`
- **Resolution** : Renomme en `_ensure_default_converter()`. Tous les call sites mis a jour. Les 9 patches de test mis a jour.
---
## Ecarts residuels
### [MIN] Fonctions depassant 30 lignes
- **Localisation** : `infra/local_converter.py` (~50 et ~48 lignes), `infra/local_chunker.py` (~48 lignes)
- **Constat** : 3-4 fonctions restent au-dessus de 30 lignes apres les extractions (les fonctions de construction de pipeline Docling sont difficiles a decomposer sans perte de lisibilite).
- **Regle violee** : 3.2.2 — Aucune fonction ne depasse 30 lignes
### [MIN] Fichiers source depassant 300 lignes
- **Localisation** : `StudioPage.vue` (~1200 lignes dont ~700 de CSS), `ResultTabs.vue` (~690 lignes), `ChunkPanel.vue` (~483 lignes)
- **Constat** : Les fichiers Vue restent volumineux. Decomposition en sous-composants reportee (hors perimetre de cette PR).
- **Regle violee** : 3.3.1 — Aucun fichier source ne depasse 300 lignes
---
## Points positifs
- Nommage excellent : verbes d'action, variables expressives, conventions respectees
- Pas de flag arguments booleen
- Un concept par fichier, architecture bien organisee
- Imports ordonnes (isort/Ruff)
- Commentaires pertinents expliquant le "pourquoi"
- Pas de code commente/dead code
- Pas d'abbreviations ambigues
- SRP respecte dans `_run_analysis_inner` apres extraction des 3 sous-fonctions
- Nommage descriptif : `_ensure_default_converter` communique le side-effect intentionnel
---
## Verdict : GO
Score 93/100 — 0 ecart CRITICAL, 0 ecart MAJOR. 2 ecarts MINOR residuels (longueur de fonctions/fichiers) planifies pour le prochain cycle. Seuil GO atteint.

View file

@ -0,0 +1,43 @@
# Rapport d'audit : KISS (Keep It Simple, Stupid)
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 8 / 8 |
| Score | 100 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts constates
Aucun ecart constate.
---
## Points positifs
- Aucune classe Factory, Strategy, Observer, Builder ni Singleton detectee
- Le pattern Ports & Adapters est justifie (deux implementations reelles) avec un wiring minimal (`if/else` dans `main.py`)
- Les Protocols sont la forme la plus legere possible d'interfaces (duck typing Python)
- Les features implementees correspondent a des cas d'usage reels, pas de genericite prematuree
- Le systeme i18n est un dictionnaire statique simple (~80 cles), pas de lib lourde
- Le feature flag system est minimal (2 flags, un registre de 2 entrees)
- Configuration via un simple dataclass + env vars, pas de framework de config
- Aucune meta-programmation, metaclass, ou magie detectee
- Structures de donnees simples (dataclasses plates, listes, schema SQLite a 2 tables)
- Chemin d'execution d'une requete : 4 couches justifiees (HTTP -> Service -> Persistence + Infra)
---
## Verdict partiel : GO

View file

@ -0,0 +1,44 @@
# Rapport d'audit : DRY (Don't Repeat Yourself)
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 6 / 7 |
| Score | 83 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 1 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts constates
### [MAJ] Magic numbers 612.0 / 792.0 dupliques dans `serve_converter.py`
- **Localisation** : `infra/serve_converter.py:195,196,223,224`
- **Constat** : Les dimensions US Letter (612.0, 792.0) sont utilisees comme litteraux bruts 4 fois, alors que `local_converter.py` definit correctement les constantes nommees `_DEFAULT_PAGE_WIDTH` et `_DEFAULT_PAGE_HEIGHT`.
- **Regle violee** : 5.3 — Pas de magic numbers eparpilles
- **Remediation** : Extraire ces constantes dans un module partage ou les importer depuis `local_converter.py`.
---
## Points positifs
- Aucun bloc de code identique n'apparait 3+ fois sans factorisation
- Types partages centralises dans `shared/types.ts` (frontend) et `domain/models.py` + `domain/value_objects.py` (backend)
- Logique reactive partagee dans `shared/composables/usePagination.ts`
- Appels API centralises via `apiFetch` dans `shared/api/http.ts` — zero fuite de `fetch()` brut
- Schemas Pydantic transforment les modeles domaine, ne les redefinissent pas
- Regles de validation definies en un seul endroit (backend = source de verite, frontend = UX optimization)
---
## Verdict partiel : GO

View file

@ -0,0 +1,38 @@
# Rapport d'audit : SOLID
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 15 / 15 |
| Score | 100 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts constates
Aucun ecart constate.
---
## Points positifs
- **S (SRP)** : Chaque service, store Pinia et router a une responsabilite unique bien definie
- **O (OCP)** : Les ports permettent d'ajouter de nouveaux adaptateurs sans modifier le code existant. Le wiring local/remote est extensible via `_build_converter()`
- **L (LSP)** : `LocalConverter` et `ServeConverter` sont pleinement interchangeables. Zero `isinstance` dans les services pour differencier les implementations
- **I (ISP)** : `DocumentConverter` et `DocumentChunker` sont des ports separes avec une seule methode chacun
- **D (DIP)** : Les services dependent des protocols abstraits. L'injection se fait dans `main.py` (composition root). Zero instanciation directe d'adaptateurs dans les services
---
## Verdict partiel : GO

View file

@ -0,0 +1,73 @@
# Rapport d'audit : Decouplage
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
**Derniere mise a jour** : 2026-04-10 (re-audit post PR #144)
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 16 / 16 |
| Score | 100 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts resolus (PR #144 — fix/decoupling-audit)
### [CRIT — RESOLU] Imports croises entre features frontend
- **Localisation** : `features/history/store.ts`, `features/chunking/`, `features/document/store.ts`, `shared/i18n.ts`
- **Resolution** :
- `shared/appConfig.ts` cree comme pont reactif neutre (`appLocale`, `appMaxFileSizeMb`, `appMaxPageCount`).
- `shared/i18n.ts` lit `appLocale` depuis `shared/appConfig` — plus d'import depuis `features/`.
- `features/document/store.ts` lit `appMaxFileSizeMb` depuis `shared/appConfig` — plus d'import de `useFeatureFlagStore`.
- `features/feature-flags/store.ts` ecrit dans `appConfig` lors du chargement.
- `features/settings/store.ts` ecrit `appLocale` lors du changement de langue.
### [MAJ — RESOLU] Features `chunking` et `history` sans store/API propres
- **Resolution** :
- `features/chunking/api.ts` cree avec `rechunkAnalysis()`.
- `features/chunking/store.ts` cree avec `useChunkingStore` (state: `rechunking`, `error`; action: `rechunk()`).
- `features/history/api.ts` cree avec `fetchHistory()` et `deleteHistoryEntry()`.
- `features/history/store.ts` reecrit comme store Pinia distinct (state: `analyses`, `error`; actions: `load()`, `remove()`).
### [MAJ — RESOLU] Collapse d'identite store history/analysis
- **Resolution** : `useHistoryStore` est desormais un store Pinia independant avec son propre state et ses propres appels API. Plus de re-export vers `useAnalysisStore`.
### [MAJ — RESOLU] Health endpoint sans schema Pydantic
- **Resolution** : `HealthResponse` schema Pydantic cree dans `api/schemas.py`. Le endpoint `/api/health` retourne `HealthResponse` avec `response_model=HealthResponse`.
### [MIN — RESOLU] Pas de format de reponse API coherent
- **Resolution** : Le schema `HealthResponse` etablit le pattern type pour les endpoints systeme. Les erreurs fonctionnelles utilisent le format standard FastAPI `HTTPException` de facon coherente.
---
## Points positifs
- Decouplage frontend/backend exemplaire via API REST, nginx proxy, et services Docker separes
- Contrat API stable : types TypeScript alignes sur les schemas Pydantic avec serialisation camelCase
- Backend pleinement testable sans frontend (TestClient)
- Repos retournent des objets domaine, pas de dicts ou Row SQLite
- Les adaptateurs infra ne leakent pas les types Docling vers les services
- Changement de DB ne necessiterait de modifier que `persistence/`
- Ports avec signatures claires utilisant des types du domaine
- Features frontend isolees : chaque feature possede son store, son API client et ses composants UI
- `shared/appConfig.ts` pattern : pont reactif sans couplage de feature a feature
---
## Verdict : GO
Score 100/100 — 0 ecart critique. Toutes les non-conformites precedentes resolues via PR #144.

View file

@ -0,0 +1,57 @@
# Rapport d'audit : Securite
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 13 / 14 |
| Score | 97 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 1 |
| Ecarts INFO | 1 |
---
## Ecarts constates
### [MIN] `python-multipart>=0.0.12` sans borne superieure
- **Localisation** : `document-parser/requirements.txt`
- **Constat** : `python-multipart>=0.0.12` n'a pas de borne superieure, contrairement aux autres dependances.
- **Regle violee** : 8.5.2 — Les versions des dependances sont epinglees
- **Remediation** : Ajouter `<1.0.0` pour la coherence.
### [INFO] Mismatch nginx `client_max_body_size 5M` vs `MAX_FILE_SIZE_MB=50`
- **Localisation** : `nginx.conf`, `frontend/nginx.conf`, `infra/settings.py`
- **Constat** : Nginx rejette les uploads > 5MB avant que le backend (configure a 50MB par defaut) ne les voie. Pas un probleme de securite (plus restrictif), mais un probleme de coherence fonctionnelle.
- **Remediation** : Aligner nginx `client_max_body_size` avec `MAX_FILE_SIZE_MB` ou rendre configurable.
---
## Points positifs
- Zero secret hardcode dans le code source — tout via env vars
- `.env` dans `.gitignore` (+ `.env.local`, `.env.production`)
- Secrets Docker passes via `environment:`, pas `build: args:`
- Toutes les entrees validees par schemas Pydantic avec validators
- `MAX_FILE_SIZE_MB` enforce en double couche (eager check + streaming check)
- Validation de contenu PDF par magic bytes, pas seulement par extension
- SQL parametrise partout (`?` placeholders), zero f-string SQL
- Zero `eval()`, `exec()`, `os.system()` dans le code
- DOMPurify utilise sur l'unique `v-html` (MarkdownViewer)
- CORS explicitement configure, pas de wildcard `*`
- Rate limiter actif sur tous les endpoints sauf `/api/health`
- Nginx sans `autoindex`, avec headers de securite
- Dependances recentes sans CVE critiques connues
---
## Verdict partiel : GO

View file

@ -0,0 +1,65 @@
# Rapport d'audit : Tests
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 11 / 14 |
| Score | 100 / 100 (*) |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 3 |
(*) Score calcule sur les 11 items verifiables. Les 3 items d'execution (9.1.x) sont marques [INFO] car non executables dans le contexte d'audit.
---
## Ecarts constates
### [INFO] Execution des tests backend non verifiable
- **Localisation** : `document-parser/tests/`
- **Constat** : 14 fichiers de tests backend bien structures. Execution non possible dans le contexte d'audit.
- **Regle violee** : 9.1.1 — Tous les tests backend passent
- **Remediation** : Verifier via CI (GitHub Actions).
### [INFO] Execution des tests frontend non verifiable
- **Localisation** : `frontend/src/**/*.test.*`
- **Constat** : 15 fichiers de tests frontend bien structures. Execution non possible dans le contexte d'audit.
- **Regle violee** : 9.1.2 — Tous les tests frontend passent
- **Remediation** : Verifier via CI.
### [INFO] Execution des tests e2e Karate UI non verifiable
- **Localisation** : `e2e/`
- **Constat** : Suite e2e comprehensive (10+ features UI, 13+ features API). Execution non possible dans le contexte d'audit.
- **Regle violee** : 9.1.3 — Les tests e2e Karate UI passent
- **Remediation** : Verifier via CI (release-gate).
---
## Points positifs
- Couverture complete : tous les 11 endpoints API ont des tests happy-path
- Cas d'erreur testes (400, 404, 413, 422, 429) avec verification des messages et headers
- Tests de services complets : concurrence, batch, cancellation, regression
- Domain teste en profondeur (bbox : 19 tests, models, schemas, value objects)
- Tous les stores et composables Vue sont testes (15 fichiers, 100+ tests)
- Zero `.only`, `fdescribe`, ou `fit` laisse par accident
- Tous les `@pytest.mark.skip` sont justifies (dependance `docling` optionnelle)
- Tests deterministes : `vi.useFakeTimers()`, `patch("time.monotonic")`, fresh Pinia instances
- Tests d'integration sur flux reel (SQLite reel, TestClient, async tasks)
- Assertions specifiques partout (zero `is not None` ou `toBeTruthy()` isolees)
- Noms de tests descriptifs et explicites
---
## Verdict partiel : GO

View file

@ -0,0 +1,55 @@
# Rapport d'audit : CI / Build
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 9 / 11 |
| Score | 90 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 2 |
| Ecarts INFO | 0 |
---
## Ecarts constates
### [MIN] ESLint n'enforce pas zero warnings
- **Localisation** : `.github/workflows/ci.yml:69`, `.github/workflows/release-gate.yml:53`
- **Constat** : `npx eslint src/` est invoque sans `--max-warnings 0`. Les warnings passent silencieusement.
- **Regle violee** : 10.1.2 — Les warnings ESLint sont resolus (0 warning)
- **Remediation** : Ajouter `--max-warnings 0` a la commande ESLint dans les deux workflows.
### [MIN] Checks de formatting absents du CI
- **Localisation** : `.github/workflows/` (tous les workflows)
- **Constat** : Ni `ruff format --check` ni `prettier --check` ne sont executes dans les workflows CI.
- **Regle violee** : 10.1.5 — Le formatting est conforme
- **Remediation** : Ajouter les steps `ruff format --check .` et `npx prettier --check src/` aux jobs lint.
---
## Points positifs
- Pipeline CI comprehensive : `ci.yml` (push/PR), `release-gate.yml` (4 phases), `release.yml` (multi-arch), `docling-compat.yml` (cron daily)
- Ruff check enforce (zero tolerance par defaut)
- Type-check frontend via `vue-tsc --noEmit` dans CI
- Docker build des deux variantes (local/remote) via matrix strategy
- Smoke test automatise : demarrage container + validation `/api/health` (status, engine)
- Trivy security scan + check taille image
- `.dockerignore` complet (git, tests, docs, dev artifacts exclus)
- Nginx route correctement `/api/*` -> backend, `/` -> frontend
- Variables d'environnement documentees dans `.env.example` avec defaults coherents
- Multi-stage Dockerfile optimise (node build, python runtime, non-root user)
---
## Verdict partiel : GO

View file

@ -0,0 +1,49 @@
# Rapport d'audit : Documentation & Changelog
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 8 / 9 |
| Score | 89 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 1 |
| Ecarts MINOR | 0 |
| Ecarts INFO | 0 |
---
## Ecarts constates
### [MAJ] Changelog 0.3.1 incomplet
- **Localisation** : `CHANGELOG.md`, section `[0.3.1]`
- **Constat** : Plusieurs modifications significatives manquent dans le changelog :
- `feat: make document max size configurable via MAX_FILE_SIZE_MB env var` (nouvelle feature operateur)
- `fix: forward RATE_LIMIT_RPM and MAX_FILE_SIZE_MB to backend container` (config deployment)
- `feat: add Karate UI e2e tests with data-e2e selectors` (nouvelle infra de test)
- **Regle violee** : 11.1.2 — Toutes les modifications significatives sont listees
- **Remediation** : Ajouter les entrees manquantes user/operator-facing avant le tag release.
---
## Points positifs
- Section `[Unreleased]` correctement renommee en `[0.3.1] - 2026-04-09`
- Pas de breaking changes (coherent avec un patch release)
- Format Keep a Changelog respecte
- `frontend/package.json` contient la bonne version `"0.3.1"`
- Version suit le Semantic Versioning
- Zero TODO/FIXME/HACK/XXX dans le code source (backend et frontend)
- Zero `console.log` de debug dans le frontend (seuls `console.warn` et `console.error` legitimes)
- Zero `print()` de debug dans le backend
---
## Verdict partiel : GO

View file

@ -0,0 +1,63 @@
# Rapport d'audit : Performance & Ressources
**Release** : 0.3.1
**Date** : 2026-04-10
**Auditeur** : claude-code
---
## Score de compliance
| Metrique | Valeur |
|----------|--------|
| Items conformes | 10 / 13 |
| Score | 86 / 100 |
| Ecarts CRITICAL | 0 |
| Ecarts MAJOR | 0 |
| Ecarts MINOR | 3 |
| Ecarts INFO | 0 |
---
## Ecarts constates
### [MIN] Pas de mecanisme d'annulation/debounce sur les requetes API frontend
- **Localisation** : `frontend/src/shared/api/http.ts`, `frontend/src/features/analysis/store.ts`
- **Constat** : `apiFetch` utilise `fetch()` brut sans support `AbortController`. Les requetes de polling peuvent se chevaucher.
- **Regle violee** : 12.2.3 — Les requetes API ont un mecanisme d'annulation ou de debounce
- **Remediation** : Ajouter le support `AbortController` dans `apiFetch`.
### [MIN] Logo de 879 KB non optimise
- **Localisation** : `frontend/src/assets/logo.png`
- **Constat** : Le logo fait 879 KB, excessif pour une image de logo (devrait etre < 50 KB).
- **Regle violee** : 12.2.5 — Les assets lourds sont optimises
- **Remediation** : Convertir en SVG ou WebP, ou compresser significativement.
### [MIN] Nginx sans configuration de cache pour les fichiers statiques
- **Localisation** : `nginx.conf`, `frontend/nginx.conf`
- **Constat** : Aucune directive `expires`, `Cache-Control` ou `add_header Cache-Control` pour les assets statiques. Vite produit des noms hashes qui sont safe a cacher agressivement.
- **Regle violee** : 12.3.1 — Nginx a une configuration de cache pour les fichiers statiques
- **Remediation** : Ajouter `location ~* \.(js|css|png|svg|ico|woff2?)$ { expires 1y; add_header Cache-Control "public, immutable"; }`
---
## Points positifs
- Zero requete N+1 : queries optimisees avec JOIN, LIMIT/OFFSET
- Fichiers uploades correctement geres (persistants, nettoyes a la suppression avec protection path-traversal)
- `MAX_CONCURRENT_ANALYSES` configure et respecte via semaphore asyncio
- Conversion Docling correctement deplacee hors event loop via `asyncio.to_thread()`
- Upload en streaming (chunks de 64 KB)
- Watchers Vue automatiquement nettoyes par le lifecycle des composants
- Event listeners supprimes dans `onBeforeUnmount` (mousemove, mouseup, ResizeObserver)
- Polling avec `stopPolling()` qui clear interval et timeout
- `computed` utilises correctement plutot que des fonctions dans les templates
- Reponses API de taille raisonnable (`has_document_json: bool` au lieu du blob complet)
- Health check leger (`SELECT 1`)
---
## Verdict partiel : GO

View file

@ -0,0 +1,80 @@
# Synthese d'audit — Release 0.3.1
**Date** : 2026-04-10
**Branche** : release/0.3.1
**Derniere mise a jour** : 2026-04-10 (re-audit post remediations PR #131, #133, #135, #139, #144)
---
## Tableau de bord
| # | Audit | Score initial | Score actuel | CRIT | MAJ | MIN | INFO | Verdict |
|---|-------|--------------|--------------|------|-----|-----|------|---------|
| 01 | Clean Architecture | 75 | **100** | 0 | 0 | 0 | 0 | **GO** |
| 02 | DDD | 81 | **100** | 0 | 0 | 0 | 0 | **GO** |
| 03 | Clean Code | 56 | **93** | 0 | 0 | 2 | 0 | **GO** |
| 04 | KISS | 100 | 100 | 0 | 0 | 0 | 0 | GO |
| 05 | DRY | 83 | 83 | 0 | 1 | 0 | 0 | GO |
| 06 | SOLID | 100 | 100 | 0 | 0 | 0 | 0 | GO |
| 07 | Decouplage | 76 | **100** | 0 | 0 | 0 | 0 | **GO** |
| 08 | Securite | 97 | 97 | 0 | 0 | 1 | 1 | GO |
| 09 | Tests | 100 | 100 | 0 | 0 | 0 | 3 | GO |
| 10 | CI / Build | 90 | 90 | 0 | 0 | 2 | 0 | GO |
| 11 | Documentation | 89 | 89 | 0 | 1 | 0 | 0 | GO |
| 12 | Performance | 86 | 86 | 0 | 0 | 3 | 0 | GO |
**Score global** : 95 / 100 (moyenne ponderee)
**Ecarts CRITICAL totaux** : 0 (etaient 5)
**Ecarts MAJOR totaux** : 2 (etaient 12)
---
## PRs de remediation mergees
| PR | Branche | Sujet | Ecarts corriges |
|----|---------|-------|-----------------|
| #131 | fix/clean-architecture-audit (base) | Clean Architecture | C1, C2, C3, M1, M2, MIN-1 |
| #133 | fix/clean-architecture-audit | Clean Architecture | (complement PR #131) |
| #135 | fix/ddd-audit | DDD | C4, M3, M4 |
| #139 | fix/clean-code-audit | Clean Code | M5, M6, M7 |
| #144 | fix/decoupling-audit | Decouplage | C5, M9, M10, M11, MIN-7 |
---
## Ecarts residuels
### MAJOR restants
1. **[05]** Magic numbers 612.0/792.0 dupliques — `infra/serve_converter.py:195,196,223,224`
2. **[11]** Changelog 0.3.1 incomplet — `CHANGELOG.md`
### MINOR restants (non bloquants)
1. **[03]** Fonctions depassant 30 lignes — `infra/local_converter.py`, `infra/local_chunker.py` (pipeline Docling)
2. **[03]** Fichiers source depassant 300 lignes — `StudioPage.vue` (~1200 lignes), `ResultTabs.vue` (~690 lignes)
3. **[08]** Securite — ecart MINOR residuel
4. **[09]** Tests — 3 ecarts INFO
5. **[10]** CI / Build — 2 ecarts MINOR
6. **[12]** Performance — 3 ecarts MINOR
---
## Verdict final : GO
**0 ecart CRITICAL** — tous les bloqueurs de release resolus.
**Score global 95/100** — toutes les categorues au-dessus du seuil GO.
**Points forts du projet :**
- Clean Architecture complete (100/100) : injection de dependances, ports/adapters, domain pur
- DDD exemplaire (100/100) : invariants proteges, value objects immutables, bounded contexts
- Architecture SOLID exemplaire (100/100)
- Simplicite KISS (100/100), aucune sur-ingenierie
- Suite de tests exhaustive (100/100) couvrant tous les endpoints, services et composants
- Decouplage frontend complet (100/100) : features isolees, pont reactif `appConfig`
- Securite solide (97/100), aucune vulnerabilite detectee
- CI/Build robuste (90/100) avec pipeline multi-phase et smoke tests
**Ecarts MAJOR residuels a planifier (prochain cycle) :**
- Extraire les magic numbers de `serve_converter.py` (S)
- Completer le changelog 0.3.1 (S)

View file

@ -66,7 +66,7 @@ git checkout main && git pull upstream main
git checkout -b feature/my-change # or fix/my-fix
```
Follow the [branching strategy](../../CONTRIBUTING.md#branching-strategy).
Follow the [branching strategy](https://github.com/scub-france/Docling-Studio/blob/main/CONTRIBUTING.md#branching-strategy).
## Step 6 — Code
@ -102,7 +102,7 @@ git push origin feature/my-change
## Step 9 — Open a PR
- Target: `main` (or `release/*` for pre-release fixes)
- Fill in the [PR template](../../.github/PULL_REQUEST_TEMPLATE.md)
- Fill in the [PR template](https://github.com/scub-france/Docling-Studio/blob/main/.github/PULL_REQUEST_TEMPLATE.md)
- Add a line in `CHANGELOG.md` under `[Unreleased]`
- Wait for CI to pass, then request a review
@ -117,4 +117,4 @@ git push origin feature/my-change
- Open a [Discussion](https://github.com/scub-france/Docling-Studio/discussions) on GitHub
- Check existing issues for similar questions
- Read the [CONTRIBUTING guide](../../CONTRIBUTING.md) for detailed rules
- Read the [CONTRIBUTING guide](https://github.com/scub-france/Docling-Studio/blob/main/CONTRIBUTING.md) for detailed rules

View file

@ -30,7 +30,7 @@ Use this checklist when reviewing a Pull Request. Not every item applies to ever
- [ ] New behavior has corresponding tests
- [ ] Tests are deterministic (no `sleep`, no random, no network)
- [ ] Test names describe the scenario, not the implementation
- [ ] E2E tests use `data-e2e` attributes, not CSS classes (see [e2e/CONVENTIONS.md](../../e2e/CONVENTIONS.md))
- [ ] E2E tests use `data-e2e` attributes, not CSS classes (see [e2e/CONVENTIONS.md](https://github.com/scub-france/Docling-Studio/blob/main/e2e/CONVENTIONS.md))
## Code Quality

View file

@ -1,6 +1,6 @@
# Security Vulnerability Response
Process for handling reported security vulnerabilities. See also [SECURITY.md](../../SECURITY.md) for the public-facing policy.
Process for handling reported security vulnerabilities. See also [SECURITY.md](https://github.com/scub-france/Docling-Studio/blob/main/SECURITY.md) for the public-facing policy.
## Response Timeline

View file

@ -35,6 +35,47 @@ nav:
- Architecture: architecture.md
- Bbox Pipeline: bbox-pipeline.md
- Contributing: contributing.md
- Processes: PROCESSES.md
- Development:
- Coding Standards: architecture/coding-standards.md
- Commit Conventions: git-workflow/commit-conventions.md
- Code Review Checklist: git-workflow/code-review-checklist.md
- Merge Policy: git-workflow/merge-policy.md
- ADR Guide: architecture/adr-guide.md
- ADR Template: architecture/adr-template.md
- Release:
- Deployment Checklist: release/deployment-checklist.md
- Rollback Playbook: release/rollback-playbook.md
- Operations:
- Incident Response: operations/incident-response.md
- Security Response: operations/security-response.md
- Monitoring Checklist: operations/monitoring-checklist.md
- Community:
- Onboarding Guide: community/onboarding-guide.md
- Issue Triage: community/issue-triage-process.md
- Roadmap Template: community/roadmap-template.md
- Audit:
- Audit Master: audit/master.md
- Audits:
- Clean Architecture: audit/audits/01-clean-architecture.md
- DDD: audit/audits/02-ddd.md
- Clean Code: audit/audits/03-clean-code.md
- KISS: audit/audits/04-kiss.md
- DRY: audit/audits/05-dry.md
- SOLID: audit/audits/06-solid.md
- Decoupling: audit/audits/07-decoupling.md
- Security: audit/audits/08-security.md
- Tests: audit/audits/09-tests.md
- CI & Build: audit/audits/10-ci-build.md
- Documentation: audit/audits/11-documentation.md
- Performance: audit/audits/12-performance.md
validation:
nav:
omitted_files: info
absolute_links: info
links:
absolute_links: info
markdown_extensions:
- admonition