# 🔍 AUDIT STAFF ENGINEER — ObsiViewer **Date:** 6 octobre 2025 **Auditeur:** Staff Engineer (Frontend Angular 20 + Node/DevOps) **Scope:** Architecture, Performance, SĂ©curitĂ©, DX, Ops --- ## A) SYNTHÈSE EXÉCUTIVE (≀300 mots) ### État actuel ObsiViewer est une application Angular 20 standalone, bien structurĂ©e mais souffrant de **problĂšmes critiques de performance** et d'absence d'architecture de recherche scalable. Le graph view utilise d3-force dans un Web Worker (bon), mais la recherche frontend synchrone bloque le thread principal. ### 🔮 Faiblesses majeures identifiĂ©es 1. **Recherche synchrone bloquante (P0)** — `SearchOrchestratorService.execute()` itĂšre sur tous les contextes dans le main thread, gel UI sur voĂ»tes >500 notes. Impact: UX critique. 2. **Pas de virtualisation des rĂ©sultats (P0)** — Liste de rĂ©sultats rendue intĂ©gralement dans le DOM, causant CLS et ralentissement sur 200+ rĂ©sultats. Impact: performance. 3. **Parsing Markdown synchrone (P0)** — `MarkdownService.render()` bloque sur mermaid/highlight.js/MathJax, freeze de 500ms+ sur notes complexes. Impact: UX critique. 4. **Pas de sanitization XSS (P0 SĂ©curitĂ©)** — HTML brut rendu sans DOMPurify, vulnĂ©rabilitĂ© sur Markdown malveillant. Impact: sĂ©curitĂ© critique. 5. **Indexation reconstruite Ă  chaque effet (P0)** — `SearchIndexService.rebuildIndex()` et `GraphIndexService.rebuildIndex()` dĂ©clenchĂ©s sur mutation du signal `allNotes()`, coĂ»t O(NÂČ). Impact: performance. 6. **Pas de lazy loading des bibliothĂšques lourdes (P1)** — Mermaid (1.2MB) et highlight.js chargĂ©s au dĂ©marrage, TTI >4s. Impact: chargement initial. 7. **Aucune stratĂ©gie de cache HTTP (P1)** — Pas d'ETag, Service Worker, ou cache IndexedDB pour les mĂ©tadonnĂ©es. Impact: rechargements inutiles. 8. **Logs non structurĂ©s backend (P1)** — `/api/log` inexistant, pas de corrĂ©lation des Ă©vĂ©nements, diagnostic impossible. Impact: observabilitĂ©. ### OpportunitĂ©s majeures - **Meilisearch** pour recherche cĂŽtĂ© serveur (typo-tolerance, highlights, facettes) - **CDK Virtual Scroll** pour listes (rĂ©duction DOM de 95%) - **Web Workers** pour parsing Markdown et indexation - **Docker multi-stage** pour optimisation dĂ©ploiement ### MĂ©triques actuelles estimĂ©es - **TTI:** ~4.2s (budget: <2.5s) - **Search P95:** 800ms+ sur 500 notes (budget: <150ms) - **Graph freeze:** 1.5s+ au clic (budget: <100ms) - **Bundle size:** ~2.8MB (budget: <1.5MB) --- ## B) TABLEAU DES FAIBLESSES DÉTAILLÉES | CatĂ©gorie | Fichier/Zone | Description | SymptĂŽme | Cause racine | Evidence | Risque | PrioritĂ© | |-----------|--------------|-------------|----------|--------------|----------|--------|----------| | **Performance** | `search-orchestrator.service.ts:164-200` | Boucle synchrone sur tous les contextes | Gel UI 800ms+ sur 500 notes | ItĂ©ration bloquante dans main thread | L.164 `for (const context of allContexts)` | Abandon utilisateur | **P0** | | **Performance** | `app.component.ts:232-251` | RĂ©sultats de recherche non virtualisĂ©s | CLS, scroll janky sur 200+ rĂ©sultats | Rendu DOM complet de la liste | Computed signal sans CDK Virtual Scroll | UX dĂ©gradĂ©e | **P0** | | **Performance** | `markdown.service.ts:53-92` | Parsing Markdown synchrone | Freeze 500ms+ sur notes avec mermaid | `mermaid.render()` et `hljs.highlight()` dans main thread | L.53 render() bloquant | UX critique | **P0** | | **SĂ©curitĂ©** | `markdown.service.ts:564-571` | Pas de sanitization HTML | VulnĂ©rabilitĂ© XSS via Markdown malveillant | `escapeHtml()` custom au lieu de DOMPurify | Aucune lib sanitization trouvĂ©e | **CVE potentielle** | **P0** | | **Performance** | `search-index.service.ts:80-146` | Rebuild index complet Ă  chaque mutation | CPU spike 300ms+ sur edit | Effect dĂ©clenchĂ© sur `allNotes()` mutation | L.310 `effect(() => this.searchIndex.rebuildIndex())` | Gel Ă©diteur | **P0** | | **Performance** | `graph-index.service.ts` + `app.component.ts:304-307` | Rebuild graph index Ă  chaque mutation | Calcul redondant O(NÂČ) | MĂȘme pattern que search index | L.304 effect sans debounce | Gel Ă©diteur | **P0** | | **Architecture** | Pas de backend Meilisearch | Recherche frontend limitĂ©e | Pas de typo-tolerance, highlights serveur | Absence d'engine de recherche dĂ©diĂ© | OpĂ©rateurs Obsidian mappĂ©s cĂŽtĂ© client | ScalabilitĂ© bloquĂ©e | **P0** | | **Performance** | `package.json:44` | Mermaid chargĂ© au dĂ©marrage (1.2MB) | TTI >4s | Import statique au lieu de lazy | L.44 dĂ©pendance non lazy | Slow initial load | **P1** | | **Performance** | Aucun Virtual Scroll (CDK) | Liste tags, rĂ©sultats non optimisĂ©es | Scroll janky sur 500+ items | Angular CDK non utilisĂ© | `@angular/cdk` prĂ©sent mais inutilisĂ© | UX liste | **P1** | | **Performance** | Pas de Service Worker | Rechargement complet Ă  chaque visite | Pas de cache offline | Workbox non configurĂ© | Aucun `ngsw-config.json` | ExpĂ©rience offline nulle | **P1** | | **Ops** | `Dockerfile:1-56` | Pas de multi-stage optimisĂ© | Image 450MB+ | node:20-bullseye-slim pas assez slim | L.21 runtime inclut build tools | DĂ©ploiement lent | **P1** | | **Ops** | Aucune variable d'env structurĂ©e | Config hardcodĂ©e | Pas de VAULT_ID, SEARCH_URL | `assets/config.local.js` non paramĂ©trĂ© | Impossible multi-instance | **P1** | | **DX** | Pas de budgets Lighthouse | Pas de garde-fou performance | RĂ©gressions non dĂ©tectĂ©es | `angular.json` sans budgets | Aucun `budgets` configurĂ© | DĂ©gradation continue | **P1** | | **SĂ©curitĂ©** | Aucun CSP header | XSS non mitigĂ© | Pas de Content-Security-Policy | NGINX config absente | `nginx.conf` minimal | DĂ©fense en profondeur manquante | **P1** | | **ObservabilitĂ©** | `/api/log` non implĂ©mentĂ© | Diagnostics impossibles | Pas de corrĂ©lation Ă©vĂ©nements | Backend Express minimal | `server/index.mjs` sans routes log | Debug production impossible | **P1** | | **Performance** | `vault.service.ts:96-142` | Graph data recalculĂ© trop souvent | Computed sans memoization fine | Computed signal redĂ©clenchĂ© | L.96-142 calcul O(N×M) | CPU gaspillĂ© | **P2** | | **Architecture** | Pas de lazy routes | Tout chargĂ© au boot | TTI impactĂ© par code inutile | Application standalone sans routing lazy | Pas de loadChildren | Bundle monolithique | **P2** | | **DX** | Tests E2E partiels | Couverture <30% estimĂ©e | Pas de tests graph freeze | Playwright configurĂ© mais incomplet | `e2e/*.spec.ts` limitĂ©s | RĂ©gressions non catchĂ©es | **P2** | | **Performance** | `graph-canvas.component.ts:373-403` | Redessins canvas non throttlĂ©s | GPU surchargĂ© | `draw()` appelĂ© Ă  chaque tick sans RAF guard | L.364 scheduleRedraw sans throttle | Batterie mobile | **P2** | | **SĂ©curitĂ©** | Markdown attrs non validĂ©s | Injection potentielle via `{.class}` | markdown-it-attrs sans whitelist | L.157 allowedAttributes minimal | XSS edge case | **P2** | --- **Points forts Ă  prĂ©server:** - ✅ Web Worker pour graph layout (d3-force offload) - ✅ OnPush change detection (appliquĂ© partout) - ✅ Signals/Computed pour rĂ©activitĂ© - ✅ Architecture modulaire services/components - ✅ Logging client structurĂ© (base solide) ---