Telaria Search
Telaria Search est le moteur de recherche interne de Codexia. Il unifie la recherche BDD et fichiers, tout en restant agnostique du moteur pour démontrer une architecture industrielle sans dépendance à un bundle tiers. Il s'appuie sur des composants open source éprouvés et s'aligne sur les principes de longévité et de simplicité maîtrisée. Sources : Philosophie, Ingénierie, Architecture.
Objectifs
- Démontrer une implémentation industrielle malgré une volumétrie réduite (vitrine de savoir-faire). Source : Philosophie.
- Garder une architecture lisible, maintenable, extensible (KISS et Clean Code). Source : Ingénierie.
- Prioriser l'open source et les standards. Source : Philosophie.
Périmètre fonctionnel
- Recherche full-text sur un sous-ensemble de tables et de champs (whitelist).
- Recherche full-text sur des fichiers textuels ou bureautiques via extraction dédiée.
- Filtrage par type de contenu, langue, statut, domaine d'expertise, date.
- Respect des règles d'accès (public / privé / rôles).
Architecture logique (moteur agnostique)
┌─────────────────────────────┐
│ Couche HTTP │
│ Controller / API Search │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Service de recherche │
│ (SearchService interne) │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Port moteur (interface) │
│ SearchEnginePort (PHP) │
└──────────────┬──────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ OpenSearch │ │ Autre moteur │
│ Adapter │ │ Adapter │
└───────────────┘ └───────────────┘
Notion de port (ports & adapters)
Un port est un contrat d'interface défini par l'application, indépendant de toute technologie externe. Les adaptateurs implémentent ce contrat pour un moteur concret. Cette séparation rend le coeur applicatif stable, testable et remplaçable sans réécriture des cas d'usage. Source : Hexagonal architecture.
Ce que cela implique :
- Le coeur applicatif dépend d'une interface, jamais d'un client spécifique.
- Le changement de moteur se limite à remplacer l'adaptateur.
- Les tests peuvent utiliser un adaptateur in-memory sans dépendance réseau.
Composants internes
SearchService: expose une API unique pour la recherche.SearchIndexer: normalise les données à indexer (BDD et fichiers).SearchEnginePort: interface PHP commune (indexer, supprimer, rechercher).OpenSearchAdapter: implémentation par défaut via le client PHP officiel. Source : Client PHP OpenSearch.IndexMappingFactory: définit le schéma de l'index (types, analyzers).SearchQueue: orchestration asynchrone via Symfony Messenger. Source : Symfony Messenger.
Mise en place du port (Symfony)
Le port est une interface PHP placée dans le coeur applicatif. L'adaptateur est un service d'infrastructure qui implémente l'interface. L'alias du conteneur Symfony relie l'interface à l'adaptateur choisi. Source : Autowiring Symfony.
Installation côté Symfony :
- Créer l'interface
SearchEnginePortdanssrc/Search/Port/. - Implémenter l'adaptateur dans
src/Search/Infrastructure/. - Déclarer un alias d'interface dans
services.yaml(autowiring). - Injecter le port dans les services applicatifs (
SearchService,SearchIndexer). Source : Autowiring Symfony.
Exemple minimal :
// src/Search/Port/SearchEnginePort.php namespace App\Search\Port; interface SearchEnginePort { public function index(array $document): void; public function delete(string $type, string $id): void; public function search(string $query, array $filters = []): array; }
# config/services.yaml services: App\Search\Port\SearchEnginePort: alias: App\Search\Infrastructure\OpenSearchAdapter
Choix moteur par défaut : OpenSearch
- Suite de recherche et d'analytics open source, communautaire. Source : About OpenSearch.
- Licence Apache 2.0, alignée avec une stratégie open source. Source : About OpenSearch.
- Client PHP officiel disponible. Source : Client PHP OpenSearch.
Configuration OpenSearch (Symfony)
Installation du client :
composer require opensearch-project/opensearch-php
Source : Client PHP OpenSearch.
Variables d'environnement recommandées :
OPENSEARCH_HOST=https://localhost:9200 OPENSEARCH_USER=admin OPENSEARCH_PASSWORD=admin OPENSEARCH_SSL_VERIFY=true
Exemple d'adaptateur (extrait) :
use OpenSearch\ClientBuilder; $client = ClientBuilder::create() ->setHosts([$_ENV['OPENSEARCH_HOST']]) ->setBasicAuthentication($_ENV['OPENSEARCH_USER'], $_ENV['OPENSEARCH_PASSWORD']) ->setSSLVerification((bool) $_ENV['OPENSEARCH_SSL_VERIFY']) ->build();
Source : Client PHP OpenSearch.
Sécurisation réseau (TLS, CA, reverse proxy)
Objectif : chiffrer les communications, valider la CA et éviter une exposition directe.
TLS côté OpenSearch (REST + transport) :
# opensearch.yml (extrait) plugins.security.ssl.http.enabled: true plugins.security.ssl.http.pemcert_filepath: certs/opensearch-http.pem plugins.security.ssl.http.pemkey_filepath: certs/opensearch-http-key.pem plugins.security.ssl.http.pemtrustedcas_filepath: certs/root-ca.pem plugins.security.ssl.transport.pemcert_filepath: certs/opensearch-transport.pem plugins.security.ssl.transport.pemkey_filepath: certs/opensearch-transport-key.pem plugins.security.ssl.transport.pemtrustedcas_filepath: certs/root-ca.pem
Source : OpenSearch TLS.
Reverse proxy Apache (optionnel) :
# Apache (reverse proxy) ProxyPass "/opensearch" "https://127.0.0.1:9200" ProxyPassReverse "/opensearch" "https://127.0.0.1:9200"
Le reverse proxy s'active avec ProxyPass / ProxyPassReverse et ne nécessite pas ProxyRequests. Source : Apache mod_proxy.
Extraction de contenu fichiers (Tika)
- Apache Tika détecte et extrait texte et métadonnées depuis un grand nombre de formats. Source : Apache Tika.
- Le mode serveur est supporté via l'option
-sdetika-app, pratique pour un service dédié. Source : Getting Started Tika.
Installation Apache Tika (Ubuntu)
- Choisir une version explicite et récupérer le jar exécutable depuis la page officielle. Source : Téléchargement Tika.
- Installer un runtime Java (exemple : OpenJDK) et placer le jar dans un répertoire dédié.
- Démarrer Tika en mode serveur :
java -jar /opt/tika/tika-app-<version>.jar -s
Source : Getting Started Tika.
Exemple de service systemd (optionnel) :
[Unit] Description=Apache Tika Server After=network.target [Service] User=tika Group=tika ExecStart=/usr/bin/java -jar /opt/tika/tika-server-<version>.jar --host=127.0.0.1 --port=9998 Restart=on-failure [Install] WantedBy=multi-user.target
Par défaut, Tika Server écoute sur localhost:9998 et le port peut être modifié via --port. Source : TikaServer.
Modèle de document indexé (schéma minimal)
Champs communs (tous les types) :
type: document, resource, file, etc.source_id: identifiant métier.title: titre court.content: texte principal indexé.language:frouen.tags: liste de tags (si applicable).visibility: public, privé, rôle.updated_at: date de mise à jour.
Flux d'indexation
1. Indexation BDD
- Doctrine émet un événement sur création ou mise à jour.
SearchIndexerconstruit le document indexable en appliquant la whitelist de champs.- Le message est envoyé à Messenger.
- Le handler appelle
SearchEnginePortpour indexer.
2. Indexation fichiers
- Upload ou ingestion de fichier.
- Envoi du fichier à Tika (serveur dédié) pour extraction du texte.
SearchIndexernormalise le document et ajoute les métadonnées.- Indexation via
SearchEnginePort.
Recherche (requêtes)
- Recherche multi-champs (titre + contenu) avec pondération.
- Filtres métiers appliqués côté moteur (type, langue, statut).
- Pagination simple et stable.
Sécurité et conformité
- Filtrage des résultats en fonction de la visibilité métier.
- Aucune exposition directe de l'endpoint OpenSearch vers le public.
- Journalisation des erreurs d'indexation et des erreurs Tika. Sources : Ingénierie, Architecture.
Accessibilité (RGAA AA)
- Formulaire de recherche avec libellé explicite et aide à la saisie.
- Résultats dans une liste structurée, focus visible et navigation clavier.
- Mise en évidence des occurrences sans dépendre uniquement de la couleur. Sources : Accessibilité, Interface utilisateur.
Observabilité et performance
- Logs structurés pour chaque opération d'indexation.
- Indexation asynchrone pour ne pas bloquer le backoffice.
- Possibilité de re-indexation complète via commande Symfony. Source : Symfony Messenger.
Évolutivité
- Ajout d'un nouveau moteur via un adapter supplémentaire (Meilisearch, Elasticsearch, Solr).
- Les appels applicatifs restent inchangés grâce au
SearchEnginePort.
Liens internes
- Architecture technique
- Principes d'ingénierie
- Philosophie du projet
- Qualité documentaire
- Accessibilité
Implémentation
| Aspect | Localisation |
|---|---|
| Statut | Conceptuel — mis en pause au profit de l'initiative IA (cf. ia-vitrine.md) |
| Bundle principal | À documenter — module src/Search/ dans telaria-app (prospectif) |
| Port moteur | src/Search/Port/SearchEnginePort.php (interface) |
| Adaptateur par défaut | src/Search/Infrastructure/OpenSearchAdapter.php |
| Services | SearchService, SearchIndexer dans telaria-app |
| Async | Symfony Messenger (SearchQueue) |
| Extraction fichiers | Apache Tika (serveur dédié, localhost:9998) |
| Config | Variables OPENSEARCH_HOST, OPENSEARCH_USER, OPENSEARCH_PASSWORD, OPENSEARCH_SSL_VERIFY |
Historique des décisions
| Version | Date | Décision |
|---|---|---|
| 1.0 | 2026-06-14 | Version initiale — première formalisation du versioning des specs. |
| — | 2026-05-28 | telaria-search mis en pause au profit de l'initiative IA (SQLite + sqlite-vec retenu pour le retrieval RAG). Spec conservée comme référence pour une future activation. |