ObsiViewer/docs/ARCHITECTURE/AUDIT_STAFF_ENGINEER_SYNTHESE.md

7.0 KiB
Raw Permalink Blame History

🔍 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)