Vue d'ensemble

Choix structurants

Choix structurants

Dernière mise à jour : 2026-05-10

Liste rapide des décisions d'architecture qui définissent le projet. Chaque entrée pointe vers son ADR détaillé dans le chapitre Adrs.

Choix Pourquoi ADR
Hono plutôt qu'Express/Fastify SSE natif, perfs, types meilleurs, moins de middleware tiers ADR-001
SQLite + Drizzle plutôt que Postgres Self-host minimal, zéro service supplémentaire, ACID suffisant pour l'usage actuel ADR-002
Claude via SSH plutôt que API Anthropic directe Quota Pro/Team du compte personnel (vs API à crédits), accès à l'outil Read de Claude Code pour la vision PDF, no-coût marginal sur appels ADR-003
Vision inline au moment de la question, pas pendant l'ingestion Coût zéro à l'ingestion, lecture PNG ciblée 1 page max au moment opportun, latence acceptable (~30s) ADR-004
RAG Fusion v2 (pondération question×2 + blending position-aware) Préserve les exact-matches de la question brute contre la dilution HyDE, et garde le signal RRF quand le reranker est peu confiant sur du contenu technique abstrait ADR-005
Repository pattern (Phase 2) Centralisation des requêtes Drizzle dans repositories/, jamais d'accès direct depuis routes/services/cron ADR-006
Handlers MVC (Phase 4) Séparation routes (HTTP) → handlers (logique pure) → services → repos. Result discriminés pour les erreurs attendues ADR-007

Autres décisions notables (sans ADR formel)

Présentation du projet

Présentation du projet

Dernière mise à jour : 2026-05-10

But

Webapp RAG (Retrieval-Augmented Generation) self-hosted qui répond en français aux questions sur les règles de jeux de société et de TCG, en citant les sources (page exacte du livret PDF, cartes, règles d'extensions).

Public

Initialement : Thymon en solo pendant ses parties / lors de l'analyse de decks. Architecture multi-utilisateur avec auth en place (argon2 + sessions cookies HTTP-only) pour future ouverture.

État

Historique court

Date Étape clé
2026 (début) Setup Hono + Vue + Qdrant, premier RAG simple
2026 Q1 Embeddings TEI, contextual retrieval B, hierarchy LLM
2026-04 Vision inline (Claude lit PNG), HyDE, RAG Fusion v2, sticky mentions, deck import FAB, mode deckbuilding
2026-04-26 Méta-game (17Lands, MTGGoldfish, MTGTop8, Mobalytics, RiftboundStats)
2026-04-27 Lorcana intégration full premium, Phase 2 OCR roadmap préparée
2026-05-06 OCR auto Phase 1 (tesseract)
2026-05-09 Sécurité SSH renforcée (user oracle dédié, ForceCommand wrapper)

Caractéristiques clés

Schéma d'architecture

Schéma d'architecture

Dernière mise à jour : 2026-05-10

Vue containers

flowchart LR
    User[Utilisateur Web]
    NPM[Nginx Proxy Manager<br/>rules.thymon.fr]
    App[Container boardgame-referee<br/>Hono + Vue dist + SQLite + PDFs]
    Qdrant[Container Qdrant<br/>:6333]
    TEI[TEI bge-m3<br/>:8099 RTX 3060]
    Reranker[TEI Reranker bge-v2-m3<br/>:8990 RTX 3060]
    SSH[VM oracle<br/>Claude Code CLI<br/>+ Read tool sur /app/pdfs]

    User -- HTTPS --> NPM
    NPM -- HTTP :3000 --> App
    App -- HTTP :6333 --> Qdrant
    App -- HTTP :8099 --> TEI
    App -- HTTP :8990 --> Reranker
    App -- SSH ed25519 --> SSH
    App -- volume PDF + PNG --> SSH

Vue d'une question (flux RAG)

sequenceDiagram
    participant U as Frontend Vue
    participant H as Hono /api/ask/stream
    participant CLF as classify (Haiku)
    participant HYDE as HyDE (Haiku)
    participant TEI as TEI bge-m3
    participant Q as Qdrant (dense+BM25)
    participant R as Reranker
    participant SSH as Claude Code SSH

    U->>H: POST { gameId, question, cardMentions, history }
    H->>CLF: classify(question)
    par parallèle
        H->>HYDE: génère passage hypothétique
        H->>TEI: embed question brute
    end
    HYDE-->>H: passage
    H->>TEI: embed passage HyDE
    H->>Q: search hybride (dense × 2 vecteurs + BM25)
    Q-->>H: candidats RRF v2 fusionnés
    H->>R: rerank top-50
    R-->>H: top-K final + scores
    H->>SSH: prompt Opus avec chunks + cartes citées + image PNG
    SSH-->>H: stream tokens
    H-->>U: SSE phases / context / token / done
    H->>H: persist questions.answer + diagnostics

Vue d'une ingestion (flux PDF → Qdrant)

flowchart TB
    PDF[PDF uploadé]
    Extract[pdfjs-dist : extract text]
    OCR{Auto OCR<br/>nécessaire ?}
    Tess[tesseract +<br/>pdftoppm 300dpi]
    Chunk[Chunking sémantique]
    Hier[Hierarchy LLM<br/>chapter / section]
    Ctx[Contextual LLM B<br/>10 SSH parallèles]
    Embed[TEI bge-m3<br/>batch 32]
    QdrantUp[Qdrant upsert<br/>rules_slug]
    Confl{Extension ?}
    ConflDetect[Conflict detect<br/>vs jeu base]
    PNG[pdftoppm rendu<br/>page-XX.png 300dpi]

    PDF --> Extract
    Extract --> OCR
    OCR -- oui --> Tess --> Chunk
    OCR -- non --> Chunk
    Chunk --> Hier --> Ctx --> Embed --> QdrantUp
    QdrantUp --> Confl
    Confl -- oui --> ConflDetect --> PNG
    Confl -- non --> PNG

Couches backend

src/
├── routes/         ← Contrats HTTP (Hono), validation Zod, auth
├── handlers/       ← Logique métier pure (Phase 4 MVC), retourne Result discriminés
├── services/       ← Domaine : RAG, Qdrant, TEI, Claude SSH, cards, méta, OCR
└── repositories/   ← Data access (Drizzle) — SEUL endroit qui importe drizzle-orm

Règles : routes ne fait que parser+valider+déléguer. handlers ne connaît pas Hono. services ne touche pas la DB. repositories ne contient pas de logique métier.

Couches frontend

frontend/src/
├── views/          ← Pages routables (HomeView, PlayView, AdminView…)
├── components/     ← Composants par domaine (admin/, play/, deck-import/, card-zoom/, home/)
├── composables/    ← Hooks logique métier réutilisable (useAskStream, useMentionAutocomplete…)
├── stores/         ← Pinia (auth, games, session)
├── services/       ← `api.ts` (client unique vers backend)
└── lib/            ← Helpers TCG-specific (mana.ts, fab-symbols.ts, …)

Stack technique

Stack technique

Dernière mise à jour : 2026-05-10

Runtime

Composant Version Rôle
Node.js 22 (image node:22-bookworm-slim) Runtime backend
Vue 3 3.5.31 Framework frontend
Tailwind CSS 4.2.2 (@tailwindcss/vite) Utility-first CSS
Vite (via @tailwindcss/vite) Bundler frontend
Pinia 3.0.4 State management
Vue Router 5.0.4 Routing client

Backend principal

Lib Version Rôle
Hono 4.7.6 Web framework (routes + middleware + SSE streaming)
@hono/node-server 1.14.1 Adapter HTTP Node
Drizzle ORM 0.44.2 ORM SQLite type-safe
better-sqlite3 11.9.1 Driver SQLite synchrone (rapide, low-overhead)
Zod 3.24.4 Validation schémas
Argon2 0.43.0 Password hashing
ssh2 1.16.0 Client SSH (pool vers VM oracle)
pdfjs-dist 4.10.38 Extraction texte PDF
sharp 0.34.5 Resize cache images cartes
cheerio 1.2.0 HTML parsing (méta-game scraping)
nodemailer 8.0.5 SMTP optionnel
stream-chain + stream-json 3.6.1 / 1.9.1 Streaming JSON parser (Claude SSH)
tsx 4.19.4 TS executor (dev + scripts)
uuid 11.1.0 UUIDs partout

Stockage / persistance

Composant Rôle
SQLite (better-sqlite3) Users, games, questions, feedbacks
Drizzle Kit Migrations
Qdrant Vector DB (1024 dims, dense + BM25 sparse) — une collection par jeu (rules_<slug>) + collections cartes par TCG (magic-cards, lorcana-cards, etc.)
Filesystem (/app/pdfs, /app/data) PDFs uploadés, PNG rendus, caches JSON (OCR / contextual / conflicts), data sources cartes

ML / RAG

Composant Rôle
TEI (Text Embeddings Inference) Service HTTP local sur RTX 3060 — modèle bge-m3 (1024 dim dense + sparse BM25)
TEI Reranker Service HTTP local — modèle bge-reranker-v2-m3 cross-encoder
Claude Code CLI (Anthropic) Génération streamée via SSH vers VM oracle
Modèle Haiku claude-haiku-4-5-20251001 — HyDE, decompose-query, conflit detect, classify intent
Modèle Opus (par défaut) — réponses RAG, deckbuilding

TCG (sources de données)

TCG Source
MTG Scryfall bulk JSON (téléchargé) + traduction Haiku
Lorcana LorcanaJSON.org (MIT, bulk JSON FR/EN)
FAB Package npm @flesh-and-blood/cards (bundlé dans l'image Docker)
Riftbound API Riot card-gallery (live JSON)
Terraforming Mars HTML parsing local + cards.json
Ark Nova Sprite sheets découpées + cards.json

Méta-game

Source TCG
17Lands API MTG (draft analytics)
MTGGoldfish (scrape) MTG (constructed metagame)
MTGTop8 (scrape) MTG (top 8 tournois)
Mobalytics (scrape) Riftbound (tier list)
RiftboundStats (API) Riftbound (tournois)
fabtcg.com (scrape) FAB (tournois officiels LSS)
BoardGameGeek XML v2 Tous (forums Rules)

Infra

Composant Rôle
Unraid OS hôte des containers
Docker Containerisation (image multi-stage)
Gitea (gitea.thymon.fr) Git + CI Runners + registry
Nginx Proxy Manager (NPM) Reverse proxy + Let's Encrypt sur rules.thymon.fr
VM SSH oracle Exécute Claude Code CLI (compte dédié least-privilege)
RTX 3060 TEI bge-m3 + reranker (GPU)