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.localsur 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_SECRETdoit être ajouté au vault Ansible (group_vars/production.yml) pour être injecté dans.env.localvia le rôlesymfony.
Section BO — « Corpus (source) »
Route : /admin/config/corpus
Catégorie IA, priorité 14 (juste avant « Documentation (RAG) » → 15).
Flux d'utilisation
- Admin choisit une branche (liste issue de
git branch -rlocal — branches remote-tracking). - Admin clique ↻ Rafraîchir (optionnel) : déclenche un
git fetchviasudo -u ubuntu, puis recharge le select ref. - 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).
- Admin sélectionne le ref et soumet.
- Checkout + ré-indexation se lancent en fond (process CLI détaché via
sudo -u ubuntu). - 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_SEGMENTSdansDocsLibrary. 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
bundles/tlr-rag.md— pipeline RAG complet../03-comment-je-travaille/guides/runbook.md— runbook VPS complet
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. |