Search by

sentinelo / agent-composer

sentinelo-webntricks

Agent de maintenance Sentinelo pour les applications basées sur Composer — Symfony, Sylius, Laravel.

v1.1.0 2026-10-01 17:23 UTC

This package is auto-updated.

Last update: 2026-10-01 17:30:22 UTC


README

L'agent Sentinelo pour les applications basées sur Composer : Symfony, Sylius, Laravel.

Il partage son cœur métier avec l'agent WordPress (sentinelo/agent-core) : mêmes routes, mêmes payloads, même barème de sécurité. Ce qui change, c'est le périmètre — et ce périmètre est un choix, pas une limite qu'on finira par lever.

Ce que fait l'agent

Sauvegarde base + code + médias, archivés, chiffrés avant de quitter la machine, envoyés vers le stockage objet, avec rétention GFS
Restauration sauvegarde de sécurité préalable, vérification SHA-256 avant d'écrire quoi que ce soit, site hors ligne pendant l'opération
Scan de sécurité 9 checks notés + l'inventaire des paquets pour la corrélation CVE côté plateforme
Heartbeat présence, version de l'agent, version du framework

Ce qu'il ne fait pas, et pourquoi

Il n'applique aucune mise à jour. composer update + migrations + cache:clear n'est pas atomique : dès que vendor/ change, l'application qui tourne est un mélange de deux versions, et une migration qui échoue n'a pas de retour arrière. Cela suppose aussi un vendor/ inscriptible, que la plupart des déploiements de production refusent — et là où il l'est, y écrire fait diverger le code exécuté de l'artefact construit par le pipeline du client : leur prochain déploiement efface notre modification sans que personne ne s'en aperçoive.

L'agent lève donc Port\UpdatesNotSupported, le backend le sait par SitePlatform::supportsPackageUpdates(), et l'interface ne propose pas le bouton. Sur ces cibles, la valeur du produit est la surveillance, la sauvegarde, la sécurité et le rapport.

Il ne se met pas à jour lui-même. Distribué en paquet Composer privé, pas en archive auto-installable. Conséquence assumée : on ne peut pas pousser un correctif à la flotte, seulement le signaler. C'est compensé par meta.plugin_version, présent sur chaque réponse : la plateforme sait quelle version répond sur chaque site et peut lister les agents périmés.

Il n'a pas d'inventaire d'extensions au sens WordPress. Il n'y a ni marketplace ni activation par paquet : la source est composer.lock. Et latest_version y vaut toujours null, ce qui signifie INCONNU, jamais « à jour » — la version installable dépend des contraintes du projet, pas de la dernière version publiée. Confondre les deux laisserait croire que la flotte est à jour alors que personne n'a vérifié.

Architecture

src/
  Platform/      quelle application, quelle disposition de fichiers, quels paramètres de base
  Adapter/       les ports d'AgentCore implémentés pour un projet Composer
  Repository/    les tables de l'agent, en PDO
  Scanner/       collecte des faits ; la NOTATION vit dans AgentCore
  Enrolment/     la poignée de main qui donne sa clé au site — sans framework
  Symfony/       bundle, contrôleur, abonnement maintenance, commande console
  Laravel/       service provider, contrôleur, middleware, commande artisan

L'enveloppe, l'authentification et le routeur ne sont pas ici : ils vivent au cœur partagé (AgentCore\Http\), et c'est ce qui fait que les trois agents répondent la même chose.

Deux invariants portent tout le reste :

  1. Le routeur ne connaît aucun framework. Symfony/ et Laravel/ ne font que traduire une requête et retraduire une réponse. C'est ce qui permet de tester la totalité de la surface HTTP sans booter quoi que ce soit — et d'ajouter une quatrième cible sans toucher à la logique.
  2. L'agent se construit depuis la racine du projet et son .env, pas depuis le conteneur de l'application. Deux des moments où il compte le plus sont des moments où le framework est indisponible : un cron sur un site dont le conteneur compilé est cassé par un mauvais déploiement, et c'est précisément là qu'on veut une sauvegarde.

Barème de sécurité

Les identifiants et les poids viennent de AgentCore\Scanner\CheckCatalogue, partagé avec tous les agents. Cette plateforme déclare le sous-ensemble qu'elle sait honnêtement exécuter (ComposerScanProfile), et ScoreCalculator normalise sur ce qui a réellement tourné : 78/100 veut dire la même chose ici que sur un site WordPress, ce que le rapport client mensuel suppose en les affichant côte à côte.

Un check qu'on ne peut pas faire est omis, jamais simulé. Un stub qui « passe » distribue des points gratuits et fait passer cette plateforme pour plus sûre que celle qui a réellement fait la vérification. Les omissions et leur raison sont documentées dans ComposerScanProfile et épinglées par un test.

Installation

Voir docs/AGENT-DISTRIBUTION.md — dépôt Composer privé, authentification, montage du bundle ou du service provider, ligne de cron, et enrôlement.

L'enrôlement est le geste qui rend l'agent utile : sans clé, Authenticator refuse tout le monde par 403 NOT_CONFIGURED, et toute la chaîne (sauvegarde, restauration, scan, audit, rapport) est authentifiée par cette clé. Deux chemins, un seul travail :

php bin/console sentinelo:enroll <clé>   # ou : php artisan sentinelo:enroll <clé>
SENTINELO_API_KEY=<clé>                  # adoptée par le prochain passage de cron

La clé, le site_uuid et le webhook_secret rendus par la plateforme sont scellés dans la table de l'agent, chiffrés au repos — jamais dans un fichier du projet, qui est un dépôt git et dont l'image est reconstruite à chaque déploiement.

Tests

docker run --rm -u $(id -u):$(id -g) -e HOME=/tmp -v $PWD:/repo -w /repo/agent-composer \
    composer:2 php vendor/bin/phpunit --no-coverage

Après toute modification de agents/core, lancer make agent-core-sync : le cœur est installé en copie dans vendor/, et sans resynchronisation la suite teste l'ancienne version — un vert trompeur. make agent-core-check échoue si les copies ont divergé.