Aller au contenu principal

Marketplace de packs complets

Version anglaise : ../../en/guides/marketplace.md

Le Marketplace distribue des packs métiers complets par tenant et par environnement. Un pack est signé, porte son SBOM, son analyse de vulnérabilités, ses rapports de tests et d'évaluations, et n'est installé qu'après un contrôle préalable et une approbation humaine. Les permissions demandées par un pack ne sont jamais celles qu'il obtient : un administrateur accorde un sous-ensemble et la plateforme n'applique que l'ensemble accordé.

Prérequis​

BesoinCommandeRemarques
Chaîne OCItools/oci/fetch.shoras 1.3.6, cosign 2.6.5, zot 2.1.22 (minimal), versions officielles, épinglées, sha256 vérifié, dans /tmp/toolchains
Outils de politique/tmp/toolchains/opa, /tmp/toolchains/fga, /tmp/toolchains/trivyopa 1.21.4, fga 0.8.2, trivy 0.76.1, récupérés par tools/oci/fetch.sh (épinglés, sha256 vérifié) ; opa test, fga model test, trivy fs (base hors ligne, téléchargée une fois par trivy image --download-db-only)
Contrôles d'observabilité/tmp/toolchains/promtoolpromtool 3.15.1, récupéré par tools/oci/fetch.sh (épinglé, sha256 vérifié)
Interpréteur des packspacks/bootstrap.sh/tmp/toolchains/packs-venv, dépendances de packs/requirements.lock installées avec --require-hashes (SDK Python MCP 2.3.0, MIT)
SDK et CLIpip install -e 'sdks/python[dev]'commande enterprise-ai

Un outil absent arrête la commande avec l'indication de récupération (cosign not found: run tools/oci/fetch.sh ...) ; rien n'est ignoré en silence.

Structure d'un pack​

plugin.yaml (manifeste Plugin, spec.format: pack), README.md, LICENSE, CHANGELOG.md, et les dossiers agents, subagents, skills/<nom>/SKILL.md, prompts, rules, policies/opa (avec _test.rego), policies/openfga (modèle et tests *.fga.yaml), mcp/servers, mcp/tools, mcp/schemas, connectors, workflows, rag, evaluations (configuration promptfoo, JSONL Ragas), security, observability/alerts (règles Prometheus et SLO), tests/unit, tests/integration, tests/authz, tests/security, docs/en, docs/fr, examples. Les dossiers optionnels (subagents, rag, workflows, mcp/*, connectors, examples, policies/openfga) ne peuvent être omis qu'avec une raison dans spec.layout.omitted. Un pack ne livre aucun tableau de bord (ADR-0169) : un dossier dashboards sous observability est refusé par plugin validate et par le contrôle schema ; les tableaux de bord de la plateforme sont dans le Navin Manager (machines, services) et le portail (agents, passerelle LLM, FinOps, SLO, sécurité).

Le manifeste déclare license, compatibility {platform, sdk, runtimes}, dependencies, requestedPermissions [{scope, reason, sensitive, classification}], dataProtection, approvals {install, sensitive, production}, docs {en, fr}, evaluations et tests. signedArtifact est rempli par la construction et la signature dans le descripteur publié.

Développer, construire, signer, publier​

enterprise-ai plugin create packs/my-legal --domain legal --name my-legal --lock packs/requirements.lock
enterprise-ai plugin validate packs/my-legal
enterprise-ai plugin build packs/my-legal --out /tmp/my-legal-dist
COSIGN_PASSWORD=... enterprise-ai plugin sign packs/my-legal --out /tmp/my-legal-dist --key cosign.key --signer acme
enterprise-ai plugin publish packs/my-legal --out /tmp/my-legal-dist --key cosign.key \
--oci <harbor-host>/packs/my-legal:1.0.0
  • build : archive tar gzip reproductible (entrées triées, propriétaire et date fixes SOURCE_DATE_EPOCH, 0 par défaut) : deux constructions donnent la même empreinte sha256. <nom>-<version>.spdx.json est un document SPDX 2.3 qui liste chaque fichier avec son SHA-256 et les dépendances épinglées de requirements.txt.
  • sign : cosign sign-blob --key (paire de clés hors ligne, --tlog-upload=false) sur l'empreinte et sur le SHA-256 de chaque SKILL.md ; écrit <nom>-<version>.pack.json.
  • publish : lance les suites pytest (unit, integration, authz, security) avec l'interpréteur des packs, opa test, fga model test, promtool check rules, les évaluations promptfoo et Ragas, trivy fs, pousse l'archive, le SBOM et le descripteur en un seul artefact OCI avec ORAS (type application/vnd.enterprise-ai.pack.v1), signe l'empreinte du manifeste avec cosign sign --key, puis envoie POST /v1/marketplace/packages (ou écrit le corps avec --body-out).

Enregistrez d'abord la clé publique de l'éditeur (tenant_admin ou security_officer) :

POST /v1/marketplace/publishers {"name": "acme", "public_key": "<contenu de cosign.pub>"}

Contrôles de publication​

La publication est refusée (422 publication_gate_failed, chaque contrôle dans details.gates) dès qu'un contrôle échoue ou que son entrée manque : schema (manifeste, structure, chaque manifeste d'agent, d'outil et de connecteur), signature (empreinte du pack et chaque skill avec une clé d'éditeur active), sbom (chaque fichier et sa somme), vulnerability_scan (rapport Trivy lié à l'empreinte, aucune vulnérabilité CRITICAL ou HIGH, aucun secret), tests, evaluations (score au-dessus du seuil), licence (MIT, Apache-2.0, ou une autre licence déclarée dans licenseDeclaration avec une raison), permissions (aucun droit dangereux : jokers, secrets, platform, tenants, keys, audit, policies, authz, identity, billing, licenses, kill-switch, ou une action admin, impersonate, bypass, delete-all ; chaque droit utilisé par un agent, une skill ou un outil est demandé), docs, secrets, provenance (attestation in-toto Statement v1 au prédicat SLSA provenance v1 dans provenance: {statement, signature}, sujet = empreinte du pack, SBOM et rapports liés comme sous-produits, signée par l'éditeur du pack ; enterprise-ai plugin publish --key la produit), privacy (G6 : détection et masquage des données personnelles quand le pack en traite, DLP, résidence, externalExportDefault: deny), security (signedArtifactRequired, sandboxRequired, dynamicAuthorization, auditRequired à true), approvals (requiredFor couvre install, upgrade, sensitivePermissions, production et resume), configuration (configSchema est un JSON Schema d'objet), resilience (G9 : délai borné de chaque outil, outil à effet de bord idempotent avec une clé d'idempotence, workflow qui s'arrête ou compense en cas d'échec). Le manifeste porte aussi namespace, category, publisher et displayName {en, fr}, enregistrés dans le catalogue, et testFlags (sdkConformance, authorization, security) : la conformité SDK de chaque objet est un résultat du rapport de tests. Un pack signé qui demande un droit dangereux est refusé. Une version publiée est immuable (409 marketplace_version_exists).

Production : POST /v1/marketplace/packages/{name}/versions/{version}/production vérifie les contrôles enregistrés, la signature courante (une clé révoquée échoue) et l'empreinte OCI, puis ouvre une approbation à quatre yeux. Installer en prod demande une version au statut production.

Installer par tenant et par environnement​

enterprise-ai plugin install hr --version 1.0.0 --env dev --grant hr.employees.read --grant hr.leave.read \
--secret-ref hr-hris=openbao://tenants/acme/hr/hris
  1. Contrôle préalable : environnement, statut de la version, compatibilité plateforme, dépendances installées dans le même environnement, empreinte et signature vérifiées à nouveau, permissions accordées demandées par le pack et sûres, références de secrets (openbao:// ou env://) des connecteurs, aucun conflit de nom. Essai à blanc : POST /v1/marketplace/preflight.
  2. Approbation par le service d'approbations (marketplace.install) : quorum de approvals.install, au moins deux approbateurs distincts quand une permission accordée est sensible (déclarée sensible, action d'écriture, de paiement, d'exécution, d'approbation, de virement ou de suppression, données restreintes ou secrètes) ou quand l'environnement est prod. Le demandeur n'approuve jamais (403 separation_of_duties).
  3. Application (POST /v1/marketplace/installations/{id}/apply) : les objets sont créés par les registres existants et nommés <objet>-<environnement> : agents (droits accordés seulement), skills (signature vérifiée par le Skill Registry), outils (statut blocked quand leurs droits ne sont pas accordés), connecteurs (références de secrets), prompts, politiques OPA (en draft : activer une politique du tenant reste une action explicite), serveurs MCP enregistrés dans la passerelle MCP quand config.mcp_servers.<nom>.url est donnée, une base de connaissances par modèle RAG. Les règles, modèles OpenFGA, serveurs MCP, workflows, modèles RAG, alertes et migrations du pack sont inscrits dans assets (eai.marketplace_assets) avec leur empreinte et leur statut : active, blocked (workflow dont un outil n'est pas accordé), pending_endpoint (serveur MCP sans adresse), suspended. La configuration est validée contre le configSchema du pack (422 config_invalid).
  4. Tests de fumée : chaque objet est enregistré, les agents n'ont que les droits accordés, les skills accordées se chargent pour leurs agents, les outils hors périmètre sont bloqués, chaque serveur MCP enregistré répond à un vrai initialize puis la liste des outils MCP (méthode tools list) avec tous les outils déclarés, chaque workflow actif n'utilise que des outils approuvés. Un échec annule la modification (422 smoke_failed).

À l'usage, une permission demandée mais non accordée est refusée par le Skill Loader (403 skill_permission_denied), par la passerelle d'outils (403 tool_blocked) et par POST /v1/marketplace/installations/{id}/authorize, que les serveurs MCP des packs appellent avant chaque outil (403 permission_not_granted).

Mise à niveau, retour arrière, désinstallation​

  • Mise à niveau : POST /v1/marketplace/installations/{id}/upgrade {version, approved_permissions} (contrôle préalable et approbation, puis /apply) ; la version et les droits précédents sont conservés.
  • Retour arrière : POST /v1/marketplace/installations/{id}/rollback réinstalle la version précédente avec ses droits précédents et retire ce que la nouvelle version avait ajouté.
  • Désinstallation : POST /v1/marketplace/installations/{id}/uninstall retire chaque objet créé par l'installation, avec ses relations. Historique : GET /v1/marketplace/installations/{id}/events.

Kill switch, suspension et supervision​

  • Suspendre une installation ou certaines de ses capacités : POST /v1/marketplace/installations/{id}/status {status: suspended, permissions?: [...], reason}. L'effet est immédiat : avec permissions, seules ces permissions sont refusées (403 permission_suspended) et leurs outils bloqués ; sans, tous les outils sont bloqués, les agents suspendus, les serveurs MCP désactivés et les contenus suspendus (403 installation_suspended).
  • Reprendre : {status: installed} ouvre une approbation marketplace.resume (quorum 2, jamais le demandeur, 202), puis le même appel avec l'approval_id approuvé rétablit l'état accordé. Aucun contournement : sans approbation approuvée la reprise est refusée.
  • Kill switch d'un paquet : POST /v1/marketplace/packages/{name}/status {status: suspended} suspend d'un coup toutes les installations du tenant et refuse installations, mises à niveau, publications, mises en production et reprises (409 package_suspended) ; {status: active} le lève avec une approbation marketplace.package.resume.
  • Supervision : GET /v1/marketplace/installations/{id}/supervision agrège l'activité (appels d'outils, exécutions, refus), la qualité (évaluations, tests de fumée, taux de réussite), les coûts des exécutions et les incidents qui nomment les objets créés.
  • Une permission qui envoie des données du pack hors de la plateforme (action export, external, share) est refusée à l'usage (403 external_export_denied) car externalExportDefault vaut deny.

Dépôt local pour un site sans accès réseau​

  1. Côté connecté : enterprise-ai plugin publish &lt;pack&gt; --key cosign.key --oci &lt;registre&gt;/packs/&lt;pack&gt; --body-out &lt;pack&gt;-&lt;version&gt;.pack-body.json produit le corps de publication complet (archive, signature, SBOM, rapports, provenance SLSA). Copier l'artefact et sa signature cosign dans une disposition OCI : oras cp <registre>/packs/<pack>@<empreinte> --to-oci-layout transfer/<pack>:<version> et oras cp <registre>/packs/<pack>:sha256-<hex>.sig --to-oci-layout transfer/<pack>:sha256-<hex>.sig.
  2. Transporter le dossier transfer/ et le fichier .pack-body.json sur le support autorisé.
  3. Côté isolé : pousser la disposition dans le registre local (zot ou Harbor du client) avec oras cp --from-oci-layout transfer/<pack>:<version> <miroir>/packs/<pack>:<version> (et la signature), vérifier que l'empreinte est identique (oras manifest fetch --descriptor) et la signature (cosign verify --key cosign.pub --insecure-ignore-tlog=true), puis importer le corps avec client.marketplace.import_publication(corps, oci_ref="&lt;miroir&gt;/packs/&lt;pack&gt;:&lt;version&gt;") (SDK Python). Le Control Plane revérifie tous les contrôles hors ligne avec la clé d'éditeur enregistrée.

Chaque route prend d'abord une décision de politique (actions marketplace.*) et écrit un événement d'audit, refus compris.

Packs de référence et modèles​

PackContenu
packs/hrannuaire aux coordonnées masquées, soldes et politique de congés, demande de congé idempotente, bulletin personnel seulement ; SIRH simulé sur des salariés fictifs
packs/financefactures, soldes du grand livre, paiement exécuté une seule fois (clé d'idempotence, pas de double paiement, reprises concurrentes), rapprochement ; ERP simulé sur un grand livre fictif
packs/templates/<domaine>banking, risk-compliance, legal, it, cybersecurity, sales-crm, marketing, procurement, support, document-intelligence

Chaque connecteur a une interface d'adaptateur, une implémentation simulée sur des données fictives et une implémentation qui passe par le Connector Broker de la plateforme : aucun système réel n'est contacté tant que le tenant n'a pas configuré la référence de secret et la règle d'egress.

Procédures dans le portail​

Les écrans sont Marketplace > Catalogue des packs (onglets Paquets, Contrôle préalable, Éditeurs de confiance), Marketplace > Installations et Marketplace > Pipeline de changement (portal/src/screens/kit-platform.tsx).

  1. Enregistrer la clé de l'éditeur. Sans clé d'éditeur active, le contrôle signature refuse chaque pack de cet éditeur.

    Écran : Catalogue des packs > Éditeurs de confiance > Ajouter un éditeur, collez le contenu de cosign.pub. API : POST /v1/marketplace/publishers.

    Résultat attendu : l'éditeur est listé comme actif.

    En cas d'échec : 403 forbidden signale que vous n'êtes ni tenant_admin ni security_officer.

  2. Publier le pack. La publication passe tous les contrôles : un pack présent au catalogue est complet et signé.

    enterprise-ai plugin publish packs/my-legal --out /tmp/my-legal-dist --key cosign.key --oci <harbor-host>/packs/my-legal:1.0.0

    Résultat attendu : la version apparaît dans Catalogue des packs > Paquets avec son SBOM et ses rapports (GET /v1/marketplace/packages/{name}/versions/{version}).

    En cas d'échec : 422 publication_gate_failed liste chaque contrôle en échec dans details.gates ; 409 marketplace_version_exists signale une version déjà publiée (publiez une nouvelle version).

  3. Lancer le contrôle préalable. Il montre, avant tout changement, ce que le pack demande et ce dont l'installation a besoin.

    Écran : Catalogue des packs > Contrôle préalable. API : POST /v1/marketplace/preflight.

    Résultat attendu : les permissions demandées, la configuration requise et chaque contrôle préalable réussi.

    En cas d'échec : chaque contrôle en échec est nommé ; corrigez l'environnement, les dépendances ou les références de secrets.

  4. Installer le pack. L'assistant accorde un sous-ensemble des permissions demandées et ouvre l'approbation.

    Écran : Marketplace > Installations > Installer un pack : paquet, version, environnement, permissions accordées, configuration et références de secrets. CLI : la commande enterprise-ai plugin install ci-dessus.

    Résultat attendu : une installation au statut pending_approval.

    En cas d'échec : 409 package_suspended signale le kill switch du paquet actif ; 409 marketplace_object_conflict signale un objet du même nom déjà présent dans l'environnement.

  5. Faire approuver l'installation. D'autres personnes décident dans Agents > Approbations ; le demandeur n'approuve jamais.

    Résultat attendu : l'approbation atteint son quorum.

    En cas d'échec : 403 separation_of_duties quand le demandeur tente d'approuver.

  6. Appliquer. L'application crée les objets, puis lance les tests de fumée.

    Écran : Installations, action Appliquer sur l'installation. API : POST /v1/marketplace/installations/{id}/apply.

    Résultat attendu : statut installed ; les actions events et supervision montrent l'historique et l'activité.

    En cas d'échec : 422 config_invalid (configuration hors du configSchema) ou 422 smoke_failed (la modification est annulée).

  7. Suivre un changement d'un objet de pack. Le pipeline de changement fait avancer une nouvelle version étape par étape, avec ses preuves : brouillon, test, revue de sécurité, approbation métier, préproduction, production, surveillance.

    Écran : Marketplace > Pipeline de changement > Nouveau changement, puis faites-le avancer avec ses preuves.

    Résultat attendu : le changement atteint production, puis monitoring.

    En cas d'échec : une étape qui exige une approbation attend son approval_id ; rejetez le changement avec une raison pour l'arrêter.

Tests d'acceptation​

cd services/control-plane && .venv/bin/python -m pytest -q tests/test_marketplace.py tests/test_marketplace_governance.py
cd sdks/python && .venv/bin/python -m pytest -q tests/test_packs.py

Limites​

  • Les signatures utilisent des paires de clés cosign hors ligne, sans journal de transparence ; la signature sans clé n'est pas utilisée.
  • Les configurations promptfoo s'exécutent avec des fournisseurs exec: et des assertions déterministes ; les métriques jugées par un modèle s'exécutent dans le service d'évaluation de la plateforme. Les jeux Ragas sont notés hors ligne avec le rappel du contexte.
  • Les règles d'alerte sont vérifiées par promtool check rules à la publication (dans le contrôle tests) ; les tests ne les chargent pas dans un Prometheus actif.

Dépannage​

StatutCodeCauseCorrection
422publication_gate_failedun contrôle a échoué ou son entrée manquelisez details.gates, corrigez le pack, republiez
409marketplace_version_existsla version est déjà publiéemontez la version dans plugin.yaml
422config_invalidconfiguration hors du configSchema du packcorrigez la configuration
422smoke_failedun test de fumée a échoué après l'application ; la modification est annuléelisez le test en échec, corrigez les droits accordés ou la configuration
403separation_of_dutiesle demandeur a tenté d'approuverfaites décider d'autres approbateurs
409package_suspendedkill switch du paquet actiflevez-le avec une approbation marketplace.package.resume
409marketplace_object_conflictun objet du même nom existe déjàrenommez ou retirez l'objet existant
403permission_not_granted, tool_blocked, skill_permission_deniedune permission demandée mais non accordéemettez à niveau l'installation avec la permission dans approved_permissions
403permission_suspended, installation_suspendedinstallation ou permission suspenduereprenez avec une approbation marketplace.resume approuvée
403external_export_deniedune permission qui exporte des données du packgardez les données dans la plateforme

Étapes suivantes​