reference/telaria-app-architecture.md

telaria-app — architecture de l'application assemblĂ©e

Ce que c'est

telaria-app est une application web Symfony 8 / PHP ≄ 8.4 conçue comme un assembleur mince. Elle ne porte pas l'essentiel de la logique mĂ©tier : celle-ci vit dans quatre bundles maison qu'elle wire et surcharge. L'application apporte, en propre : la couche utilisateur/authentification, la surface web (contrĂŽleurs, routes, templates), l'API, et quelques extensions applicatives (SEO, config chatbot, validation IA de la veille, anti-spam IA du contact).

Elle sert une vitrine web multi-sites, deux viewers de documentation, des assistants conversationnels RAG, un espace lecteur connecté, un formulaire de contact protégé et un back-office /admin de production doc-IA.

FrontiĂšres de composition

L'application se compose de quatre bundles maison plus son propre cƓur applicatif. Chaque bundle est une dĂ©pendance Composer (VCS) enregistrĂ©e pour tous les environnements.

Domaine Fourni par RĂŽle de telaria-app
CMS, multisite, contact, i18n, markdown, settings, hub de config bundle CMS/socle ContrĂŽleurs de surface, companion SEO, choix des routes vitrine
Produit doc-IA : veille, chat, docs, metrics bundle produit doc-IA ContrĂŽleurs back-office, validation IA, config chatbot
CƓur RAG : indexation, embeddings, chunking, retrieval, vector store bundle RAG Configuration + section back-office
Serveur MCP : tenants, clients, outils, audit, rate limit bundle MCP Configuration + back-office clients/audit + seed CLI
User, auth, 2FA, reset, token API telaria-app CƓur applicatif du repo

Principe : les bundles rĂ©fĂ©rencent l'utilisateur par interface ; l'application fournit l'implĂ©mentation concrĂšte via la rĂ©solution d'entitĂ©s cibles Doctrine (CmsUserInterface et VeilleReaderInterface → App\Entity\User). L'application Ă©tend les donnĂ©es des bundles sans modifier leurs tables, via des entitĂ©s companion en relation OneToOne (SEO sur le contenu CMS, verdict de validation sur l'item de veille, rĂ©glages de prompt sur le chat).

Contrats de wiring (config des bundles)

  • Vitrine multisite : une liste blanche vitrine_allowed_routes dĂ©finit les routes servies sur un site non primaire ; tout le reste renvoie 404 (via un subscriber du bundle). Les noms de routes appartiennent Ă  l'application, d'oĂč un couplage explicite app ↔ bundle dĂ©clarĂ© cĂŽtĂ© config.
  • RAG : la racine indexĂ©e est le dossier docs/ (prĂ©vu comme sous-module Git). Politique observĂ©e default-allow (indexe tout sauf une liste d'exclusions) ; embeddings dĂ©lĂ©guĂ©s Ă  un microservice externe (URL via variable d'environnement) ; paramĂštres de chunking et de retrieval fixĂ©s en config ; store = base + extension vectorielle (chemins via variables d'environnement).
  • MCP : version de protocole et quota par (tenant, outil) fixĂ©s en config ; le quota est branchĂ© sur un rate limiter Symfony dĂ©diĂ© injectĂ© dans la passerelle du bundle.
  • Routes importĂ©es : les bundles MCP et CMS/socle exposent leurs routes via import. Les contrĂŽleurs de l'application sont chargĂ©s en double : une variante localisĂ©e prĂ©fixĂ©e /{_locale} (prĂ©fixe de nom localized_) et une variante par dĂ©faut ; l'API est exclue du prĂ©fixe de locale.

Architecture de sécurité

Entité utilisateur

App\Entity\User est l'entité applicative centrale. Champs de contrat : email (identifiant unique de connexion), password (hashé), roles (ROLE_USER toujours garanti), isVerified, apiToken (nullable, stocké hashé SHA-512), et les champs 2FA (is2faEnabled opt-in, authCode, totpSecret, trustedVersion).

Elle implémente les contrats Symfony (UserInterface, PasswordAuthenticatedUserInterface, TwoFactorInterface, TrustedDeviceInterface) et les contrats des bundles (CmsUserInterface, VeilleReaderInterface).

Firewalls et contrĂŽle d'accĂšs

  • api (^/api/) : stateless, provider par apiToken, authenticator custom dĂ©clenchĂ© par le header X-Auth-Token.
  • main : reste du site, provider par email, form_login avec CSRF + 2FA + logout.
  • ContrĂŽle d'accĂšs : ^/admin → ROLE_ADMIN ; ^/api → ROLE_USER. HiĂ©rarchie : ROLE_ADMIN ⊃ ROLE_USER.
  • Redirection post-login selon le rĂŽle (admin → dashboard, lecteur → espace lecteur).

Mécanismes transverses

  • Auth API : token prĂ©sentĂ© hashĂ© en SHA-512 puis comparĂ© au token stockĂ© ; rate-limitĂ© par IP ; Ă©chec → 401 JSON.
  • 2FA email (scheb/2fa) : provider email actif globalement mais opt-in par utilisateur ; code Ă  6 chiffres ; appareils de confiance via cookie dĂ©diĂ©.
  • Basic Auth global (« public dans le privĂ© ») : un listener sur kernel.request protĂšge tout le site derriĂšre un Basic Auth HTTP quand un drapeau d'environnement est actif, sinon reste inerte — ce qui rend les pages publiques rĂ©ellement privĂ©es en environnement de prĂ©production.
  • Reset password / vĂ©rification email : via bundles SymfonyCasts dĂ©diĂ©s.

Surface web et endpoints (contrats de route)

Chaque route non-API possÚde une variante localisée localized_<nom> préfixée /{_locale}.

Public

Path Nom Méthodes
/ front.index GET
/veille front.veille GET
/legal, /accessibility front.legal, front.accessibility GET
/contact front.contact GET, POST
/captcha/challenge front.captcha_challenge GET
/{slug} cms.page GET (priorité -10)
/docs, /docs/{slug} docs.index, docs.show GET
/docs/chat/ask, /docs/chat/reset docs.chat.* POST
/docs-files, /docs-files/{path} docs-files.* GET
/assistant + /ask /settings /reset assistant.* GET / POST
/robots.txt, /sitemap.xml seo.robots, seo.sitemap GET
/login, /logout security.* GET, POST

Lecteur (ROLE_USER)

Path Nom Méthodes
/lecteur reader.index GET
/lecteur/billet/{id} reader.show GET
/lecteur/billet/{id}/lu reader.toggle_read POST
/lecteur/tout-lu reader.mark_all_read POST

Admin (ROLE_ADMIN, préfixe /admin)

Familles de noms de routes : admin.dashboard.*, admin.cms.* (pages, sites, images, media), admin.veille.*, admin.corpus.*, admin.rag.*, admin.mcp.*, admin.metrics*, admin.chatbot.config, admin.chat.params, admin.users.*, admin.profile.*.

API (firewall api, stateless, préfixe /api)

Path Nom Méthodes Auth
/api/me api.user.me GET ROLE_USER (X-Auth-Token)
/api/webhook/github/docs api.webhook.github.docs POST HMAC-SHA256 (X-Hub-Signature-256)

Contrat du webhook de rĂ©-indexation : la signature sha256=hmac_sha256(body, secret) est vĂ©rifiĂ©e en temps constant. L'endpoint ne rĂ©agit qu'Ă  un Ă©vĂ©nement de crĂ©ation de tag avec ref non vide (sinon 200 IgnorĂ©) ; si aucun checkout n'est dĂ©jĂ  en cours, il lance checkout + rĂ©-indexation en fond → 202. Signature invalide → 401 ; payload non-JSON → 400. L'exĂ©cution effective (git + reindex) est dĂ©lĂ©guĂ©e Ă  un contrat fourni par le bundle produit doc-IA ; l'application ne fait que valider la signature et dĂ©lĂ©guer.

Fonctions IA applicatives

Deux fonctions IA sont propres à l'application (au-dessus des bundles). Les deux appellent un modÚle Claude rapide de la famille Haiku via l'API Anthropic Messages, sur clé API fournie par variable d'environnement, avec parsing tolérant (jamais d'échec silencieux du pipeline).

Validation automatique de la veille

AprĂšs chaque cycle de veille (message traitĂ© par le worker Messenger), un subscriber Ă©coute l'Ă©vĂ©nement de message traitĂ© et valide les items nouvellement proposed, dans le mĂȘme process worker. Garde-fous observĂ©s :

  • DĂ©sactivĂ© si le prompt de validation n'est pas configurĂ© (clĂ© de rĂ©glage Ă©ditĂ©e en back-office).
  • Limite de 20 items par cycle (garde anti-runaway), triĂ©s par date de traitement, uniquement ceux sans validation dĂ©jĂ  persistĂ©e.
  • Le prompt systĂšme = le prompt configurĂ© par l'utilisateur ; le message utilisateur porte titre, rĂ©sumĂ© tronquĂ©, source et thĂšme.
  • Verdict attendu ACCEPT|raison, REJECT|raison ou UNCERTAIN|raison. RĂ©ponse malformĂ©e → UNCERTAIN.
  • Application : ACCEPT → item acceptĂ© (visible en vitrine et espace lecteur) ; REJECT → rejetĂ© ; UNCERTAIN → reste proposed pour revue humaine. La raison est persistĂ©e dans une entitĂ© companion. Les erreurs d'appel sont loggĂ©es mais ne font pas Ă©chouer le cycle.

FrontiÚre : le pipeline de collecte/résumé/proposition et l'entité VeilleItem (statuts proposed/accepted/rejected) viennent du bundle ; l'application ajoute le subscriber, le service d'appel, l'entité de validation et la section de config du prompt.

Anti-spam du contact

Le formulaire de contact combine plusieurs couches : rate limit, honeypot, CAPTCHA (Altcha, challenge/HMAC via variables d'environnement) et une analyse IA (ContactSpamAnalyzer) qui implémente le contrat de détection de spam du bundle.

Contrats de configuration

Toute la configuration sensible passe par variables d'environnement ; les fichiers versionnés ne contiennent que des placeholders. Contrats observés (usages, pas de valeurs) : framework (APP_ENV, APP_SECRET), base (DATABASE_URL), transport Messenger, mail (DSN, expéditeur, DKIM), CAPTCHA (secret + complexité), clé API Anthropic, secret HMAC du webhook, microservice d'embeddings et chemins du store vectoriel, drapeau + identifiants du Basic Auth global, throttle de reset, réglages du viewer docs, paramÚtres du pipeline de veille.

Rate limiters (politiques observĂ©es) : formulaire de contact (token bucket, quelques requĂȘtes par fenĂȘtre de minutes), API (token bucket, par IP), 2FA (token bucket serrĂ©), outil MCP (sliding window, par (tenant, outil), actif dans tous les environnements).

Points de contrat pour un intégrateur

  • IdentitĂ© : implĂ©menter/mapper l'utilisateur derriĂšre les interfaces des bundles ; ne jamais dupliquer, rĂ©soudre via resolve_target_entities.
  • Extension de donnĂ©es de bundle : passer par une entitĂ© companion OneToOne, jamais par modification des tables du bundle.
  • API : header X-Auth-Token (token hashĂ© SHA-512 cĂŽtĂ© stockage), firewall stateless, rĂ©ponses JSON.
  • Webhook : signature HMAC-SHA256 en en-tĂȘte, vĂ©rification en temps constant, traitement asynchrone bornĂ© par un flag anti-concurrence.
  • Multisite : toute nouvelle route destinĂ©e Ă  la vitrine doit ĂȘtre ajoutĂ©e Ă  la liste blanche, sinon 404 sur site non primaire.
  • IA : les fonctions IA sont pilotĂ©es par des prompts configurables en back-office et bornĂ©es par des garde-fous (dĂ©sactivation si non configurĂ©, plafond par cycle, dĂ©gradation en UNCERTAIN).

Fiche de référence descriptive, généralisée depuis une rétro-doc code-first. Certains éléments marqués « à confirmer par le Dev » dans la source (politique default-allow du RAG, découpage des migrations par bundle, ouverture de l'inscription publique, choix d'appels IA non centralisés) restent à valider.

Assistant documentaire

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