#Sommaire
| § | Section | Nombre de fiches |
|---|---|---|
| 1 | Comment lire une fiche | — |
| 2 | Carte générale des services | — |
| 3 | Partie A — Le châssis multi-locataire | 3 |
| 4 | Partie B — Les services de la vague 1 (cœur SDD) | 8 |
| 5 | Partie C — Les services scopés de la vague 2 | 17 |
| 6 | Partie D — Le plan agentique | 11 |
| 7 | Partie E — Le plan MCP | 2 |
| 8 | Partie F — Paquets partagés et surfaces web | 7 |
| 9 | Synthèse par statut | — |
| 10 | Ce qui n'existe pas, dit explicitement | — |
Total : 48 fiches.
#1. Comment lire une fiche
#1.1 Le gabarit
Chaque fiche suit la même structure, sans exception :
| Rubrique | Contenu |
|---|---|
| Nom public | Le nom que la communication emploie, en français |
| Rôle en une phrase | Ce que le service fait, sans jargon |
| Problème résolu | La douleur concrète qu'il supprime |
| Ce que l'utilisateur peut faire | Des verbes d'action, pas des fonctionnalités abstraites |
| Surface réelle | Les points d'accès ou les écrans qui existent aujourd'hui |
| Données gérées | Les tables réelles, préfixées app_ |
| Dépendances | Ce dont le service a besoin pour fonctionner pleinement |
| Capacités IA | Appel réel à un modèle, ou absence assumée |
| Limites connues | Ce que le service ne fait pas, ou fait de façon dégradée |
| Statut | Livré / En cours / Planifié / Bloqué |
| Preuve | Le fichier ou la route qui atteste l'affirmation |
#1.2 Les statuts
| Pastille | Statut | Signification opposable |
|---|---|---|
| 🟢 | Livré | Le code existe, il est testé, et la capacité est atteignable par un utilisateur |
| 🟡 | En cours | Le code existe mais une condition d'activation manque : drapeau, déploiement, ou preuve en ligne |
| ⚪ | Planifié | La capacité est conçue, pas implémentée. Elle ne doit jamais être présentée comme disponible |
| 🔴 | Bloqué | L'implémentation existe mais une contrainte externe empêche son fonctionnement |
#1.3 Les deux styles d'enregistrement à la passerelle
La source de vérité du routage est un module unique, backend/api-gateway/src/core/registry.py. Il connaît deux styles :
| Style | Mécanisme | Qui l'emploie |
|---|---|---|
| Préfixes natifs (« flat ») | Le service est atteint à ses propres chemins /api/v1/<ressource>, proxifiés à l'identique |
Le châssis et la vague 1 |
| Montage scopé | Le service est atteint à un seul préfixe /api/v1/<slug> et la passerelle réécrit le chemin avant de proxifier |
La vague 2 |
Le montage scopé existe parce que tous les services de la vague 2 exposent des sous-ressources sous les mêmes espaces de noms partagés (/api/v1/projects/..., /spec-items, /audit, /metrics) : un enregistrement plat provoquerait des collisions.
#1.4 La convention de base de données
Une base par service, nommée ks_<slug>_<env> avec env ∈ {dev, qa, prod}. Les identifiants de connexion sont résolus dans cet ordre : variable DATABASE_URL, puis coffre de secrets au chemin secret/data/kyspectra/<env>/postgres/<slug>, puis variables d'environnement DB_*. Aucun secret n'est jamais écrit dans le dépôt.
⚠️ Piège transverse documenté. Le pilote
asyncpgattend le paramètressl=, pas lesslmode=de libpq. Une chaîne de connexion portantsslmode=fait échouer le démarrage. Ce piège s'applique à tous les services.
#2. Carte générale des services
#2.1 Répartition
| Famille | Répertoire | Nombre |
|---|---|---|
| Services backend déployables | backend/ |
31 |
| Services d'agents et cœur agentique | services/ |
9 |
| Paquets partagés Python | packages/ |
2 |
| Paquets partagés front | frontend/packages/ |
3 |
| Portails web | frontend/ |
3 |
#2.2 Ports et montages — table complète
| Service | Port | Montage passerelle | Partie |
|---|---|---|---|
api-gateway |
4100 | — (c'est la passerelle) | A |
user-service |
4101 | plat, 14 préfixes | A |
example-service |
4103 | plat, exclu de l'agrégat de santé | A |
ai-orchestrator |
4106 | plat, /api/v1/ai, /api/v1/agents |
D |
spec-service |
4107 | plat, /api/v1/projects, /spec-items, /ears, /steering |
B |
sdlc-service |
4108 | scopé /api/v1/sdlc |
C |
test-quality-service |
4109 | scopé /api/v1/test-quality |
C |
test-data-factory-service |
4110 | scopé /api/v1/test-data-factory |
C |
product-config-service |
4111 | scopé /api/v1/product-config |
C |
platform-config-service |
4112 | scopé /api/v1/platform-config |
C |
audit-compliance-service |
4113 | scopé /api/v1/audit-compliance |
C |
observability-board-service |
4114 | scopé /api/v1/observability |
C |
billing-usage-service |
4115 | scopé /api/v1/billing-usage |
C |
extension-registry-service |
4116 | scopé /api/v1/extension-registry |
C |
dependency-graph-service |
4117 | scopé /api/v1/dependency-graph |
C |
copilot-service |
4118 | plat, /api/v1/copilot |
B |
agent-runtime-service |
4119 | scopé /api/v1/agent-runtime |
C |
reverse-engineering-service |
4120 | scopé /api/v1/reverse-engineering |
C |
deploy-service |
4121 | scopé /api/v1/deploy |
C |
integration-sync-service |
4122 | scopé /api/v1/integration-sync |
C |
prompt-orchestration-service |
4123 | scopé /api/v1/prompt-orchestration |
C |
custom-fields-service |
4124 | plat, /api/v1/custom-fields |
B |
ingestion-service |
4125 | plat, /api/v1/ingestion |
B |
ml-service |
4126 | plat, /api/v1/ml |
B |
portal-experience-service |
4127 | plat, 9 préfixes | B |
collaboration-service |
4128 | plat, 5 préfixes | B |
artifact-service |
4129 | plat, 5 préfixes | B |
feedback-service |
4130 | scopé /api/v1/feedback |
C |
demo-orchestrator-service |
4132 | scopé /api/v1/demo |
C |
agent-registry-service |
4133 | non enregistré — interne uniquement | D |
agentic-core-service |
8095 | scopé /api/v1/agentic-core |
D |
mcp-gateway |
8080 | scopé /api/v1/mcp, service à la racine |
E |
memory-rag-service |
8096 | non enregistré | D |
chat-service |
8097 | non enregistré | D |
analyst-agent-service |
8100 | non enregistré | D |
writer-agent-service |
8101 | non enregistré | D |
reviewer-agent-service |
8102 | non enregistré | D |
extractor-agent-service |
8103 | non enregistré | D |
calculator-agent-service |
8105 | non enregistré | D |
advisor-agent-service |
8108 | non enregistré | D |
mcp-servers (5 serveurs) |
8200 | atteints par la passerelle MCP | E |
3. Partie A — Le châssis multi-locataire
#Fiche A1 — Passerelle d'interface api-gateway
Rôle en une phrase. Elle est la porte d'entrée unique de toute la plateforme : elle vérifie l'identité, résout le locataire, route vers le bon service et protège l'ensemble.
Problème résolu. Sans elle, chaque portail devrait connaître l'adresse de trente services, dupliquer la vérification de jeton, et réimplémenter la limitation de débit. Un seul endroit déclare une route ; un seul endroit refuse.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Rien directement : il en bénéficie à chaque appel. L'exploitant, lui, lit l'état de santé agrégé et la table de routage résolue |
| Surface réelle | GET /health, GET /health/aggregate, GET /ready, GET /status, GET /api/v1/version, GET /api/v1/gateway/services, GET /api/v1/gateway/dashboard, plus le routage attrape-tout /api/{path} |
| Données gérées | Aucune. Ni base de données, ni couche de persistance, ni migration |
| Dépendances | Le serveur d'identité pour la vérification des jetons, Redis pour la limitation de débit |
| Capacités IA | Aucune. Elle applique une limite dédiée de 20 appels par minute sur les chemins /api/v1/ai/* |
| Limites connues | Deux replis de compatibilité renvoient un corps vide en 200 sur circuit ouvert, uniquement en lecture ; toute écriture laisse remonter la vraie erreur. Deux services hérités sont encore référencés par le module d'agrégation alors qu'ils n'existent plus |
| Statut | 🟢 Livré — en ligne sur les trois environnements |
| Preuve | backend/api-gateway/main.py, backend/api-gateway/src/core/registry.py, backend/api-gateway/src/routes/proxy.py |
Ce qu'elle applique concrètement
| Mécanisme | Réglage réel |
|---|---|
| Vérification de jeton | Realm principal + realm additionnel d'administration, algorithme RS256, cache des clés publiques rafraîchi toutes les heures, service en cas de cache périmé, cinq tentatives, pré-chauffage au démarrage |
| Injection d'en-têtes | Identifiant de locataire, identifiant d'utilisateur, rôles, juridiction |
| Disjoncteur | Cinq échecs déclenchent l'ouverture, trente secondes de récupération |
| Limitation de débit | 300 appels par minute par défaut, clé par utilisateur si le jeton est valide, sinon par adresse ; 5 par minute sur l'authentification |
| Protection anti-falsification | Double soumission de cookie |
| Santé honnête | GET /health/aggregate renvoie 200 seulement si tous les services amont répondent 200, sinon 503 réel |
#Fiche A2 — Service d'identité et de plan de contrôle user-service
Rôle en une phrase. Il détient les personnes, les organisations, les droits, les abonnements et les preuves de conformité en matière de vie privée.
Problème résolu. Une plateforme multi-locataire sans autorité unique sur « qui est qui, dans quelle organisation, avec quels droits » devient impossible à auditer. Ce service est cette autorité.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | S'authentifier, créer et rejoindre une organisation, inviter un collègue avec un lien à durée limitée de 7 jours, activer la double authentification, révoquer ses sessions, consulter et exporter ses données personnelles, souscrire, changer de plan, annuler en fin de période, appliquer un code promotionnel |
| Surface réelle | 14 familles de préfixes : /api/v1/auth, /users, /profile, /organizations, /roles, /permissions, /settings, /account, /invitations, /security, /admin, /keycloak, /billing, plus une surface GraphQL à /api/v1/graphql |
| Données gérées | app_users, app_user_profiles, app_organizations, app_org_memberships, app_org_invitations, app_roles, app_permissions, app_user_role_assignments, app_permission_overrides, app_permission_audit_log, app_consent_records, app_dsar_requests, app_data_export_jobs, app_user_jurisdictions, app_plans, app_subscriptions, app_invoices, app_payment_methods, app_coupons, app_billing_config, app_trial_records, app_stripe_event_log |
| Dépendances | Serveur d'identité Keycloak, fournisseur de paiement, bus d'événements optionnel |
| Capacités IA | Aucune |
| Limites connues | Le mode d'authentification par en-têtes auto-déclarés est la valeur par défaut du code ; le proxy d'administration du serveur d'identité renvoie un 501 explicite quand aucun identifiant d'administration n'est configuré ; les compteurs d'usage de GET /billing/usage sont codés en dur ; aucun manifeste Kubernetes de ce service n'est versionné dans le dépôt |
| Statut | 🟢 Livré |
| Preuve | backend/user-service/main.py, src/api/billing_routes.py, src/services/permission_engine.py |
Le moteur de permissions en cascade
| Étage | Règle |
|---|---|
| 1 | Défaut de rôle : union sur tous les rôles, une autorisation l'emporte |
| 2 | Dérogation explicite, départagée par un score de spécificité, puis par priorité décroissante, puis par date décroissante |
| 3 | En l'absence des deux, refus — c'est le principe de refus par défaut |
Chaque évaluation écrit une ligne dans le journal de permissions.
#Fiche A3 — Service exemple example-service
Rôle en une phrase. C'est le gabarit « dupliquez-moi » : un microservice CRUD complet, neutre de tout domaine, qui montre comment on écrit un service correct sur ce châssis.
Problème résolu. Créer un nouveau service demande normalement de retrouver les bonnes conventions : résolution du locataire, garde anti-usurpation, RBAC serveur, santé honnête, migration idempotente. Ici tout est déjà écrit, il suffit de renommer les entités.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Rien en production : ce n'est pas un service métier. Un développeur le duplique pour démarrer un nouveau contexte borné |
| Surface réelle | /api/v1/items (CRUD paginé complet) et /api/v1/ledger (comptes, écritures, solde calculé, garde métier anti-découvert), plus une surface GraphQL minimale |
| Données gérées | app_example_items, app_example_ledger_accounts, app_example_ledger_entries |
| Dépendances | PostgreSQL uniquement |
| Capacités IA | Aucune, volontairement |
| Limites connues | Il est exclu de l'agrégat de santé de la plateforme : son absence sur un cluster partagé ne doit pas faire basculer l'état global en dégradé. Il reste routable et visible dans l'état détaillé |
| Statut | 🟢 Livré en tant que gabarit |
| Preuve | backend/example-service/main.py, src/api/routes_items.py, src/api/routes_ledger.py |
4. Partie B — Les services de la vague 1 (cœur SDD)
#Fiche B1 — Magasin de spécification spec-service
Rôle en une phrase. Il détient la spécification comme structure de données : des objets typés, versionnés, reliés, et une machine à états qui interdit les raccourcis.
Problème résolu. Une exigence écrite dans un document meurt le jour où le document n'est plus lu. Ici, l'exigence est une ligne de base de données avec un identifiant canonique, un statut, des révisions et des arêtes vers ce qui la satisfait et ce qui la vérifie.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un projet, créer et modifier des objets de spécification, les relier, faire transiter leur statut, geler une base de référence, produire une matrice de traçabilité, calculer le rayon d'impact d'un changement, bâtir un arbre de document d'exigences produit, enregistrer et faire évoluer des décisions d'architecture |
| Surface réelle | /api/v1/projects, /api/v1/spec-items, /api/v1/projects/{id}/spec/{specify,clarify,plan,tasks,converge,implement}, /api/v1/projects/{id}/spec/analyze, /api/v1/projects/{id}/model/validate, /api/v1/projects/{id}/prd/bootstrap, /api/v1/projects/{id}/baselines, /api/v1/projects/{id}/adrs, /api/v1/projects/{id}/traceability-matrix, /api/v1/spec-items/{id}/impact, /api/v1/events |
| Données gérées | app_project, app_spec_item, app_spec_relationship, app_spec_item_revision, app_id_counter, app_external_link, app_constitution_article, app_baseline, app_adr_detail, app_adr_option, app_adr_supersession, app_adr_review, app_adr_decision_drift, app_spec_event |
| Dépendances | collaboration-service pour le métamodèle résolu, dependency-graph-service pour l'impact, ai-orchestrator pour les générations |
| Capacités IA | Aucun appel direct à un modèle. Les générations sont déléguées à l'orchestrateur. Les moteurs EARS et de pilotage sont symboliques et purs |
| Limites connues | L'export d'une décision d'architecture en PDF renvoie un 501 explicite ; le vocabulaire de relations n'est pas contraint en base, seulement dans le code ; un service de graphe injoignable produit un 502 typé, jamais un rayon d'impact fabriqué |
| Statut | 🟢 Livré |
| Preuve | backend/spec-service/main.py, src/domain/state_machine.py, src/domain/ears.py |
Le vocabulaire canonique, mesuré
| Élément | Nombre réel | Source |
|---|---|---|
| Types d'objets de spécification | 63 | backend/shared/shared/ids/engine.py, constante REGISTRY_TYPES |
| Types de relations | 24 | backend/shared/shared/metamodel/document.py, constante REL_TYPES |
| Statuts du cycle de vie | 7 : brouillon, clarifié, planifié, en développement, implémenté, vérifié, déprécié | src/domain/constants.py |
L'identifiant canonique a la forme PROJ-TYPE-NNNN, avec une séquence à quatre chiffres minimum, immuable, jamais réutilisée, allouée par un compteur atomique en base.
#Fiche B2 — Copilote de spécification copilot-service
Rôle en une phrase. Il transforme une intention exprimée en langage naturel en objets de spécification validés, sous garde-fous, avec un tableau d'agents en direct.
Problème résolu. Écrire une spécification structurée à la main est lent et décourage. Dicter une intention et obtenir des objets typés, validés et rattachés supprime la barrière d'entrée — à condition que rien ne soit écrit sans validation.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Décrire un besoin en français et obtenir des objets de spécification ; suivre l'exécution en direct ; poser une question sur un document téléversé ; demander un enrichissement approfondi par un collège d'experts ; proposer un lot d'écritures et le confirmer ; pré-remplir un formulaire depuis un document |
| Surface réelle | POST /api/v1/copilot/specify (202), POST /copilot/enrich (202), GET /copilot/runs/{id}/events (flux d'événements serveur), POST /copilot/uploads, POST /copilot/ask, POST /copilot/analyze, POST /copilot/save-objects/propose puis /confirm, POST /copilot/form-fill, POST /copilot/rpa/extract, GET /copilot/reviews |
| Données gérées | app_copilot_run, app_copilot_run_event, app_copilot_setting, app_copilot_kb_article, app_copilot_document, app_copilot_doc_chunk, app_copilot_proposal, app_copilot_ask, app_copilot_review, app_copilot_analysis |
| Dépendances | Passerelle de modèles LiteLLM, spec-service, collaboration-service (métamodèle), ai-orchestrator (enrichissement), ml-service (optionnel), Qdrant (optionnel) |
| Capacités IA | Oui, réelles. Appel de complétion vers un proxy compatible OpenAI ; température 0,2 ; 4 096 jetons maximum ; identifiants lus au coffre |
| Limites connues | La recherche augmentée est désactivée par défaut : un document est découpé mais marqué dégradé, et la récupération renvoie un 501 typé. Le stockage d'objets est désactivé par défaut. Sans service de facturation, le reçu porte explicitement « non facturé » |
| Statut | 🟢 Livré |
| Preuve | backend/copilot-service/src/services/copilot_service.py, src/services/run_stream.py, src/services/safety.py |
La chaîne d'exécution, telle qu'écrite
création du run → run.started → appel du modèle → llm.completed avec le comptage de jetons → analyse et validation strictes, une seule relance corrective → spec.persisting → appel à spec-service → run.completed. Toute erreur produit un run en échec ; le magasin de spécification n'est appelé qu'après validation, donc aucun objet partiel n'est écrit.
Les cinq garde-fous
| Garde-fou | Effet |
|---|---|
| Classifieur de sûreté | Appliqué en tête de chaque entrée en langage naturel, avant tout appel de modèle et tout débit |
| Validation humaine de niveau 2 | Les objets d'écriture sont proposés, jamais appliqués sans confirmation explicite |
| Politique brouillon/définitif | Chaque résultat persisté est marqué et accompagné d'un enregistrement de revue |
| Pré-vérification de crédits | Un solde insuffisant renvoie 402 avant tout appel de modèle |
| Ticket de flux signé | L'abonnement au flux d'événements exige un ticket à durée limitée lié au run |
#Fiche B3 — Registre de champs dynamiques custom-fields-service
Rôle en une phrase. Il permet à chaque organisation cliente d'ajouter ses propres attributs à des entités existantes, sans migration de schéma.
Problème résolu. Deux clients n'ont jamais exactement les mêmes champs. Sans registre dynamique, chaque demande devient un changement de code et un déploiement.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Déclarer un champ sur un type d'entité, lui donner un type de donnée et des contraintes, lire et écrire ses valeurs, obtenir une spécification de rendu prête à afficher |
| Surface réelle | 12 routes : /api/v1/custom-fields/schemas[...], /custom-fields/values/{type}/{id}, /custom-fields/render-spec/{type}[/{id}], /custom-fields/ai/apply |
| Données gérées | app_custom_field_schema, app_custom_field_value |
| Dépendances | PostgreSQL uniquement |
| Capacités IA | Aucune. La route dite « IA » est un point d'écriture consommé par le copilote ; la validation se fait contre le registre, pas par un modèle |
| Limites connues | Six types de donnée seulement : chaîne, nombre, booléen, date, énumération, JSON. Aucun drapeau de fonctionnalité |
| Statut | 🟢 Livré |
| Preuve | backend/custom-fields-service/main.py, CONTRACT.md |
#Fiche B4 — Pipeline d'ingestion documentaire ingestion-service
Rôle en une phrase. Il transforme un document téléversé en candidats de spécification, sous validation humaine obligatoire et sous barrière de renseignements personnels.
Problème résolu. Une organisation arrive avec des cahiers des charges en PDF et des tableaux Word. Les retranscrire à la main coûte des semaines. Les importer sans contrôle produirait une spécification fausse et exposerait des données personnelles.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Téléverser un document, voir les candidats extraits, les modifier, les rejeter, les relier à un objet existant, ou les accepter — l'acceptation seule crée un objet réel |
| Surface réelle | POST /api/v1/ingestion/uploads, GET /ingestion/documents[/{id}[/candidates]], POST /ingestion/candidates/{id}/review |
| Données gérées | app_ingestion_document, app_ingestion_candidate — les deux en isolation par ligne forcée |
| Dépendances | Stockage objet compatible S3, spec-service, prompt-orchestration-service (optionnel), ml-service (optionnel), Qdrant (optionnel) |
| Capacités IA | Optionnelles et désactivées par défaut : génération assistée et déduplication sémantique. En configuration par défaut, le service tourne entièrement en déterministe local |
| Limites connues | Une image est stockée mais produit zéro candidat et un statut dégradé : aucune transcription n'est fabriquée. Aucun événement n'est publié sur le bus |
| Statut | 🟢 Livré |
| Preuve | backend/ingestion-service/src/services/pipeline.py, src/services/review_service.py, src/domain/classify.py |
Les dix étapes du pipeline
| # | Étape | Comportement honnête |
|---|---|---|
| 1 | Normalisation du type | Extension inconnue ⇒ refus typé 415 |
| 2 | Création du document | Provenance ingested:<nom de fichier> |
| 3 | Extraction du texte | Markdown, texte, PDF et DOCX réels ; image ⇒ dégradation honnête |
| 4 | Stockage | Auto-guérison du seau ; échec ⇒ statut « indisponible », jamais de référence fabriquée |
| 5 | Classification | Langue toujours détectée localement ; renseignements personnels détectés localement ou par le service ML |
| 6 | Structuration | Déterministe, pure : tableaux, titres, puces. Un texte sans marqueur n'est pas inventé en candidat |
| 7 | Génération assistée | Seulement si activée ; le document est encadré comme donnée non fiable, jamais instruction |
| 8 | Déduplication | Seuil de doublon 0,92 ; seuil de conflit 0,80 avec test de contradiction |
| 9 | Persistance | Marquage par candidat des extraits contenant des renseignements personnels |
| 10 | Statut final | En attente de revue s'il y a des candidats, jamais « accepté » |
La barrière Loi 25. Accepter un candidat marqué comme contenant des renseignements personnels exige une justification non vide, sous peine d'un refus typé 422. La justification est conservée dans l'enregistrement de revue. Les échantillons de détection sont masqués : la valeur brute n'est jamais persistée.
#Fiche B5 — Service d'apprentissage automatique ml-service
Rôle en une phrase. Il sert des prédictions honnêtes : soit un calcul réel, soit un refus explicite — jamais une valeur inventée.
Problème résolu. Les autres services ont besoin de similarité, de triage, de prévision et de classification. Les centraliser évite sept implémentations divergentes et rend leur provenance auditable.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Indirectement : bénéficier de la déduplication à l'ingestion, du triage d'échecs de test, de la prévision de consommation, de l'extraction de documents |
| Surface réelle | POST /api/v1/ml/{embed,similar,triage-score,forecast,classify,extract,map-schema,vision-classify}, GET /api/v1/ml/{models,extract/capabilities} |
| Données gérées | app_ml_model (registre versionné), app_ml_prediction (journal d'audit, empreinte de l'entrée, jamais le texte brut), app_ml_embedding_ref |
| Dépendances | Passerelle de modèles pour les plongements et la classification à zéro exemple, Qdrant pour la similarité |
| Capacités IA | Sept modèles enregistrés au démarrage, tous marqués déterministes ; deux chemins seulement font appel à un modèle distant : les plongements et la classification à zéro exemple |
| Limites connues | Voir le tableau des dégradations ci-dessous. Aucun modèle entraîné n'existe dans le dépôt |
| Statut | 🟢 Livré |
| Preuve | backend/ml-service/src/domain/registry_seed.py, src/services/vision_classify.py, src/domain/triage_model.py |
Les sept modèles enregistrés — et ce qu'ils sont vraiment
| Nom | Tâche | Technique réelle |
|---|---|---|
failure-triage |
Triage de défaillance | Inférence logistique multinomiale à poids écrits à la main, puis normalisation exponentielle. Quatre classes : défaut produit, instable, environnement, données |
usage-forecast |
Prévision | Moindres carrés ordinaires en forme fermée + intervalles de prédiction de Student. Moins de 3 points ⇒ refus honnête |
pii-detector |
Détection de renseignements personnels | Expressions régulières + somme de contrôle de Luhn. Ne renvoie jamais la valeur brute |
document-type-lexical |
Classification de type de document | Fréquence de termes pondérée. Signal trop faible ⇒ renvoie honnêtement « autre » |
doc-extract |
Extraction | Routage multi-moteurs : PDF, tableur, CSV, image, DOCX, texte |
doc-schema-map |
Mise en correspondance de schéma | Correspondance approximative déterministe ; sous le seuil, le champ reste non mappé |
page-vision |
Analyse de page | Profils de projection et densité d'encre |
Les dégradations, telles qu'écrites
| Situation | Réponse |
|---|---|
| Modèle de plongement non configuré | 501 |
| Magasin vectoriel non configuré | 501 vector-store/unconfigured |
| Fournisseur injoignable | 502 ou 503 |
| Historique insuffisant pour une prévision | 422 forecast/insufficient-history |
| Moteur d'extraction absent | 501 nommant le moteur manquant |
| Bibliothèque d'image absente | 501 vision/engine-unavailable |
| Reconnaissance de caractères demandée sans binaire | Type de document laissé nul avec avertissement — jamais deviné |
#Fiche B6 — Service d'expérience de portail portal-experience-service
Rôle en une phrase. Il fournit au portail client ses agrégats de page d'accueil, ses assistants pas à pas, ses tableaux de bord, ses vues sauvegardées, ses notifications et sa palette de commandes.
Problème résolu. Sans lui, chaque écran du portail ferait dix appels et recomposerait la même logique côté navigateur. Le service assemble une fois, côté serveur.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Voir sa page d'accueil agrégée, dérouler un assistant et le reprendre où il s'est arrêté, composer un tableau de bord, sauvegarder et partager une vue filtrée, consulter son centre de notifications, ouvrir la palette de commandes, suivre sa progression d'intégration |
| Surface réelle | 30 routes sur 9 préfixes : /api/v1/home, /wizards, /dashboards, /metrics, /saved-views, /notifications, /screens, /palette, /onboarding, plus le sous-ensemble d'espace de travail /api/v1/app/projects/{id}/... |
| Données gérées | app_metric_definition, app_dashboard_definition, app_dashboard_widget, app_saved_view, app_wizard_run, app_notification, app_screen_contract, app_onboarding_step, app_onboarding_progress, app_workspace_view_state |
| Dépendances | PostgreSQL ; le catalogue livré est semé par les migrations elles-mêmes |
| Capacités IA | Aucune |
| Limites connues | Seules 4 routes portent une garde de rôle explicite : création et suppression de tableau de bord, démarrage et avancement d'assistant. Les autres n'ont que l'isolation par locataire |
| Statut | 🟢 Livré |
| Preuve | backend/portal-experience-service/main.py, migrations/0002_app_workspace.sql |
#Fiche B7 — Service de collaboration et de métamodèle collaboration-service
Rôle en une phrase. Il porte les espaces produit, les fils de commentaires, les revues avec séparation des devoirs, la modélisation par domaine, et le métamodèle propre à chaque projet.
Problème résolu. Une spécification sans conversation ni revue devient un monologue. Et un métamodèle unique imposé à tous les projets force chaque équipe à plier sa méthode. Ce service résout les deux.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un espace produit et y ajouter des membres, ouvrir un fil de commentaires sur n'importe quel objet, le résoudre ou le rouvrir, soumettre une revue et rendre un verdict, définir des contextes bornés et une carte de contexte, générer un diagramme d'agrégat, activer un ou plusieurs paquets de méthode sur un projet |
| Surface réelle | 28 routes sur 5 préfixes : /api/v1/spaces, /comments, /reviews, /ddd, /metamodel |
| Données gérées | app_product_space, app_space_member, app_comment_thread, app_comment, app_review, app_review_event, app_bounded_context, app_context_map_edge, app_aggregate, app_metamodel_version, app_metamodel_element |
| Dépendances | spec-service pour la vérification des références |
| Capacités IA | Aucune. Le rendu de diagramme est une fonction pure |
| Limites connues | Aucun drapeau de fonctionnalité, aucun 501 |
| Statut | 🟢 Livré |
| Preuve | backend/collaboration-service/src/domain/review_state_machine.py, src/api/routes_metamodel.py |
Le catalogue de métamodèles intégrés — 17 paquets, version de catalogue 3
sdd-core · domain-model · spec-kit · kiro-ears · shape-up · safe · openspec · bdd · adr · c4-model · archimate · togaf · zachman · bmad-core · diataxis · tessl · task-master
Plusieurs paquets peuvent être actifs simultanément sur un même projet ; la référence résolue est alors composite. Un projet vierge retombe sur sdd-core. Le point d'accès GET /api/v1/metamodel/projects/{id}/resolved est le contrat lu par spec-service et par le copilote.
La séparation des devoirs, réellement codée. La machine à états de revue rejette une décision dont l'auteur est aussi le soumissionnaire. La décision exige le rang PUBLISHER. Neuf types de cibles de revue sont admis, cinq états et trois verdicts.
#Fiche B8 — Fabrique d'artefacts d'ingénierie artifact-service
Rôle en une phrase. Il génère et versionne les artefacts d'ingénierie — document d'exigences, UML, BPMN, ERD, ArchiMate, TOGAF, sécurité — et projette la documentation depuis la spécification.
Problème résolu. Les diagrammes vivent d'habitude dans des fichiers dessinés à la main, qui divergent du code dès la deuxième semaine. Ici, chaque artefact référence au moins un objet de spécification vérifié, et la documentation détecte sa propre dérive.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un document d'exigences produit, générer un diagramme UML parmi 14 types, un processus BPMN, un modèle entité-relation, une vue ArchiMate, un livrable TOGAF, un artefact de sécurité ; versionner chaque artefact avec un motif de changement obligatoire ; projeter une documentation bilingue, détecter sa dérive, la reprojeter, l'exporter |
| Surface réelle | `/api/v1/artifacts[/prd |
| Données gérées | app_artifact, app_artifact_version, app_doc, app_doc_version — les quatre en isolation par ligne forcée |
| Dépendances | spec-service (vérification des références), prompt-orchestration-service (génération assistée) |
| Capacités IA | Uniquement par POST /api/v1/artifacts/generate, en déléguant au service d'orchestration de prompts, avec une provenance tracée. Le rendu graphique est 100 % déterministe et sans modèle |
| Limites connues | Voir le tableau ci-dessous — c'est la fiche qui contient le plus d'écarts honnêtes du dossier |
| Statut | 🟢 Livré |
| Preuve | backend/artifact-service/src/domain/mermaid.py, src/services/projection.py, src/services/export.py |
Les deux invariants portés par le code
- Aucun artefact orphelin : chaque référence de spécification est vérifiée par un appel réel avant persistance, doublé d'une contrainte en base exigeant au moins une référence.
- Aucun faux succès : magasin de spécification injoignable ⇒
502typé ; génération en échec ⇒502typé ; moteur d'export absent ⇒501honnête, jamais un fichier vide.
UML : le compte exact
| Mesure | Valeur |
|---|---|
| Types acceptés | 14, verrouillés par une assertion au chargement du module |
| Types avec générateur dédié | 5 : classe, machine à états, séquence, composant, déploiement |
| Types retombant sur un organigramme générique | 9 |
Écarts connus de ce service
| # | Écart |
|---|---|
| 1 | Le routeur ArchiMate est monté dans le service mais son préfixe n'est pas déclaré à la passerelle : il est inatteignable depuis le portail |
| 2 | Réviser un ERD ou une vue ArchiMate perd le diagramme : le répartiteur de rendu ne couvre pas ces deux familles |
| 3 | La génération assistée n'accepte que 5 des 7 familles d'artefacts |
| 4 | Aucune lecture n'est protégée par un rôle ; seule l'isolation par locataire s'applique |
| 5 | Les transitions de statut ne sont pas contraintes : toute transition entre les 5 statuts est acceptée |
| 6 | L'export PDF force un encodage hérité ; le tiret cadratin employé par la projection elle-même devient un point d'interrogation |
| 7 | Aucune suppression n'existe dans l'API, ni pour les artefacts, ni pour la documentation |
| 8 | Les livrables TOGAF de forme « catalogue » et « matrice » sont stockés sans être validés ni rendus |
5. Partie C — Les services scopés de la vague 2
#Fiche C1 — Moteur de cycle de vie sdlc-service
Rôle en une phrase. Il pilote un projet d'un bout à l'autre : admission, découverte, spécification, conception, plan, construction, vérification, revue, livraison, exploitation, évolution, retrait.
Problème résolu. Les équipes traversent ces phases de toute façon, mais sans porte ni trace. Ici, chaque transition de phase est refusée si sa porte n'est pas satisfaite, et chaque promotion vers un environnement laisse une ligne.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Déposer une demande d'admission, la qualifier, la convertir en objet de spécification avec le lien de traçabilité persisté ; déclarer des portes d'étape ; préparer, geler et promouvoir une version ; ouvrir un correctif urgent ; vérifier après mise en production ; ouvrir un incident et en dériver des exigences ; instruire une demande de changement et son analyse d'impact ; planifier un retrait |
| Surface réelle | Environ 38 routes sous /api/v1/sdlc : /intake-requests, /lifecycle/{scope}, /stage-gates, /releases, /environments, /promotions, /feature-flags, /incidents, /change-requests, /maintenance-tasks, /deprecations, /autonomy |
| Données gérées | 15 tables, dont app_intake_request, app_lifecycle_state, app_stage_gate, app_release, app_environment, app_promotion, app_incident, app_change_request, app_maintenance_task, app_post_release_verification, app_deprecation, app_autonomy_policy |
| Dépendances | spec-service, deploy-service, dependency-graph-service, feedback-service — toutes optionnelles, non configurées ⇒ 503 typé |
| Capacités IA | Aucun appel de modèle. Le mode « pilote automatique » est un enchaînement de phases qui s'arrête aux points de validation humaine, pas une génération |
| Limites connues | Il n'existe pas d'entité défaut propre : seulement une référence sur l'incident. Il n'existe pas de point d'accès de matrice de traçabilité ici. La suppression d'un objet de spécification renvoie toujours un conflit typé : on déprécie, on ne supprime pas |
| Statut | 🟢 Livré |
| Preuve | backend/sdlc-service/src/services/gates.py, src/api/routes_lifecycle.py, src/api/routes_spec_items.py |
#Fiche C2 — Service de test et de qualité test-quality-service
Rôle en une phrase. Il génère des tests depuis les exigences, les exécute, calcule une couverture reliée aux critères d'acceptation, et regroupe les échecs en causes.
Problème résolu. Une suite verte ne prouve rien si personne ne sait quelle exigence elle couvre. Et quarante tests rouges provoqués par une même cause font perdre une journée à trois personnes.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Dériver des cibles de test depuis la spécification, générer des scénarios depuis un critère d'acceptation, générer des cas depuis un scénario, générer des cas limites, exécuter un run, lire un rapport, recalculer la couverture, regrouper les échecs, ouvrir un défaut par grappe, soumettre puis approuver un plan de test, produire une matrice de traçabilité, exporter les analyses |
| Surface réelle | Environ 75 routes sous /api/v1/test-quality |
| Données gérées | 29 tables, dont app_test_target, app_test_scenario, app_test_case, app_test_step, app_test_suite, app_e2e_journey, app_test_plan, app_coverage_surface, app_failure_triage, app_test_run, app_test_result, app_failure_cluster, app_test_spec, app_e2e_flow |
| Dépendances | prompt-orchestration-service obligatoire pour toute génération, spec-service, test-data-factory-service, agent-runtime-service, agentic-core-service, observability-board-service |
| Capacités IA | Oui, réelles et gouvernées. Aucune génération ne passe en direct : sans service d'orchestration de prompts configuré, la génération renvoie 503 generation/governance-required. Il n'existe aucun chemin de repli non gouverné |
| Limites connues | Voir ci-dessous |
| Statut | 🟢 Livré |
| Preuve | backend/test-quality-service/src/services/gateway.py, src/domain/gherkin.py, src/api/routes_coverage.py |
Ce qui est réel, ce qui ne l'est pas
| Affirmation courante | Réalité vérifiée |
|---|---|
| « Génération de tests par IA » | ✅ Réelle, mais obligatoirement gouvernée, sortie validée strictement, artefact posé en brouillon avec provenance agent:QA |
| « Éditeur Gherkin » | ⚠️ Il existe une validation Gherkin structurée (donné, quand, alors, et) doublée d'une contrainte en base. Il n'y a ni parseur de fichiers .feature, ni export Gherkin |
| « Carte de chaleur de couverture » | ⚠️ Aucune carte de chaleur dans ce service. L'équivalent est une surface de couverture : une grille dimensions × périmètres, exposée par GET /projects/{id}/coverage/surface. Le rendu visuel appartient au portail |
| « Couverture des critères d'acceptation » | ✅ Réelle, calculée depuis les runs verts, avec les trous listés explicitement |
| « Regroupement d'échecs » | ✅ Réel, mais désactivé par défaut : les routes renvoient 503 clustering/disabled |
| « Porte qualité » | ✅ Réelle : soumission puis approbation d'un plan par une personne différente, via le cœur agentique |
| « Portes d'évaluation d'agents » | ⚪ Le code pur existe mais n'est câblé à aucune route |
#Fiche C3 — Fabrique de données de test test-data-factory-service
Rôle en une phrase. Il produit des jeux de données de test synthétiques, reproductibles et sans aucun renseignement personnel réel.
Problème résolu. Tester avec une copie de la base de production est la première cause de fuite de données. Tester avec trois lignes bricolées ne prouve rien. Ce service tranche les deux.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un jeu de données, générer N enregistrements déterministes, générer un graphe d'entités liées avec des clés étrangères correctes par construction, dé-identifier, valider, matérialiser, démonter, consulter la provenance |
| Surface réelle | 11 routes sous /api/v1/test-data-factory/test-datasets |
| Données gérées | app_test_dataset, app_dataset_record, app_dataset_provenance |
| Dépendances | PostgreSQL uniquement |
| Capacités IA | Aucune. La génération est entièrement déterministe, sur la bibliothèque standard |
| Limites connues | Plafond de 10 000 enregistrements par appel. Le module de virtualisation de service existe en code pur mais n'est exposé par aucune route |
| Statut | 🟢 Livré |
| Preuve | backend/test-data-factory-service/src/services/generator.py, src/services/reidentification.py, src/domain/constants.py |
La conformité, telle qu'implémentée
| Mécanisme | Valeur réelle |
|---|---|
| Barrière Loi 25 | Toute stratégie non synthétique sans approbateur nommé ⇒ refus 422, doublé d'une contrainte en base |
| Seuil de k-anonymat | 2 |
| Risque de ré-identification maximal | 0,5 ; un identifiant direct résiduel force le score à 1,0 et le refus est automatique |
| Domaines de courriel employés | Domaines réservés par les normes, jamais un domaine réel |
| Numéros de téléphone | Bloc de fiction réservé |
| Reproductibilité | Empreinte de la graine ⇒ mêmes octets sur n'importe quelle machine |
| Marquage | Chaque enregistrement porte un marqueur explicite de synthèse |
#Fiche C4 — Configuration du produit généré product-config-service
Rôle en une phrase. Il décrit la pile technique, le style d'architecture, le découpage en services, les bibliothèques épinglées, la posture de sécurité et le modèle d'identité du produit que la plateforme fabrique.
Problème résolu. Sans contrainte déclarée, un agent génère du code dans la pile qu'il préfère. Ici, la configuration devient une contrainte de génération, et un artefact hors liste blanche est signalé.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Déclarer la configuration produit, la valider, obtenir le document de contraintes agrégé, l'appliquer, analyser un artefact contre elle, découper en services, épingler des bibliothèques et les faire rescanner, définir la posture zéro confiance, le modèle d'identité, et la configuration du fournisseur d'identité |
| Surface réelle | Environ 22 routes sous /api/v1/product-config |
| Données gérées | app_product_config, app_microservice_config, app_library_pin, app_security_config, app_iam_model, app_auth_config, app_shared_component |
| Dépendances | Base publique d'avis de vulnérabilité, coffre de secrets |
| Capacités IA | Aucune |
| Limites connues | Quatre points d'accès de calcul n'ont aucune garde de rôle. Le scan de vulnérabilité désactivé rend un verdict « inconnu » explicite, jamais un faux « conforme » |
| Statut | 🟢 Livré |
| Preuve | backend/product-config-service/src/domain/guards.py, src/services/vault_writer.py |
Invariant structurel vérifié au chargement du module : la table de configuration d'authentification ne peut pas contenir de colonne de secret. Seul un chemin de coffre y est écrit. La garde est exécutée à l'import, pas seulement documentée.
#Fiche C5 — Configuration de la plateforme platform-config-service
Rôle en une phrase. Il est le magasin de configuration d'exécution de KySpectra elle-même : drapeaux de fonctionnalité, configurations de modèles et d'adaptateurs, politiques d'exécution et garde-fous.
Problème résolu. Changer un comportement en production sans redéployer, et pouvoir dire à un auditeur exactement quelle politique était active à quelle date.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un drapeau à portée globale ou par locataire avec un déploiement progressif de 0 à 100 %, l'évaluer pour un locataire donné, déclarer une configuration de modèle avec son chemin de coffre, déclarer un adaptateur d'assistant, définir une politique d'exécution, créer un garde-fou et évaluer une action à la volée |
| Surface réelle | 24 routes sous /api/v1/platform-config |
| Données gérées | app_feature_flag, app_model_config, app_adapter_config, app_execution_policy, app_guardrail_policy |
| Dépendances | PostgreSQL uniquement |
| Capacités IA | Le service stocke des configurations de modèles mais n'appelle aucun modèle |
| Limites connues | La notion de budget n'existe pas dans ce service : elle vit dans le service de facturation et d'usage. Le point d'accès d'évaluation de garde-fou n'a aucune garde de rôle |
| Statut | 🟢 Livré |
| Preuve | backend/platform-config-service/src/services/flag_evaluation.py, src/services/guardrail_evaluation.py |
Deux garanties inscrites dans le schéma
| Garantie | Contrainte réelle |
|---|---|
| Aucun secret en base | Le chemin de coffre doit commencer par secret/ |
| Refus réseau par défaut | La politique réseau d'une politique d'exécution doit commencer par deny- ; les valeurs par défaut sont un refus total sauf liste d'autorisations, une durée maximale d'une heure, un espace de travail éphémère |
L'évaluation du rollout est déterministe : le seau est dérivé d'une empreinte stable de la paire clé de drapeau et identifiant de locataire, jamais d'un tirage aléatoire. Elle est donc uniforme et monotone : un locataire activé à un pourcentage donné le reste pour tout pourcentage supérieur.
L'évaluation de garde-fou est en refus par défaut, avec un ordre total de sélection du gagnant : priorité, puis le refus l'emporte sur l'autorisation, puis le locataire l'emporte sur le global, puis le motif le plus long, puis l'ordre alphabétique.
#Fiche C6 — Journal d'audit et conformité audit-compliance-service
Rôle en une phrase. Il tient un journal d'audit inviolable par chaîne de hachage, et produit des rapports de conformité Loi 25 sur une période.
Problème résolu. « Prouvez-moi que ce journal n'a pas été modifié » est une question à laquelle un fichier de logs ne peut pas répondre. Une chaîne de hachage vérifiable, si.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Rechercher dans le journal par acteur, action, ressource ou texte libre ; vérifier l'intégrité de la chaîne entière ; générer un rapport Loi 25 sur une période ; l'exporter |
| Surface réelle | 7 routes sous /api/v1/audit-compliance : /audit/events, /audit/verify-chain, /compliance/reports[/{id}[/export]] |
| Données gérées | app_audit_log (ajout seul, révocation des droits de modification en base, déclencheurs), app_compliance_report |
| Dépendances | PostgreSQL uniquement |
| Capacités IA | Aucune |
| Limites connues | Les trois lectures sensibles n'ont aucune garde de rôle, seulement l'isolation par locataire. L'export PDF renvoie un 501 explicite si la bibliothèque de rendu n'est pas installée, avec un message renvoyant vers l'export CSV |
| Statut | 🟢 Livré — en ligne sur les trois environnements |
| Preuve | backend/audit-compliance-service/src/services/hash_chain.py, migrations/0001_audit.sql |
La chaîne, telle que calculée
Le hachage d'une ligne combine le hachage de la ligne précédente et une sérialisation canonique de l'action, de l'acteur, de la ressource et de la charge utile. La première ligne part d'une valeur de genèse fixe. La vérification contrôle deux invariants par ligne : la continuité du chaînage et l'exactitude du recalcul. Elle retourne le premier bris avec sa raison typée. Une chaîne vide est valide par vacuité.
Le code le dit lui-même : la vérification effectue un vrai recalcul, elle peut retourner « invalide », elle ne tamponne rien.
Comment le journal se remplit. Un intergiciel partagé émet un événement d'audit par mutation réussie depuis n'importe quel service. Il suffit d'une ligne par service pour le brancher. Avant ce correctif, le journal existait mais restait vide.
Résidence des données : paramétrable, valeur par défaut « ca-qc », reportée dans chaque rapport.
#Fiche C7 — Tableau d'observabilité observability-board-service
Rôle en une phrase. Il calcule la progression réelle depuis les faits, évalue les seuils de niveau de service, et enregistre les brèches.
Problème résolu. Une progression déclarée à la main est une opinion. Une progression calculée depuis des critères d'acceptation vérifiés et des tâches terminées est un fait.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Lire un instantané agrégé, descendre du projet jusqu'à la tâche, s'abonner au flux, déclencher un calcul de progression, agréger les rollups enfants, définir des métriques et des cibles, évaluer une porte, consulter l'historique des brèches, ouvrir et faire transiter un défaut, consulter le graphe d'exécution d'un run d'agent |
| Surface réelle | 12 routeurs sous /api/v1/observability, plus un point d'exposition de métriques hors préfixe |
| Données gérées | app_progress_rollup, app_metric_definition, app_metric_value, app_defect, app_kpi_target, app_kpi_breach_event, app_ml_derivation, app_board_layout, app_ai_activity_event, app_ai_control_request |
| Dépendances | ml-service (optionnel), agentic-core-service (optionnel) |
| Capacités IA | Consommateur du service ML pour la classification de signal et la prévision ; non configuré ⇒ 502 typé |
| Limites connues | L'ingestion depuis un bus de messages ou un système de métriques est hors périmètre : les valeurs sont postées par l'API. Le rapport en PDF renvoie un 501 explicite |
| Statut | 🟢 Livré |
| Preuve | backend/observability-board-service/src/domain/catalog.py, src/api/routes_progress.py |
Trois invariants remarquables
| Invariant | Comportement |
|---|---|
| Progression calculée, jamais déclarée | POST /progress et PUT /progress renvoient toujours un refus typé progress/derived-only |
| Défaut vérifié seulement sur preuve | Un défaut n'atteint l'état « vérifié » qu'avec une preuve de nouvelle exécution verte, sinon conflit typé |
| Pas d'observation, pas de brèche | Une cible sans valeur observée renvoie « non évaluée » avec la raison, jamais une brèche |
Le catalogue d'indicateurs compte environ 42 entrées réparties en huit familles : flux, DORA, qualité, agents, coût, spécification, sécurité, fiabilité. Chaque entrée porte une formule évaluée par un moteur d'expressions sûr, jamais par une évaluation dynamique de code. Une entrée manquante produit un refus typé, pas un zéro.
⚠️ Écart d'affichage à connaître. Le tableau AgentOps de l'espace de travail du portail client ne lit pas ce service : il consomme les exécutions du copilote. Ce service porte sa propre piste d'activité, distincte.
#Fiche C8 — Facturation d'usage, budgets et crédits billing-usage-service
Rôle en une phrase. Il compte la consommation réelle, applique des budgets et des fenêtres de quota, et tient un grand livre de crédits en ajout seul.
Problème résolu. Laisser des agents consommer un modèle sans plafond est une facture surprise. Refuser après coup est trop tard. Ici, une charge qui ferait dépasser un budget est refusée avant d'être écrite.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Consulter sa consommation par modèle, définir un budget avec seuils d'avertissement et critique, déclarer une fenêtre de quota, mesurer le coût réel d'un correctif, consulter son solde de crédits, son historique et une prévision explicitement étiquetée « estimation » |
| Surface réelle | 6 routeurs sous /api/v1/billing-usage : /usage, /budgets, /quota-windows, /fix-budgets, /credits, /accounts |
| Données gérées | 15 tables, dont app_budget, app_usage_record, app_quota_window, app_fix_budget, app_credit_account, app_credit_transaction, app_credit_price, app_credit_voucher, app_provider_account, app_account_credential, app_switch_event |
| Dépendances | PostgreSQL, coffre de secrets pour les identifiants de fournisseur |
| Capacités IA | Aucune |
| Limites connues | Les prévisions sont étiquetées « estimation » par configuration. La table de comptes de crédits n'a volontairement pas de colonne de solde : le solde est toujours une somme du grand livre |
| Statut | 🟢 Livré |
| Preuve | backend/billing-usage-service/src/domain/budget_logic.py, migrations/0002_credit_economy.sql |
Prix par modèle réellement semés en base — en crédits pour mille jetons, en entrée puis en sortie :
| Modèle | Entrée | Sortie |
|---|---|---|
| valeur par défaut | 0,003000 | 0,015000 |
| famille équilibrée | 0,003000 | 0,015000 |
| famille rapide | 0,000800 | 0,004000 |
| famille experte | 0,015000 | 0,075000 |
| modèle tiers standard | 0,002500 | 0,010000 |
| modèle tiers léger | 0,000150 | 0,000600 |
Configuration semée : seuils d'alerte à 50, 80 et 95 % ; crédits de grâce à 0 ; bascule de routage à 80 % ; drainage à 95 %.
La garantie d'honnêteté sur la facturation vit dans la bibliothèque partagée, pas ici. Quand aucun service de facturation n'est joignable, la pré-vérification renvoie un ticket non contraignant et le reçu porte
metered=falseavec la raison « facturation désactivée ». Aucun montant n'est inventé.
#Fiche C9 — Registre d'extensions et de capacités extension-registry-service
Rôle en une phrase. Il est le catalogue gouverné des compétences, des serveurs et outils du protocole MCP, et des capacités de prompt — avec revue par une personne différente, refus par défaut et journal d'appels.
Problème résolu. Donner un outil à un agent est une décision de sécurité. Sans registre, cette décision est prise par celui qui écrit le code, sans trace et sans revue.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Importer une compétence avec vérification de signature honnête, la rédiger, la valider statiquement, la tester, la lier à un périmètre ; enregistrer un serveur d'outils et sa configuration d'authentification ; accorder ou refuser une permission d'outil ; soumettre, approuver ou rejeter une extension ; révoquer ; consulter le journal des appels d'outils et l'exporter ; adopter une entrée du catalogue global ; créer et paramétrer un rôle virtuel |
| Surface réelle | Une cinquantaine de routes sous /api/v1/extension-registry |
| Données gérées | app_skill, app_skill_version, app_skill_binding, app_mcp_server, app_mcp_tool, app_tool_permission, app_extension_review, app_tool_call_audit, app_prompt_capability, app_prompt_binding, app_capability_audit, app_capability_adoption, app_virtual_role |
| Dépendances | user-service comme source de vérité des droits commerciaux, prompt-orchestration-service, coffre de secrets |
| Capacités IA | Un classement sémantique existe, mais il opère sur des vecteurs fournis par l'appelant : aucune entrée-sortie propre |
| Limites connues | Les deux drapeaux maîtres — portées à trois niveaux et rôles virtuels — valent faux par défaut et aucun manifeste de déploiement ne les active. Sans eux, les routes de catalogue global, d'adoption et de rôles virtuels renvoient un 404 typé |
| Statut | 🟡 En cours — le code est complet et testé ; l'activation par environnement reste à faire |
| Preuve | backend/extension-registry-service/src/domain/catalog.py, src/core/entitlements.py, src/domain/tool_auth.py |
Les trois niveaux réels
| Niveau | Valeur | Propriétaire |
|---|---|---|
| Global | global |
Le locataire réservé de la plateforme |
| Organisation | tenant — le défaut |
Le locataire lui-même |
| Utilisateur | user — prompts uniquement |
La personne propriétaire |
« Projet » n'est pas un niveau : c'est une valeur de la grammaire de liaison, aux côtés de « locataire » et « agent ».
Le refus par défaut, en trois endroits
- La colonne d'effet d'une permission d'outil vaut
denypar défaut : sans ligne explicite d'autorisation pour le triplet outil, agent, projet, l'appel est refusé. - Une capacité n'est offerte que si elle est approuvée et liée et non révoquée — l'appelant ne voit rien plutôt qu'une capacité fabriquée.
- Au moment de l'appel, si le magasin de sessions est injoignable, le verdict est refus.
La séparation des devoirs, à trois étages : contrainte en base interdisant le même identifiant en soumissionnaire et en relecteur, garde applicative avant toute approbation, et exigence d'un identifiant d'acteur valide sous peine de refus « une décision doit être attribuable ». Approuver un sujet à risque élevé exige en plus une attestation de revue de sécurité.
Le plafonnement d'autonomie : le niveau effectif est le minimum entre le plafond du rôle et celui du plan. Une dégradation du service de droits retombe sur le niveau le plus bas — l'autonomie baisse en cas d'incertitude, jamais l'inverse.
Les secrets d'outils. La base ne stocke jamais une valeur de secret : seulement la forme non secrète et un chemin de coffre. Vingt noms de secret sont interdits hors des clés de coffre, huit en-têtes d'authentification sont interdits, et chaque chaîne passe un détecteur de secrets à fort signal. Le message de refus n'écho jamais la matière offensante.
#Fiche C10 — Graphe de dépendances dependency-graph-service
Rôle en une phrase. Il détient un graphe où chaque arête porte une origine et une preuve, et calcule des traversées, des cycles, des métriques de couplage et des rayons d'impact.
Problème résolu. « Si je change ceci, qu'est-ce qui casse ? » n'a de réponse fiable que si le graphe est bâti sur des faits sourcés, pas sur des suppositions.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Injecter des nœuds et des arêtes, interroger les ascendants, les descendants, les chemins et le voisinage, détecter les cycles, simuler un changement et son rayon de souffle, calculer des métriques de couplage et des points chauds, figer un instantané immuable et le comparer, importer une nomenclature logicielle, scanner les vulnérabilités et les licences, calculer l'impact réel d'un changement de spécification et l'ensemble minimal à régénérer |
| Surface réelle | Une trentaine de routes sous /api/v1/dependency-graph |
| Données gérées | app_dependency_node, app_dependency_edge, app_graph_snapshot, app_coupling_metric, app_hotspot, app_impact_simulation, app_sbom_component, app_vulnerability_finding, app_license_finding |
| Dépendances | Base publique d'avis de vulnérabilité |
| Capacités IA | Aucune |
| Limites connues | Le moteur de graphe est PostgreSQL, derrière une couture prévue pour un moteur de graphe natif — ce dernier n'est pas implémenté. Un scan désactivé rend un verdict « inconnu » explicite |
| Statut | 🟢 Livré |
| Preuve | backend/dependency-graph-service/src/graph_query/postgres_cte.py, src/domain/constants.py |
L'invariant dur. Une arête doit porter une origine et une preuve non vide : la contrainte est en base, pas seulement dans le code. Onze niveaux de nœuds, onze types d'arêtes de base plus vingt-trois de traçabilité, six provenances possibles.
Les bornes de coût sont explicites : profondeur par défaut 6, plafond 25 au-delà duquel la requête est refusée sans être exécutée ; longueur de cycle maximale 200 ; nombre de chemins par défaut 50, plafond 200.
#Fiche C11 — Plan d'exécution des agents agent-runtime-service
Rôle en une phrase. Il détient l'état d'exécution de chaque run d'agent : suivi, points de reprise, moteur de politique en refus par défaut, flux d'activité rejouable, et exécution en tâche Kubernetes éphémère.
Problème résolu. Faire tourner du code produit par une IA sur une machine partagée est un risque. L'isoler dans une tâche jetable, non privilégiée, sans réseau sauf une adresse autorisée, avec un système de fichiers en lecture seule, ramène ce risque à un niveau tenable.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Démarrer un run, le suspendre et le reprendre, répondre à une question interactive, l'interrompre, le rejouer, poser un point de reprise manuel, suivre son flux d'activité même après un changement de serveur, comparer deux captures d'écran, approuver une capture de référence |
| Surface réelle | Environ 20 routes sous /api/v1/agent-runtime, plus un descripteur de contrat d'environnement de développement |
| Données gérées | app_agent_run, app_checkpoint, app_activity_event, app_policy_check, app_vault_lease, app_visual_baseline |
| Dépendances | API Kubernetes, coffre de secrets, prompt-orchestration-service, extension-registry-service (optionnel) |
| Capacités IA | L'exécuteur en tâche éphémère lance un agent de codage en mode non interactif |
| Limites connues | L'exécuteur par défaut est en ligne dans le processus, et le manifeste de développement le fixe explicitement : le module déployé ne fournit pas d'isolation dure. Le manifeste de la politique réseau de l'espace de noms d'exécution n'est pas versionné dans le dépôt |
| Statut | 🟢 Livré pour le plan d'état ; 🟡 En cours pour l'isolation dure en exploitation |
| Preuve | backend/agent-runtime-service/src/executors/k8s_job.py, src/policy/engine.py, src/core/config.py |
La posture de sécurité de la tâche, telle que rendue
| Réglage | Valeur |
|---|---|
| Espace de noms | Dédié, jamais celui de l'application |
| Utilisateur | Non root, identifiant 1000 |
| Système de fichiers racine | Lecture seule, seul un espace temporaire est inscriptible |
| Capacités | Toutes retirées |
| Élévation de privilège | Interdite |
| Espace de travail | Volume éphémère de 2 Gio |
| Durée maximale | 3 600 secondes |
| Nettoyage | 600 secondes après la fin |
| Politique de redémarrage | Jamais — un run en échec n'est pas silencieusement rejoué |
| Sortie réseau autorisée | Une seule adresse, celle de la passerelle de modèles |
| Injection de secret | Par agent de coffre : le secret ne touche jamais la spécification de la tâche, ce service, la base ni un journal |
Le moteur de politique en refus par défaut autorise onze motifs d'action et refuse tout le reste. Sont intentionnellement absents, donc refusés : le déploiement en production, la suppression de fichiers par commande système, la sortie réseau, l'écriture hors espace de travail et l'emprunt de secret. Chaque verdict est écrit en base.
Comparaison visuelle : différence pixel à pixel et indice de similarité structurelle, calculés sur des tableaux numériques. Activée par défaut ; désactivée, elle renvoie un 503 honnête.
#Fiche C12 — Rétro-ingénierie reverse-engineering-service
Rôle en une phrase. Il part d'un dépôt de code existant et en extrait des faits horodatés par fichier et par ligne, en infère des candidats de spécification avec confiance et preuve, et verrouille leur promotion derrière une validation.
Problème résolu. Reprendre un système dont personne ne connaît plus l'intention. C'est le maillon « Comprendre » de la chaîne de valeur, et le seul moyen de partir de l'existant plutôt que d'une page blanche.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Déclarer une source durable pour un projet, lancer un travail d'analyse, suivre son avancement, consulter les artefacts extraits, traiter la file de validation, reconstruire à la demande sept familles d'artefacts, obtenir les contextes bornés, les vues d'architecture, la surface d'attaque, un plan de modernisation, analyser la dérive entre spécification et code, brancher un webhook d'analyse incrémentale |
| Surface réelle | Environ 30 routes sous /api/v1/reverse-engineering |
| Données gérées | 16 tables, dont app_reverse_job, app_source_ref, app_extracted_artifact, app_inferred_item, app_validation_task, app_drift_finding, app_dynamic_run, app_project_source, app_target_app |
| Dépendances | Binaire git dans l'image, coffre de secrets pour les jetons d'accès, spec-service pour la promotion |
| Capacités IA | Optionnelle et désactivée par défaut : enrichissement sémantique par plongements. Par défaut, la déduplication est locale et déterministe |
| Limites connues | Voir le tableau des langages ci-dessous. Le clone n'a ni délai d'expiration ni limite de taille |
| Statut | 🟢 Livré — chaîne prouvée en navigateur réel sur l'environnement de production |
| Preuve | backend/reverse-engineering-service/src/analysis/ingestion.py, src/analysis/emitters/, src/services/pipeline_runner.py |
Langages et formats : ce qui est vraiment analysé
| Entrée | Analyse réelle | Statut |
|---|---|---|
| Python | Arbre syntaxique complet de la bibliothèque standard : modules, classes, fonctions, complexité cyclomatique, graphe d'appels interne, imports internes contre externes, points d'accès HTTP par décorateur, détection d'authentification, entités et champs, événements publiés, code mort, surface de sécurité | ✅ Réel |
| JavaScript, TypeScript, Go, Java, Ruby, C# | Aucun analyseur — le fichier est ajouté à la liste « non supporté » | ❌ Non supporté, signalé honnêtement |
| SQL (définitions de tables) | Expressions régulières : tables, colonnes, clés étrangères | ⚠️ Heuristique |
| OpenAPI | Analyse YAML réelle : chemins, opérations, sécurité, champs requis | ✅ Réel |
| GraphQL | Réutilise l'analyseur OpenAPI, sans sémantique propre | ⚠️ Dégradé |
| Infrastructure — composition de conteneurs | Services, images, ports, dépendances | ✅ Réel |
| Infrastructure — Kubernetes | Quatre familles de ressources seulement | ✅ Réel mais restreint |
| Markdown | Premier titre, taille, extrait — aucune analyse sémantique | ⚠️ Superficielle |
| Historique de dépôt | Journal réel, plafonné à 200 commits | ✅ Réel borné |
| gRPC, intégration continue, exécution | Aucun gestionnaire ⇒ refus typé | ❌ Non supporté |
Il n'existe aucun analyseur polyglotte dans le service : la recherche exhaustive ne trouve aucune bibliothèque de ce type. Le seul langage réellement compris est Python.
Le clone, tel qu'exécuté. Aucune bibliothèque intermédiaire : appel direct au binaire, arguments passés en liste, jamais par un interpréteur de commandes. Clone superficiel à une seule branche. Le jeton est injecté par une option de configuration à chaque invocation, jamais dans l'adresse ni dans la configuration du dépôt cloné. Le répertoire temporaire est supprimé dans un bloc de nettoyage garanti, même en erreur. Les messages d'erreur sont caviardés et tronqués.
#Fiche C13 — Service de déploiement deploy-service
Rôle en une phrase. Il modélise, garde et enregistre la chaîne construction, test, analyse, porte, déploiement, surveillance comme une machine à états ordonnée et non contournable — et il exécute chaque étape pour de vrai.
Problème résolu. Un déploiement sans décision approuvée et sans trace est un effet de bord. Ici, il devient une décision, avec un demandeur, un approbateur différent, une preuve et un retour arrière.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un run et voir ses six étapes, exécuter tout le pipeline, faire une simulation à blanc, approuver ou rejeter, déclencher un rollout réel puis un retour arrière, publier un produit sur un sous-domaine avec certificat, générer et committer un pipeline d'intégration continue, vérifier un lien de registre, déposer un identifiant au coffre, exécuter une recette navigateur, analyser une base en exploitation |
| Surface réelle | 42 routes plus la santé, sous /api/v1/deploy — dont 28 routes de « forge » |
| Données gérées | app_deploy_run, app_deploy_stage, app_deployment, app_bastion_session, app_deploy_approval |
| Dépendances | API Kubernetes, registre d'images, coffre de secrets, dépôt Git |
| Capacités IA | Un point d'accès de vérification de passerelle de modèles exécute un appel réel ; aucune génération métier |
| Limites connues | L'interrupteur maître d'exécution réelle vaut faux par défaut ; le client DNS est écrit et testé mais non branché ; les pilotes nuage natifs n'existent pas |
| Statut | 🟢 Livré pour Kubernetes, prouvé en production · 🟡 Partiel pour les nuages publics |
| Preuve | backend/deploy-service/src/domain/pipeline.py, src/executors/, src/api/routes_forge.py |
Les six étapes et ce qu'elles font vraiment
| # | Étape | Exécution réelle | Sans l'outil |
|---|---|---|---|
| 1 | Construction | Clone puis construction d'image ; variante sans démon en tâche Kubernetes | 501 typé |
| 2 | Test | Commande de test configurée dans l'arbre cloné ; le code de retour est le verdict | 501 |
| 3 | Analyse | Trois dimensions réelles : analyse statique de sécurité, audit de dépendances, détection de secrets | 501 nommant les analyseurs manquants |
| 4 | Porte | Aucun outil externe : verdict dérivé des trois précédents | — |
| 5 | Déploiement | Application de l'image puis nouvelle interrogation : l'état « en ligne » n'est prononcé que si les répliques prêtes, mises à jour, disponibles et souhaitées coïncident | 501 deploy/live-not-enabled |
| 6 | Surveillance | Relecture post-déploiement ; sinon un retour est renvoyé vers la spécification | — |
Les invariants d'ordre, portés par un module pur : une étape d'ordre inférieur non franchie bloque l'avancement ; les portes non franchies sont listées ; l'étape de déploiement ne se marque jamais à la main ; un seul déploiement par run.
Les quatre fournisseurs d'intégration continue générés : GitHub Actions, GitLab CI, Azure Pipelines, Jenkins. La génération est un module pur ; les secrets sont référencés par nom de secret du fournisseur uniquement. Côté commit réel, deux cibles de gestion de version sont supportées ; la troisième est honnêtement déclarée non supportée.
Ce qui est réel côté nuage : un mécanisme générique — n'importe quelle interface en ligne de commande de nuage exécutée dans une tâche avec les identifiants déposés. Il n'existe aucun exécuteur dédié par fournisseur ; le module de publication nuage ne fournit que des plans avec leurs prérequis.
#Fiche C14 — Synchronisation d'intégrations integration-sync-service
Rôle en une phrase. Il synchronise dans les deux sens avec deux outils de suivi du marché, en gardant la spécification comme source de vérité.
Problème résolu. Les équipes ne vont pas abandonner leur outil de tickets du jour au lendemain. Mais laisser cet outil écraser la spécification détruirait le modèle. La réponse est une proposition de changement, pas une écriture aveugle.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Déclarer une connexion, exporter des objets de spécification vers l'outil de suivi de façon idempotente et dans l'ordre hiérarchique, recevoir un webhook signé, consulter les demandes de changement proposées, les approuver ou les rejeter, ouvrir une vraie demande de fusion |
| Surface réelle | 8 routeurs sous /api/v1/integration-sync |
| Données gérées | app_connection, app_external_link, app_webhook_delivery, app_sync_event, app_change_request, app_launch_binding, app_launch_event |
| Dépendances | spec-service, dependency-graph-service, les API des fournisseurs |
| Capacités IA | Aucune |
| Limites connues | L'application effective à la spécification est désactivée par défaut : l'approbation est enregistrée sans écriture. Les surfaces de lancement et le support multi-fournisseur de gestion de version sont désactivés par défaut et renvoient un 503 typé |
| Statut | 🟡 En cours — le code est complet, l'activation est un choix d'exploitation |
| Preuve | backend/integration-sync-service/src/security/webhook_verifier.py, src/api/routes_change_requests.py |
La vérification de signature est réelle : empreinte à clé sur le corps brut, comparaison à temps constant, quatre en-têtes acceptés par ordre de priorité, secret résolu au coffre avec repli sur variable d'environnement. Secret absent ⇒ requête rejetée, jamais validée par défaut. L'un des deux fournisseurs n'ayant pas de signature native, l'absence d'en-tête produit un rejet honnête.
L'idempotence est en base, par unicité de la paire système et identifiant de livraison — elle ne dépend pas de Redis. Une signature invalide est quand même enregistrée, marquée invalide, puis rejetée en 401.
#Fiche C15 — Orchestration de prompts prompt-orchestration-service
Rôle en une phrase. Il est le plan de contrôle des prompts : registre versionné, assemblage de contexte budgété et tracé, détection de secrets bloquante, et dispatch avec contrat de sortie.
Problème résolu. Un prompt écrit en dur dans un service est invisible, non versionné, non révisable, et peut fuiter un secret. Ici, il devient un objet gouverné.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Créer un modèle de prompt, en publier des versions immuables, le promouvoir, l'évaluer, assembler un envoi avec ses segments de contexte, l'envoyer réellement, valider la sortie contre un schéma, rejouer, gérer des paquets de capacités |
| Surface réelle | 7 routeurs sous /api/v1/prompt-orchestration |
| Données gérées | app_prompt_template, app_prompt_version, app_capability_pack, app_dispatch, app_dispatch_segment, app_dispatch_result, app_template_eval, app_skill_proposal |
| Dépendances | Passerelle de modèles, billing-usage-service (optionnel), coffre de secrets |
| Capacités IA | Oui, sur le point d'accès d'envoi : appel réel, validation de contrat, métrage des jetons |
| Limites connues | Voir ci-dessous |
| Statut | 🟢 Livré |
| Preuve | backend/prompt-orchestration-service/src/domain/budget.py, src/domain/contract.py |
Le budget de jetons, honnêtement décrit. L'estimation est une heuristique déterministe — le maximum entre le nombre de mots et le nombre de caractères divisé par quatre. Ce n'est pas un tokeniseur du modèle cible, et le code le dit. Le choix est assumé : la reproductibilité entre plateformes prime, car l'empreinte d'assemblage doit être stable.
L'invariant : aucune troncature silencieuse. Un dépassement de budget bloque l'envoi avec un refus typé, et les segments qui auraient dû sauter sont enregistrés sur l'envoi. On ne coupe jamais du contexte en douce.
Le contrat de sortie est vérifié par un validateur de schéma réel. Un schéma lui-même malformé est refusé avant tout appel de modèle. Une violation après une relance cadrée produit un conflit typé, avec l'envoi et le résultat conservés pour l'audit — jamais une analyse approximative.
La chaîne d'envoi : pré-vérification de crédits avant l'appel, envoi, validation, puis métrage réel — y compris en cas de violation de contrat, puisque le modèle a bien été invoqué. Une erreur de transport laisse l'envoi rejouable, sans charge fantôme.
⚠️ Écart relevé. La configuration pointe le service de facturation sur un port qui est en réalité celui du service de retours. Sans effet observable aujourd'hui, la facturation étant désactivée par défaut, mais à corriger.
#Fiche C16 — Service de retours produit feedback-service
Rôle en une phrase. Il capte les retours des utilisateurs finaux, les nettoie, les déduplique, les convertit en demandes d'admission réelles, et les rend publics sous forme de tableau, de feuille de route et de journal des changements.
Problème résolu. Les retours arrivent par courriel, par messagerie, par capture d'écran. Ils se perdent. Et quand une demande est livrée, personne ne prévient celui qui l'avait faite.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Déposer un retour depuis un widget embarqué ou depuis le portail, voter, suivre, commenter, partager ; côté équipe : qualifier, convertir en demande d'admission, fusionner un doublon, scorer selon un modèle de priorisation, faire transiter l'état, publier une entrée de journal des changements, lancer un sondage |
| Surface réelle | 6 routeurs authentifiés + un ensemble public sous /api/v1/feedback/public/* protégé par une clé de widget, pas par un jeton |
| Données gérées | app_feedback_item, app_feedback_widget_key, app_feedback_vote, app_feedback_follower, app_feedback_comment, app_feedback_share, app_feedback_survey, app_feedback_survey_response, app_feedback_changelog, app_feedback_counter |
| Dépendances | sdlc-service pour la conversion, user-service pour la résolution d'auteur, copilot-service pour l'enrichissement |
| Capacités IA | Oui, avec repli honnête : titre automatique, résumé et catégorisation par le copilote ; en cas d'échec, une heuristique qui se contente de réordonner les mots du soumettant — aucun contenu inventé. La source est toujours enregistrée |
| Limites connues | Toutes les dépendances valent « non configuré » par défaut ⇒ 503 typé ou étape marquée « ignorée ». Limitation de débit publique en mémoire de processus, 60 appels par minute et par clé |
| Statut | 🟢 Livré |
| Preuve | backend/feedback-service/src/services/ai_enrich.py, src/domain/rice.py, src/domain/state_machine.py |
La machine à états : nouveau, en revue, planifié, en cours, livré ; avec deux sorties, fermé et fusionné. La réouverture est possible depuis « fermé ». L'arête de livraison est modélisée explicitement, jamais forcée en silence.
La priorisation combine portée, impact, confiance et effort. La portée suggérée est un plancher observé — votes plus abonnés — et reste modifiable. Les quadrants valeur contre effort viennent des médianes observées ou de valeurs documentées, jamais de données inventées.
#Fiche C17 — Orchestrateur de démonstration demo-orchestrator-service
Rôle en une phrase. Il provisionne, réinitialise et supprime un locataire de démonstration complet, de façon idempotente et strictement confinée.
Problème résolu. Faire une démonstration crédible demande des données cohérentes dans quinze services. Les créer à la main est long ; les créer par script sauvage risque de toucher un vrai client.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Provisionner la démonstration, la réinitialiser à une base connue, la supprimer, consulter son statut, dérouler un script de visite guidée |
| Surface réelle | 5 routes seulement, sous /api/v1/demo |
| Données gérées | Une seule table, app_demo_manifest, sans couche de mapping objet — SQL direct |
| Dépendances | La passerelle d'interface, puisque tout le provisionnement passe par les API gouvernées |
| Capacités IA | Aucune. Le service n'appelle aucun modèle |
| Limites connues | Le module entier est désactivé par défaut et confiné au locataire de démonstration réservé : quand il est éteint, les écritures renvoient 404 et le statut se déclare désactivé, sans rien révéler |
| Statut | 🟡 En cours — code complet, drapeau éteint par défaut |
| Preuve | backend/demo-orchestrator-service/src/api/deps.py, migrations/0001_demo_manifest.sql |
La garde de sécurité est la seule dépendance des routes d'écriture : drapeau éteint, mauvais locataire ou rôle insuffisant sont rejetés avant toute session de base et tout appel réseau. Chaque ressource provisionnée porte un statut honnête : semée, déjà existante, en erreur, ou ignorée.
6. Partie D — Le plan agentique
#Fiche D1 — Orchestrateur IA ai-orchestrator
Rôle en une phrase. Il compose des graphes d'exécution d'agents, tient un collège d'experts de cycle de vie, et pousse le catalogue d'agents vers le registre central.
Problème résolu. Un agent seul répond à une question. Une chaîne d'agents avec classification d'intention, vérification de crédit, point de validation humaine et formatage de sortie produit un résultat exploitable.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Invoquer un agent, diffuser sa réponse, planifier, rejouer un flux, le reprendre, consulter les flux actifs et leur chronologie, saisir un expert du collège, demander un conseil collégial, approuver ou rejeter un run, consulter la file de validation humaine, gérer des tâches agentiques, indexer et interroger sémantiquement |
| Surface réelle | Environ 180 routes, sous /api/v1/ai et /api/v1/agents |
| Données gérées | app_semantic_index, app_copilot_task_logs, app_ai_outcomes, app_expert_run, app_team_run, app_expert_team, app_sdlc_expert_run — créées par des instructions idempotentes au démarrage |
| Dépendances | Passerelle de modèles LiteLLM, agent-registry-service, extension-registry-service (optionnel), memory-rag-service (optionnel) |
| Capacités IA | Oui, le plus intensif de la plateforme. Tous les appels passent par le proxy partagé, jamais en direct chez un éditeur |
| Limites connues | Voir ci-dessous |
| Statut | 🟢 Livré |
| Preuve | backend/ai-orchestrator/src/orchestrators/graphs.py, src/agentic/central_registry.py, src/api/routes_experts.py |
Les graphes réellement compilés
| Graphe | Rôle |
|---|---|
| Graphe de profil générique | Enchaînement : classification d'intention, vérification de crédit, agent, routage post-agent, validation humaine ou pont inter-agents, formatage, gestion d'erreur |
| Assistant | Graphe d'assistant conversationnel |
| Analyse comparative | Graphe d'analyse |
| Analyse de copilote | Graphe d'analyse asynchrone |
| Souscription | Graphe métier de décision |
Neuf orchestrateurs de profil sont compilés, tandis que la configuration en déclare quinze : six profils n'ont pas de graphe compilé. Un validateur vérifie que chaque agent et chaque compétence référencés existent.
Le pont vers le registre central. Au démarrage, le service pousse toutes ses spécifications d'agents vers le registre central, qui est déclaré source de vérité. Il peut aussi tirer ce qui lui manque. Registre injoignable ⇒ le registre en mémoire reste intact — dégradation gracieuse.
Écarts honnêtes de ce service
| # | Écart |
|---|---|
| 1 | L'adaptateur d'agent de codage lève systématiquement une erreur typée quand aucun environnement de codage n'est câblé |
| 2 | Une route de recommandations porte un commentaire de contrôle de rôle manquant : un identifiant d'utilisateur passé en paramètre permet de lire l'historique d'autrui |
| 3 | Le compteur de jetons d'un flux renvoie toujours zéro |
| 4 | Environ 29 routeurs sont montés sous capture d'erreur d'import : un import cassé fait disparaître silencieusement une famille de points d'accès sans faire échouer le démarrage |
| 5 | Les instructions de schéma sont paresseuses avec repli en mémoire : certaines fonctions peuvent tourner sans persistance si la base manque |
| 6 | Aucune garde de rôle déclarative sur les routes : l'autorisation repose sur la passerelle |
#Fiche D2 — Registre central d'agents agent-registry-service
Rôle en une phrase. Il est la source de vérité persistée de tous les agents de la plateforme.
Problème résolu. Sans registre unique, personne ne peut répondre à « combien d'agents tournent chez nous, avec quelles capacités, et lesquels sont sains ». Le portail d'administration affichait zéro agent avant sa création.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Par le portail d'administration : lire le registre central — nom, nature statique ou dynamique, capacités, compétences, serveurs d'outils, jetons estimés, état |
| Surface réelle | 3 routes seulement : enregistrement en lot, liste paginée, lecture par identifiant ou par nom. Plus deux sondes de santé, dont une strictement processus |
| Données gérées | app_agents, avec unicité de la paire locataire et nom |
| Dépendances | PostgreSQL uniquement |
| Capacités IA | Aucune — c'est un magasin |
| Limites connues | Aucun contrôle d'accès basé sur les rôles, et l'en-tête de locataire est optionnel. C'est assumé par la conception « interne seulement », mais toute compromission du réseau interne permettrait d'écrire dans le registre. Aucune migration versionnée : le schéma est créé par génération automatique, ce qui n'applique aucune modification de colonne |
| Statut | 🟢 Livré — vérifié sur les trois environnements |
| Preuve | backend/agent-registry-service/main.py, src/api/routes_agents.py |
#Fiche D3 — Cœur agentique et personnel virtuel agentic-core-service
Rôle en une phrase. Il détient le cycle de vie des tâches agentiques, la validation humaine, la coordination multi-agents, et le personnel virtuel IA : effectif, équipes, files de travail.
Problème résolu. Traiter un agent comme un employé — avec un rôle, une équipe, un niveau d'autonomie, une file de travail et un historique — plutôt que comme un appel de fonction anonyme.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Recruter un membre du personnel virtuel depuis l'interface, l'affecter à une équipe, lui assigner une tâche, suivre sa file, mettre en pause et reprendre, consulter le récapitulatif ; côté plan : créer un plan multi-agents, le démarrer, le mettre en pause, l'interrompre, le faire avancer, soumettre et approuver une décision humaine |
| Surface réelle | 5 groupes : /api/v1 hérité, /api/v1/mas, /api/v1/workforce, /api/v1/agents, /api/v1/roundtrip — atteignables via /api/v1/agentic-core |
| Données gérées | 19 tables. Personnel : app_workforce_team, app_workforce_staff, app_workforce_task. Coordination : app_mas_plan, app_mas_task, app_mas_lease, app_mas_agent, app_mas_schedule, app_mas_hil_decision, app_mas_event. Héritées, sans préfixe : agent_tasks, hitl_requests, agent_budgets, skill_registry |
| Dépendances | Redis, ai-orchestrator, les six agents de la flotte, copilot-service |
| Capacités IA | Coordination et acheminement ; les appels de modèle sont délégués |
| Limites connues | Voir ci-dessous — c'est le service le plus en écart avec les conventions du châssis |
| Statut | 🟢 Livré pour la phase 1 du personnel virtuel, prouvé en navigateur réel sur développement et sur production · ⚪ Planifié pour les phases 2 et 3 |
| Preuve | services/agentic-core-service/src/mas/workforce_models.py, src/mas/hil.py, src/api/fleet_routes.py |
Le personnel virtuel, phase 1 — ce qui existe vraiment
| Capacité | Route réelle | Statut |
|---|---|---|
| Créer une équipe | POST /api/v1/workforce/teams |
🟢 Livré |
| Recruter un membre | POST /api/v1/workforce/staff |
🟢 Livré |
| Modifier un membre — statut, équipe, autonomie | PATCH /api/v1/workforce/staff/{id} |
🟢 Livré |
| Assigner une tâche | POST /api/v1/workforce/staff/{id}/tasks |
🟢 Livré |
| Consulter la file d'un membre | GET /api/v1/workforce/staff/{id}/tasks |
🟢 Livré |
| Faire transiter une tâche | PATCH /api/v1/workforce/tasks/{id} |
🟢 Livré |
| Récapitulatif de l'effectif | GET /api/v1/workforce/overview |
🟢 Livré |
| Organigramme | Aucune route dédiée | ⚠️ Les primitives existent — équipe parente, coordinateur, rattachement du personnel — mais l'arbre doit être reconstruit par l'appelant |
| Autonomie déléguée, escalade, chaîne d'imputabilité | — | ⚪ Planifié |
Les deux systèmes de validation humaine, non unifiés
| Système | Garanties |
|---|---|
| Hérité | Cinq actions possibles, reprise de l'orchestrateur. Aucune garde de rôle, aucun contrôle de séparation des devoirs |
| Multi-agents | Machine à états stricte avec transitions légales seulement, trois politiques, et séparation des devoirs réelle : l'auto-approbation renvoie un refus typé |
Écarts assumés : ce service est hors du châssis partagé — configuration propre, création de schéma automatique pour les tables héritées, origines de partage de ressources ouvertes, base partagée plutôt que dédiée, adresse de cache codée en dur dans la valeur par défaut, aucune garde de rôle sur les routes héritées ni sur les connexions temps réel, et un jeton accepté puis jamais vérifié. La lecture de configuration de garde anti-boucle renvoie des valeurs codées en dur et ne relit pas ce que l'écriture a posé.
#Fiches D4 à D9 — Les six agents spécialisés
Les six services d'agents partagent une architecture identique : image durcie multi-étapes, utilisateur non privilégié, roue Python locale du kit de développement d'agents installée sans accès réseau, quatre routes racine, et un appel direct à la passerelle de modèles.
Constat transverse important. Aucun des six n'est enregistré à la passerelle d'interface : ils ne sont pas atteignables publiquement. Leur seule surface publique est le récapitulatif de flotte exposé par le cœur agentique. Leur route d'exécution n'a aucun appelant dans le dépôt : la flotte est câblée pour la synchronisation et le manifeste, pas encore pour l'exécution.
Constat de gouvernance. Les adresses du registre d'extensions et de l'orchestration de prompts sont vides par défaut dans les six configurations. La synchronisation centrale renvoie alors un conflit typé, et l'exécution retombe sur un chemin d'outils hérité, non filtré. Le champ de provenance des capacités indique honnêtement l'origine.
#Fiche D4 — Agent analyste analyst-agent-service (port 8100)
| Rubrique | Détail |
|---|---|
| Rôle | Analyse de sujet, recherche de segment, listes de diligence raisonnable, analyse de revenus récurrents, questions-réponses |
| Ce qu'il sait faire | 5 compétences, chacune avec un gestionnaire complet : appels d'outils, invite système spécialisée en français, appel de modèle, extraction stricte de JSON |
| Validation humaine réelle | Confiance sous 0,75 ou valeur au-delà d'un million déclenche un état d'attente humaine |
| Limites | Les valeurs de confiance sont codées en dur, non calculées |
| Statut | 🟢 Livré en tant que service ; 🟡 En cours pour son raccordement à l'exécution |
#Fiche D5 — Agent rédacteur writer-agent-service (port 8101)
| Rubrique | Détail |
|---|---|
| Rôle | Rédaction de contenu et résumé de document, en français et en anglais |
| Ce qu'il sait faire | 2 compétences, sous contraintes éditoriales explicites : interdiction des superlatifs invérifiables et des affirmations trompeuses, quatre tons paramétrables |
| Limites | Confiances codées en dur ; le besoin de revue est toujours faux. Le résumé de document existe aussi dans l'agent extracteur, avec une implémentation différente |
| Statut | 🟢 Livré en tant que service |
#Fiche D6 — Agent réviseur reviewer-agent-service (port 8102)
| Rubrique | Détail |
|---|---|
| Rôle | Porte qualité des boucles de retour : il note une sortie de 0 à 10 |
| Ce qu'il sait faire | 5 grilles de critères en français, cinq critères chacune. Le seuil de qualité par défaut est 8,5 |
| Garantie remarquable | L'approbation est recalculée en Python : le verdict du modèle n'est pas cru sur parole |
| Limites | Une compétence inconnue est silencieusement rétrogradée vers la revue de contenu au lieu d'échouer. Le raccordement de gouvernance est branché mais inutilisé, ce que le code dit explicitement |
| Statut | 🟢 Livré en tant que service |
#Fiche D7 — Agent extracteur extractor-agent-service (port 8103)
| Rubrique | Détail |
|---|---|
| Rôle | Extraction de données structurées depuis des documents non structurés |
| Ce qu'il sait faire | 2 compétences. Tri déterministe des constats par sévérité, et score de complétude calculé en Python — pas par le modèle — qui alimente la boucle de retour |
| Limites | Troncature de sûreté à dix mille caractères. Une confiance codée en dur pour le résumé |
| Statut | 🟢 Livré en tant que service |
#Fiche D8 — Agent calculateur calculator-agent-service (port 8105)
| Rubrique | Détail |
|---|---|
| Rôle | Calculs numériques et financiers déterministes. Le modèle ne produit que la recommandation narrative — jamais un nombre |
| Ce qu'il sait faire | 2 compétences. Amortissement, résolution de principal maximal, taux de capitalisation, rendement sur fonds propres, projection pluriannuelle — toutes en Python pur |
| Particularité | Seul agent avec une validation d'entrée réelle renvoyant un échec typé sur revenu négatif, durée hors bornes, pourcentage invalide |
| Limites | Les constantes sont explicitement déclarées « illustratives » dans le code, et certaines hypothèses ne sont pas paramétrables |
| Statut | 🟢 Livré en tant que service |
#Fiche D9 — Agent conseiller advisor-agent-service (port 8108)
| Rubrique | Détail |
|---|---|
| Rôle | Recommandation structurée et conseil de stratégie. Le manifeste dit : « conseiller, jamais promettre un résultat » et défère toute décision à conséquence juridique ou financière à un professionnel qualifié |
| Ce qu'il sait faire | 1 seule compétence — le plus étroit de la flotte. Cinq profils de demandeur avec des instructions distinctes |
| Validation humaine réelle | Confiance sous 0,78 ou montant au-delà d'un seuil élevé |
| Limites | Ses quatre appels d'outils sont séquentiels malgré un commentaire notant qu'ils pourraient être parallèles : dette de performance assumée |
| Statut | 🟢 Livré en tant que service |
#Fiche D10 — Mémoire et recherche augmentée memory-rag-service
Rôle en une phrase. Il tient la mémoire des agents sur quatre niveaux et fournit une recherche hybride avec fusion de rangs.
Problème résolu. Un agent sans mémoire recommence à zéro à chaque appel. Un agent avec une mémoire non hygiénisée finit par se contredire ou par se faire empoisonner.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Indirectement : bénéficier d'un contexte assemblé sous budget, d'une mémoire par agent, et d'une hygiène automatique |
| Surface réelle | Deux sous-systèmes : hérité /api/v1/memory/* et avancé /api/v1/agent-memory/*, plus les espaces de noms partagés |
| Données gérées | Héritées : mémoires épisodiques et explicites avec index vectoriel et index plein texte français. Avancées : app_agent_session, app_agent_memory, app_agent_memory_audit, app_context_snapshot |
| Dépendances | PostgreSQL avec extension vectorielle, Redis, Qdrant (optionnel), passerelle de modèles pour les plongements |
| Capacités IA | Plongements distants, génération d'un paragraphe hypothétique avant recherche, résumé et compactage |
| Limites connues | Voir ci-dessous |
| Statut | 🟢 Livré — le plus abouti des services d'agents, avec 11 fichiers de tests |
| Preuve | services/memory-rag-service/src/memory/service.py, migrations/0001_agent_memory.sql |
Les quatre niveaux réels
| Niveau | Support | Rétention |
|---|---|---|
| Mémoire de travail | Redis | 24 heures et 50 entrées maximum |
| Mémoire épisodique | PostgreSQL | Durable |
| Mémoire explicite et sémantique | PostgreSQL avec extension vectorielle | Durable |
| Session ou permanent (sous-système avancé) | PostgreSQL | Expiration paramétrable ; la fin de session purge la partition de session |
Trois protections réelles à l'écriture : déduplication exacte par empreinte, détection d'empoisonnement avec mise en quarantaine, et détection de conflit qui met en quarantaine le côté le moins fiable.
Écarts honnêtes
| # | Écart |
|---|---|
| 1 | La description annonce un reclassement par encodeur croisé : aucun n'est implémenté, et le réglage correspondant est inutilisé |
| 2 | Le magasin vectoriel avancé est vide par défaut ⇒ la récupération retombe en mode lexical, et l'écriture rapporte honnêtement « non indexé » |
| 3 | Deux modèles de sécurité coexistent : les routes héritées n'ont aucune authentification et lisent le locataire dans le corps ; le sous-système avancé l'impose par en-tête et par isolation de ligne |
| 4 | Si la bibliothèque partagée est absente de l'image, tout le sous-système avancé disparaît en 404 |
#Fiche D11 — Service de conversation chat-service
Rôle en une phrase. Il fournit un fil de conversation persistant avec diffusion de la réponse jeton par jeton.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Ouvrir une conversation, envoyer un message, voir la réponse s'écrire, archiver, consulter des statistiques |
| Surface réelle | 7 routes REST plus des événements temps réel |
| Données gérées | Conversations et messages, avec métadonnées : compétence détectée, agent, modèle, jetons, durée, confiance |
| Dépendances | Passerelle de modèles ; un orchestrateur dont l'adresse par défaut ne correspond à aucun service du dépôt |
| Capacités IA | Diffusion réelle, avec repli automatique en mode non diffusé si la passerelle refuse |
| Limites connues | Voir ci-dessous |
| Statut | 🟡 En cours — service réel, mais raccordement agentique non fonctionnel par défaut |
| Preuve | services/chat-service/src/main.py |
Ce que ce service n'est pas. Ce n'est pas un chat agentique : la détection d'intention est purement lexicale, la compétence détectée n'est pas exécutée, et la réponse vient d'un modèle généraliste. L'exécution réelle n'a lieu que sur un événement dédié, dont l'adresse cible par défaut est morte. Il ne parle jamais aux six agents ni au service de mémoire : aucune mémoire longue, aucune recherche augmentée. Aucune authentification sur les routes ni sur la poignée de main temps réel ; le locataire et l'utilisateur sont acceptés depuis le client.
7. Partie E — Le plan MCP
#Fiche E1 — Passerelle d'outils mcp-gateway
Rôle en une phrase. Elle est la porte d'entrée unique de l'exécution d'outils par les agents, et le point d'application de la politique.
Problème résolu. Laisser chaque agent appeler directement chaque outil rend impossible toute allow-list, tout budget et tout journal.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Indirectement : bénéficier d'un appel d'outil gouverné, journalisé et facturé |
| Surface réelle | 8 routes, atteignables sous /api/v1/mcp : santé, catalogue d'outils, liste des serveurs, découverte, rafraîchissement de santé, exécution, appel gouverné, appel explicite par serveur |
| Données gérées | Aucune. État entièrement en mémoire ; les entités du plan MCP appartiennent au registre d'extensions |
| Dépendances | API Kubernetes pour la découverte, registre d'extensions comme point de décision, coffre de secrets |
| Capacités IA | Aucune — elle achemine |
| Limites connues | Voir ci-dessous |
| Statut | 🟢 Livré pour le chemin gouverné, testé par 17 tests · 🟡 En cours pour son déploiement, aucun manifeste Kubernetes n'existant dans le dépôt |
| Preuve | backend/mcp-gateway/main.py, backend/mcp-gateway/README.md |
Les deux plans qui coexistent
| Plan | Gouvernance |
|---|---|
| Découverte et proxy hérité | Aucune : ni authentification, ni autorisation, ni locataire. Le fichier de description l'assume : ce sont les chemins internes de l'orchestrateur |
| Appel gouverné | Identifiant de locataire obligatoire et valide, décision déléguée au registre d'extensions, exécution uniquement sur autorisation explicite |
La posture d'échec fermé du chemin gouverné. Un refus est relayé verbatim et l'outil n'est pas exécuté. Une panne réseau du point de décision produit un refus. Une erreur serveur produit un refus. Toute erreur de résolution de secret produit un refus, sans exécution.
La résolution des secrets au moment de l'appel. Le point de décision ne voit jamais de secret : il ne stocke qu'un chemin de coffre. La passerelle lit le secret au moment de l'appel, l'injecte selon le type d'authentification, et ne journalise que des codes de raison non secrets. Les en-têtes statiques ne peuvent jamais écraser l'authentification résolue.
⚠️ Écart majeur. Le drapeau de portées à trois niveaux étant éteint par défaut, l'injection d'authentification amont est inerte en configuration par défaut.
#Fiche E2 — Serveurs d'outils mcp-servers
Rôle en une phrase. Ce sont cinq petits services par domaine, chacun exposant un catalogue d'outils que la passerelle agrège.
| Rubrique | Détail |
|---|---|
| Surface réelle | Contrat commun : santé, catalogue, exécution d'outil. 27 outils sur 5 serveurs |
| Données gérées | Aucune base. Deux fichiers JSON locaux au plus |
| Capacités IA | Aucune |
| Statut | 🟡 En cours |
| Preuve | backend/mcp-servers/*/main.py |
Inventaire honnête des 27 outils
| Serveur | Outils | En lecture | En écriture | Sur données d'exemple | Amont mort |
|---|---|---|---|---|---|
| Magasin de documents | 5 | 5 | 0 | 0 | 5 |
| Profils d'utilisateurs | 5 | 5 | 0 | 0 | 5 |
| Base de connaissances | 4 | 3 | 1 | 4 | 0 |
| Moteur de référentiels | 5 | 5 | 0 | 5 | 0 |
| Réglages et configuration | 8 | 7 | 1 | 8 | 0 |
| Total | 27 | 25 | 2 | 17 | 10 |
Trois rectifications factuelles importantes
- Les cinq serveurs sont des applications Python, pas Node.js. La documentation interne du projet affirme le contraire ; le dépôt dit l'inverse.
- Le protocole MCP n'est pas implémenté : ni appel de procédure JSON, ni transport par entrée-sortie standard, ni flux d'événements. C'est un contrat HTTP maison inspiré de MCP. Le schéma du registre autorise trois transports ; un seul existe.
- Le repli statique de la passerelle déclare 14 serveurs ; 9 n'ont aucune implémentation et seront systématiquement signalés en mauvaise santé.
Autres absences structurelles : aucun test, aucun manifeste Kubernetes, aucune authentification entrante, aucune isolation par locataire — l'état est global au processus et partagé entre tous les locataires.
8. Partie F — Paquets partagés et surfaces web
#Fiche F1 — Kit de développement d'agents packages/agent-sdk
Rôle en une phrase. C'est la roue Python autonome qui donne aux agents leurs contrats typés, leurs clients de passerelle et leur liaison de capacités centrale.
| Rubrique | Détail |
|---|---|
| Ce qu'il fournit | Modèles typés, classe de base d'agent, orchestrateur de domaine, client de modèles, client d'outils, résolveur de capacités, budget de jetons, garde anti-boucle, en-têtes de service, intégration de flotte |
| Volume réel | 2 837 lignes de source, 829 lignes de tests, 40 fonctions de test, roue 1.0.0 construite et versionnée |
| Capacités IA | Client vers le proxy de modèles, trois paliers de modèle |
| Limites connues | Aucune diffusion, aucune reprise sur erreur, aucun repli de modèle, aucun moteur d'orchestration, aucune persistance des budgets en base |
| Statut | 🟢 Livré |
| Preuve | packages/agent-sdk/src/agent_sdk/, packages/agent-sdk/dist/ |
Le fil conducteur : la liaison centrale de capacités. Un agent ne code pas en dur ses compétences, ses outils ni son invite : il résout tout depuis le registre d'extensions, en échec fermé. Une résolution impossible fait échouer le run avec le message « refus d'exécuter avec une gouvernance non résolue ».
Le budget de jetons est réel mais approximatif : le kit ne tokenise rien, il consomme les compteurs renvoyés par la passerelle et applique des plafonds dans le cache. La pré-autorisation est conservatrice, pas atomique : deux exécutions simultanées peuvent chacune passer avant d'incrémenter.
Écart notable : la classe de base d'agent et l'orchestrateur de domaine ne sont importés par aucun service. La surface réellement consommée se limite à l'intégration de flotte, aux en-têtes de service, au client de modèles et au résolveur de capacités.
Incohérence relevée : le palier expert est facturé au tarif du modèle le plus cher alors qu'il est exécuté sur le modèle intermédiaire.
#Fiche F2 — Compétences génériques packages/skills/global
Rôle en une phrase. Quatre spécifications de compétences transverses, en Markdown avec en-tête structuré.
| Rubrique | Détail |
|---|---|
| Contenu réel | 4 fichiers Markdown, 344 lignes au total. Aucun code exécutable |
| Les quatre compétences | Résumé de document, questions-réponses, extraction structurée, traduction bilingue |
| Taux d'implémentation | 2 sur 4 : le résumé et les questions-réponses ont un exécutant ; l'extraction structurée et la traduction n'en ont aucun |
| Limites connues | Aucun mécanisme de chargement n'existe. Aucun code du dépôt ne lit ces fichiers à l'exécution. Le registre effectif vit ailleurs, sous quatre formes dupliquées |
| Statut | 🟡 En cours — documentation de conception, pas un moteur |
| Preuve | packages/skills/global/*.md |
Conséquence opérationnelle honnête : un message contenant le mot « traduire » est routé vers un identifiant de compétence sans exécutant.
#Fiche F3 — Système de conception frontend/packages/design-system
| Rubrique | Détail |
|---|---|
| Rôle | Jetons de couleur, de typographie, d'espacement, de rayon et d'élévation ; composants ; motifs ; thème clair et sombre |
| Ce qu'il garantit | Une seule source de vérité pour la palette, reprise à l'identique par les trois portails et par ce dossier de lancement |
| Statut | 🟢 Livré |
| Preuve | frontend/packages/design-system/src/tokens.ts |
#Fiche F4 — Kit de portail frontend/packages/portal-shared
| Rubrique | Détail |
|---|---|
| Rôle | Composants de coquille communs aux portails : rail de navigation, barre supérieure, fil d'Ariane, palette de commandes, sélecteur de locataire, bascule de thème et de langue |
| Statut | 🟢 Livré |
| Preuve | frontend/packages/portal-shared/ |
#Fiche F5 — Widget de collecte de retours frontend/packages/feedback-widget
Rôle en une phrase. C'est un composant autonome à déposer sur n'importe quel site client, qui capture un retour avec son contexte technique.
| Rubrique | Détail |
|---|---|
| Ce que l'utilisateur peut faire | Signaler un problème, joindre une capture d'écran annotée, laisser un enregistrement d'interactions, le tout sans quitter la page |
| Ce qu'il capture vraiment | Capture d'écran sans dépendance externe : sérialisation du DOM en objet étranger SVG puis rastérisation sur canevas. Enregistreur d'événements d'interaction : clics avec chemin CSS, saisies masquées, défilements limités, navigations, redimensionnements |
| Limites déclarées dans le code | Les feuilles de style d'origines tierces sont illisibles et ignorées ; les images d'origines tierces sont remplacées par un cadre neutre ; la capture est un rendu statique, sans cadres imbriqués ni vidéo ; en cas d'échec, le widget soumet sans capture plutôt qu'une capture corrompue |
| Plancher de vie privée | Les valeurs saisies ne sont jamais capturées, seulement leur longueur ; un élément portant l'attribut de masquage ne produit aucun chemin |
| Honnêteté | Le code écrit lui-même que ce n'est pas un rejoueur complet de DOM, tout en gardant une enveloppe d'événements compatible |
| Statut | 🟢 Livré |
| Preuve | frontend/packages/feedback-widget/src/screenshot.ts, src/recorder.ts |
#Fiche F6 — Portail client frontend/client-portal
| Rubrique | Détail |
|---|---|
| Rôle | La surface de travail unique des équipes clientes |
| Volume réel | 27 routes utilisateur plus la page d'erreur, environ 39 900 lignes de code |
| Architecture | Export statique complet, sans rendu serveur : les routes dynamiques passent par une sentinelle réécrite côté serveur, l'identifiant réel étant lu côté navigateur |
| Navigation | 15 destinations en trois sections plus un pied de rail ; une seule est protégée par une capacité |
| Espace de travail projet | 11 vues canoniques, verrouillées par un test : spécification, graphe, tableaux, configuration, opérations d'agents, tests, revue, documentation, artefacts, livraison, personnel IA |
| Internationalisation | Français par défaut, anglais de plein droit |
| Authentification | Code d'autorisation avec preuve de clé, sans secret dans le navigateur |
| Limites connues | Le nom affiché est encore le nom de code interne ; un libellé français concurrent désigne la vue de personnel virtuel |
| Statut | 🟢 Livré — en ligne sur les trois environnements |
| Preuve | frontend/client-portal/src/lib/workspace/views.ts, src/components/shell/nav.tsx |
#Fiche F7 — Portail d'administration frontend/admin-portal
| Rubrique | Détail |
|---|---|
| Rôle | Le plan de contrôle de l'exploitant de la plateforme |
| Volume réel | 16 destinations, verrouillées par un test ; 3 rôles plateforme croisés avec 16 capacités ; 841 clés de traduction strictement à parité |
| Ce que l'exploitant peut faire | Lire la santé des services et le catalogue d'indicateurs ; superviser la flotte et interrompre un run ; créer un locataire ; gérer les utilisateurs et leurs rôles ; instruire une revue de gouvernance avec blocage anti-auto-approbation ; gérer les budgets et les fenêtres de quota ; vérifier la chaîne d'audit et générer un rapport Loi 25 ; gérer les drapeaux, les modèles, les adaptateurs, les garde-fous et les politiques d'exécution ; administrer le registre de compétences, d'outils et d'invites ; lire le registre central d'agents ; superviser le personnel virtuel ; paramétrer les rôles IA et leur plafond d'autonomie ; piloter la démonstration |
| Limites connues | La clé de traduction de la destination Personnel IA est absente en français et en anglais ; le tableau du manifeste de démonstration est codé en dur à vide ; le compagnon conversationnel n'est raccordé à aucun modèle, ce que l'interface indique explicitement ; le flux d'activité est un sondage, pas un flux serveur ; la latence de santé affiche toujours zéro en mode passerelle |
| Statut | 🟢 Livré — en ligne sur les trois environnements |
| Preuve | frontend/admin-portal/src/components/nav.tsx, src/lib/rbac.ts |
9. Synthèse par statut
#9.1 Décompte
| Statut | Nombre de fiches | Part |
|---|---|---|
| 🟢 Livré | 39 | 81 % |
| 🟡 En cours | 9 | 19 % |
| ⚪ Planifié | 0 fiche entière — mais des capacités planifiées à l'intérieur de fiches livrées | — |
| 🔴 Bloqué | 0 fiche entière — un blocage identifié au niveau capacité | — |
#9.2 Les neuf fiches « En cours » et ce qui manque exactement
| Fiche | Ce qui manque |
|---|---|
extension-registry-service |
Activation des deux drapeaux maîtres dans les manifestes de déploiement |
agent-runtime-service |
Bascule de l'exécuteur vers l'isolation dure, et versionnement du manifeste de politique réseau |
integration-sync-service |
Activation de l'écriture vers la spécification et des surfaces de lancement |
demo-orchestrator-service |
Activation du drapeau du module de démonstration |
chat-service |
Raccordement à un orchestrateur existant, et authentification |
mcp-gateway |
Manifestes Kubernetes, et gouvernance des plans hérités |
mcp-servers |
Implémentation du protocole réel, tests, isolation par locataire, amonts vivants |
packages/skills/global |
Un mécanisme de chargement, et deux exécutants manquants |
| Les six agents de flotte (statut de raccordement) | Un appelant réel de leur route d'exécution, et l'activation de la gouvernance |
10. Ce qui n'existe pas, dit explicitement
Cette section existe parce qu'un inventaire qui ne dit pas ses trous n'est pas un inventaire.
| # | Affirmation qu'on pourrait croire | Réalité vérifiée |
|---|---|---|
| 1 | « Un service de passerelle de modèles maison, port 4131 » | Ce répertoire n'existe pas dans le dépôt. Il n'est référencé que par une adresse dans deux configurations. Le chemin réel est un proxy LiteLLM partagé, hébergé hors de ce dépôt |
| 2 | « Les serveurs MCP sont en Node.js, seule exception à la règle Python » | Faux. Les cinq serveurs sont en Python. Aucun fichier TypeScript ni JavaScript n'existe dans ce répertoire |
| 3 | « Le protocole MCP est implémenté » | Non. C'est un contrat HTTP maison inspiré de MCP |
| 4 | « Un moteur de graphe natif porte le graphe de dépendances » | Non. C'est PostgreSQL, derrière une couture prévue pour un tel moteur |
| 5 | « La rétro-ingénierie comprend plusieurs langages » | Non. Seul Python est analysé par arbre syntaxique. Six autres langages sont détectés et déclarés non supportés |
| 6 | « Il existe une carte de chaleur de couverture côté service » | Non. Il existe une surface de couverture ; le rendu appartient au portail |
| 7 | « Il existe un point d'accès d'organigramme » | Non. Les colonnes hiérarchiques existent ; l'arbre est reconstruit par l'appelant |
| 8 | « Le service de cycle de vie porte une entité défaut » | Non. Seulement une référence sur l'incident. L'entité défaut vit dans le service d'observabilité |
| 9 | « Il existe un service de facturation dédié, port 4110 » | Non. Le port 4110 est celui de la fabrique de données de test |
| 10 | « Il existe un service de crédits dédié, port 4130 » | Non. Le port 4130 est celui du service de retours |
| 11 | « Les agents de la flotte sont appelables depuis l'extérieur » | Non. Aucun n'est enregistré à la passerelle. Leur route d'exécution n'a aucun appelant dans le dépôt |
| 12 | « Le portail d'administration a un compagnon IA » | Non. Le composant est un navigateur déterministe par correspondance approximative, et l'interface le dit |
| 13 | « Un troisième portail “business” existe » | Non. « Business » est une persona à l'intérieur du portail client |
| 14 | « Une application mobile existe » | Non. Aucun code mobile n'existe dans le dépôt |
KySpectra — Plateforme agentique SDD/SDLC · par Kyrieva
Documentation : kyspectradoc.kyrieva.com ·
Dossier de lancement : Strategielancement/
Document interne de pré-lancement — version 1.0 du 2026-08-17. Les données marquées
« [Gabarit : … ] » doivent être renseignées ou revalidées avant diffusion externe.