02-ce-que-je-construis/specs/corpus-refresh.md

Corpus refresh — synchronisation telaria-doc → RAG

Contexte

Le RAG de telaria.dev indexe docs/ : un clone git de telaria-doc hébergé sur le VPS (/var/www/telaria/docs). Sans mécanisme de refresh, ce clone devient stale dès qu'un nouveau commit est poussé sur telaria-doc.

Architecture

Deux mécanismes complémentaires :

Mécanisme Déclencheur Ref ciblé
Webhook GitHub Nouveau tag poussé sur telaria-doc/master Le tag en question
BO (section Corpus) Action manuelle admin Branche + ref au choix

Les deux passent par le mĂŞme pipeline :

Webhook / BO → BackgroundCorpusCheckoutLauncher
    → CLI détaché : app:docs:checkout --ref=<ref>
        → CorpusManager::checkout(ref)
            → git fetch origin --tags --prune
            → git checkout <ref>
            → git pull --ff-only (si branche, pas si tag/SHA détaché)
        → IngestionService::ingest() (drop + rebuild full)
        → AppSettings: RUNNING=false, LAST_AT=now, CURRENT_REF=ref

Webhook GitHub

Endpoint : POST https://telaria.dev/api/webhook/github/docs

Sécurité : HMAC-SHA256 du corps de la requête, validé via X-Hub-Signature-256.

  • Secret : variable d'environnement GITHUB_WEBHOOK_SECRET (.env.local sur le serveur).
  • Si secret vide ou signature invalide → 401.

Filtre : seuls les événements create avec ref_type: tag sont traités. Push de branches, PRs, etc. → réponse 200 "Ignoré".

Comportement : si un checkout est déjà en cours (docs.checkout_running=true), le webhook répond 202 sans relancer.

Configuration webhook GitHub (sur telaria-doc) :

Champ Valeur
URL https://telaria.dev/api/webhook/github/docs
Content-Type application/json
Events Branch or tag creation uniquement
Secret valeur de GITHUB_WEBHOOK_SECRET

Note : GITHUB_WEBHOOK_SECRET doit être ajouté au vault Ansible (group_vars/production.yml) pour être injecté dans .env.local via le rôle symfony.

Section BO — « Corpus (source) »

Route : /admin/config/corpus
Catégorie IA, priorité 14 (juste avant « Documentation (RAG) » → 15).

Flux d'utilisation

  1. Admin choisit une branche (liste issue de git branch -r local — branches remote-tracking).
  2. Admin clique ↻ Rafraîchir (optionnel) : déclenche un git fetch via sudo -u ubuntu, puis recharge le select ref.
  3. Le select ref se peuple via AJAX (GET /admin/corpus/refs?branch=<b>) depuis les refs locales :
    • Tags fusionnĂ©s dans la branche (du plus rĂ©cent, en gras dans le select).
    • 10 derniers commits (SHA court — date — message).
  4. Admin sélectionne le ref et soumet.
  5. Checkout + ré-indexation se lancent en fond (process CLI détaché via sudo -u ubuntu).
  6. La section affiche le verrou « en cours » + auto-refresh (via data-config-reindex-running).

Endpoints AJAX

Méthode URL Rôle
GET /admin/corpus/refs?branch=<b> Refs locales (tags + commits, pas de fetch réseau)
POST /admin/corpus/fetch Déclenche git fetch distant via sudo-ubuntu

Infrastructure VPS

Ségrégation d'identité

www-data (FPM) n'a aucune clé SSH et aucune identité externe. C'est ubuntu qui détient la clé SSH GitHub. La communication entre les deux passe par des règles sudoers ultra-scoped.

git safe.directory

Sans cette config, FPM reçoit fatal: detected dubious ownership en lisant un dépôt appartenant à ubuntu.

# tlr-ansible roles/system/tasks/main.yml
- name: Autoriser git sur /var/www (safe.directory système)
  community.general.git_config:
    name: safe.directory
    value: /var/www/telaria/docs
    scope: system

Wrapper /usr/local/bin/telaria-docs-checkout

Les noms de commandes Symfony contiennent des : — caractère réservé en syntaxe sudoers. Le wrapper contourne cette limitation.

#!/bin/bash
exec /usr/bin/php /var/www/telaria/bin/console app:docs:checkout "$@"

Règle sudoers scoped

www-data ALL=(ubuntu) NOPASSWD: /usr/bin/git -C /var/www/telaria/docs fetch origin --tags --prune
www-data ALL=(ubuntu) NOPASSWD: /usr/local/bin/telaria-docs-checkout *

Ces deux règles couvrent exactement : le bouton ↻ Rafraîchir (fetch) et le checkout en fond. Rien d'autre.

Composants

tlr-codexia

Fichier RĂ´le
Docs/CorpusManager Opérations git : fetchRemote() (sudo), checkout(), localBranches(), refsForBranch(), status()
Docs/DocsLibrary Accès lecture aux fichiers .md du clone — mode default-allow (exclusions permanentes uniquement)
Docs/CorpusCheckoutLauncherInterface Contrat du lanceur (testable via stub)
Docs/BackgroundCorpusCheckoutLauncher Implémentation : setsid nohup sudo -u ubuntu /usr/local/bin/telaria-docs-checkout --ref=…
Command/CorpusCheckoutCommand CLI app:docs:checkout --ref=<ref> — git checkout + RAG rebuild

AppSettings keys :

Clé Type Rôle
docs.checkout_running bool verrou anti-chevauchement
docs.last_checkout_at datetime ISO horodatage dernier checkout
docs.current_ref string ref actuellement indexé

telaria-app

Fichier RĂ´le
Admin/Config/Section/CorpusSection Section BO — affichage état, form, dispatch launcher
Controller/Admin/CorpusController Endpoints AJAX refs + fetch
Controller/API/GithubWebhookController Endpoint webhook /api/webhook/github/docs
templates/admin/config/sections/_corpus.html.twig UI : sélecteurs + bouton ↻ + JS inline

DocsLibrary — mode default-allow

DocsLibrary (et le RAG via excluded_paths) opèrent en default-allow : tout fichier .md est visible sauf exclusions permanentes codées dans le bundle :

Exclusion Raison
inputs/ Données personnelles (CV, sources)
scripts/ Hooks git — pas de la documentation
legacy/ Archivé, hors corpus courant
SCRATCH.md Brouillon non publié
Dotfiles/dotdirs Méta-repo (.git, .claude, etc.)

Pas d'allowlist Ă  maintenir dans services.yaml. Si un dossier doit ĂŞtre exclu, ajouter son segment Ă  ALWAYS_EXCLUDED_SEGMENTS dans DocsLibrary. Si un dossier doit ĂŞtre visible : il l'est d'office, sans intervention.

Opérations

Provisionnement initial du clone docs/

Si docs/ n'existe pas encore sur le VPS :

cd /var/www/telaria
git clone git@github.com:<owner>/telaria-doc.git docs
cd docs && git checkout master

Le webhook s'occupera ensuite des mises Ă  jour automatiques.

Vérifier l'état courant

# Via BO : /admin/config/corpus (carte "État courant")
# Via CLI :
ssh -p 9501 ubuntu@telaria.dev "cd /var/www/telaria/docs && git log --oneline -3 && git describe --tags"

Forcer un refresh manuel en SSH

ssh -p 9501 ubuntu@telaria.dev \
  "cd /var/www/telaria && php bin/console app:docs:checkout --ref=master --env=prod"

Logs checkout

tail -f /var/www/telaria/var/log/corpus-checkout.log

Workflow de release recommandé

1. Pousser les commits sur telaria-doc/develop
2. Merger develop → master
3. Tagger : git tag 0.9.0 && git push --tags
→ Webhook déclenche automatiquement checkout 0.9.0 + ré-indexation
→ telaria.dev reflète la doc de release en quelques minutes

Voir aussi


Implémentation

Aspect Localisation
Bundle principal tlr-codexia (domaine Docs/) + telaria-app
Composants tlr-codexia Docs/CorpusManager, Docs/DocsLibrary, Docs/BackgroundCorpusCheckoutLauncher
Commandes CLI Command/CorpusCheckoutCommand (app:docs:checkout) dans tlr-codexia
Controllers telaria-app Controller/Admin/CorpusController, Controller/API/GithubWebhookController
Config Variable d'env GITHUB_WEBHOOK_SECRET sur VPS ; sudoers /usr/local/bin/telaria-docs-checkout
Templates templates/admin/config/sections/_corpus.html.twig dans telaria-app
Infrastructure Clone docs/ dans /var/www/telaria/docs ; wrapper /usr/local/bin/telaria-docs-checkout

Historique des décisions

Version Date Décision
1.0 2026-06-14 Version initiale — première formalisation du versioning des specs. Mécanisme webhook + BO livré en prod.
— 2026-06-14 DocsLibrary passe en mode default-allow : tout fichier .md est visible sauf exclusions permanentes codées dans le bundle. Fin de l'allowlist app.docs.published_paths.

Assistant documentaire

Posez une question sur la documentation. Les réponses citent leurs sources — un clic ouvre le document à gauche.

Loading…
Loading the web debug toolbar…
Attempt #