# GardenArena API Pro — pilote v1 Statut : pilote privé sur invitation, provisionnement opérateur. Pas de paiement, de tarif public, de SLA ou de promesse d'autonomie agronomique. Mise à jour du 13 septembre 2026 : le pilote privé est activé sur GardenArena. Les nouveaux projets créés en CLI expirent après 30 jours par défaut. Le plafond reste mensuel UTC, sans report : ce n'est pas un crédit glissant de 500 unités pour toute la durée du contrat. Aucun abonnement payant n'est activé. ## Ce que le client peut intégrer Une stratégie GardenScript → un calcul borné Rust → un résultat expliqué → un export rejouable. La ferme v4 et la comparaison partent d'un journal complet, pas d'un état inventé. Le scénario « La semaine d'après », à J96, est inclus. Le catalogue contient les six canaux, les capteurs et les trois programmes exemples du moteur existant. La comparaison n'invente pas de vainqueur global. Ce pilote n'inclut ni API LLM, ni moteur de règles Python, ni nouvelle espèce, ni météo réelle, ni recherche autonome, ni service de conseil agricole. Les artefacts peuvent être importés explicitement dans `/ferme` (politique) ou `/ferme#farm-compare` (comparaison). La 3D existante peut alors les illustrer. Pour la mission J96, importer la comparaison dans `/ferme/la-semaine-dapres#farm-compare` : une ferme ordinaire J0 peut lire le rapport, mais son garde-fou interdit d'y adopter une branche de base J96. L'adoption exige la même ferme de départ ; la partie habituelle reste séparée. Il n'y a pas de lien public secretless vers un replay privé ni de widget 3D en marque blanche dans ce lot. Les droits des assets 3D ne sont pas assimilés à la licence MIT du noyau. ## Contrat HTTP, serveur-à-serveur Préfixe : `/api/pro/v1`. Toutes les réponses sont `no-store`, non indexables. Pas de paramètres dans l'URL, pas de clé en cookie, pas de CORS tiers. Description OpenAPI 3.1 : `GET /api/pro/v1/schema.json`. Les schémas décrivent les bornes de transport ; les commandes de jeu restent validées par Rust. | Route | Droit | Fonction | |---|---|---| | `GET /catalog` | public | Contrat, release exacte, programmes et mission | | `POST /jobs/validate` | run | Validation GardenScript, rapport `valid` + diagnostics | | `POST /jobs/run` | run | Une politique depuis un journal ferme v4 | | `POST /jobs/compare` | run | Deux politiques depuis la même base | | `GET /jobs/{id}` | read | État du travail, consommation, empreintes | | `GET /jobs/{id}/artifact` | read | Export JSON, en-tête `X-Artifact-SHA256` | | `GET /usage` | read | Quota mensuel UTC et 20 derniers travaux du projet | | `DELETE /jobs/{id}` | run | Annuler un travail en file ou supprimer un artefact terminé | Les routes privées attendent `Authorization: Bearer `. Les droits sont liés au projet : deux clés `read` du même projet voient ses mêmes résultats. Créez des projets distincts pour des clients qui ne doivent rien partager. L'API ne reconnaît pas les cookies du jeu ou la session Hub comme clé client. La console `/api-pro` garde la clé en mémoire de l'onglet, sans localStorage. Elle affiche l'échéance effective en UTC. Projet et clé peuvent avoir leur propre échéance ; la première l'emporte. Une rotation de clé ne prolonge pas le projet. À la seconde d'expiration, lecture et écriture sont refusées, même si le worker est arrêté. Les travaux encore en file sont annulés sans débit par le worker ; un calcul déjà commencé peut finir et consommer ses unités, mais une clé expirée ne peut plus télécharger son résultat. Exporter avant la fin d'accès, même si les 24 heures de l'artefact ne sont pas écoulées. ### Premier essai Le programme exemple `scripts/api_pro_client.py` effectue cette séquence avec la bibliothèque standard Python, sans SDK payant : catalogue → demande de comparaison → polling → contrôle SHA-256 → fichier d'export privé. ```bash python scripts/api_pro_client.py \ --base https://gardenarena.io \ --credentials /chemin/prive/client.json \ --idempotency atelier-semaine-dapres-0001 \ --out /chemin/prive/comparaison.json ``` Ne passez pas une clé brute dans les arguments du shell. Le fichier de clés est remis au client par un canal choisi par l'opérateur, jamais publié dans le dépôt, le document du challenge ou une URL. Le client ne suit pas les redirections, afin de ne pas transporter une clé vers un autre domaine. Le client s'identifie avec `User-Agent: GardenArena-API-Pro-Client/1.0` : le front du domaine refuse actuellement le User-Agent Python générique. Corps `validate` : `{"source":"… GardenScript 0.6 farm.v1 …"}`. Corps `run` : `request`, `source`, `max_days`, `budget_credits`. Corps `compare` : `request`, `source_a`, `source_b`, `max_days`, `budget_credits`. Le journal de la mission vient de `catalog.mission.request` et ses sources de `catalog.mission.sources.a` et `.b`. Pour cette mission : 7 jours et 540 crédits de jeu par branche, pas des euros. Rust vérifie les règles et les commandes. Corps strict de 64 Kio maximum après canonicalisation, source ASCII de 16 Kio maximum chacune, journal de 512 commandes maximum, période de 1–7 jours, budget de 0–1 000 crédits de jeu. Aucun champ URL, binaire, code libre ou outil système n'est accepté. Le scénario est `farm-harvest-365-v4` uniquement. `supported_scenarios` borne le pilote ; le sous-document `policy` reste le catalogue Rust exact (plus large), afin de vérifier son empreinte publiée. ### Idempotence et reprise Chaque POST exige une `Idempotency-Key` de 16–128 caractères `[A-Za-z0-9_-]`. Une demande admise retourne `202`, un identifiant aléatoire et `Location`. Répéter exactement la même demande dans le même projet renvoie le même travail (`200`), sans autre réservation ni exécution. Cela fonctionne après redémarrage et avec une autre clé du même projet. Un contenu/opération différent sous la même identité donne `409`. Une réponse réseau perdue ne justifie donc pas de générer une nouvelle identité. La trace d'idempotence reste 90 jours, y compris après expiration ou suppression du résultat. Après cette durée, la même clé peut à nouveau désigner un essai. Le corps canonique et l'opération identifient la demande ; l'identité de release est fixée lors de son admission. La reprise ne modifie pas cette release. Les états sont `queued`, `running`, `succeeded`, `failed`, `cancelled`, `deleted`. `succeeded` signifie qu'un résultat a été produit, pas que la stratégie gagne : un rapport `valid:false` et une mauvaise journée simulée sont des résultats. Une réponse `429` ou `503` expose une action/délai, ne supprime pas le brouillon et ne doit jamais être affichée comme une défaite de gestion. Un worker interrompu rend son travail `failed/worker_interrupted` au redémarrage, sans débit. Pas de relance automatique d'une exécution incertaine. Un nouveau calcul requiert une nouvelle identité explicite. Les travaux en file expirent après dix minutes. La suppression d'un calcul en cours retourne `409` : attendre sa fin. La révocation d'une clé annule ses travaux encore en file ; un calcul déjà commencé peut finir, mais la clé révoquée ne peut plus consulter le résultat. ### Capacité et consommation : aucune facturation activée Unité = capacité réservée, ni jeton LLM, ni euro, ni seconde CPU : - Validation : 1 unité. - Politique : nombre de jours demandé. - Comparaison : deux fois le nombre de jours demandé. Les unités sont réservées atomiquement avant mise en file et débitées seulement lorsqu'un résultat est persisté. Même débit si la simulation s'arrête tôt pour une conséquence de gestion. Le worker libère les unités sur erreur technique ou refus d'un run invalide. Les POST de validation terminés avec `valid:false` coûtent une unité : le rapport du compilateur constitue leur résultat. Une suppression après réussite n'annule pas l'usage déjà consommé. Le plafond de projet est réglé manuellement (500 unités/mois par défaut). Le plafond global initial est de 10 000 unités/mois. Mois UTC d'admission, sans report ; une réservation prise en fin de mois reste imputée à ce mois. Pas de dépassement automatique, pas de carte bancaire, pas de facture. Bornes supplémentaires : 120 requêtes/minute/projet, 60 nouveaux travaux admis par heure/projet même s'ils échouent, 2 000 admissions/jour au total ; file de 16 travaux, dont deux maximum par projet ; un seul calcul simultané. Les appels de polling doivent respecter `Retry-After`, typiquement trois secondes. Les artefacts occupent au plus 64 Mio par projet et 256 Mio au total (hors métadonnées SQLite et fichiers transitoires). Chaque travail en attente réserve ses 3 Mio de sortie maximum avant admission, pour ne pas découvrir la limite après calcul. Exporter puis supprimer permet de libérer cette capacité ; le compteur mensuel d'unités ne diminue pas. Le moteur dispose de 6 secondes CPU, 8 secondes murales, 512 Mio d'espace d'adressage et 3 Mio de sortie maximum, dans un processus de priorité réduite. Ce sont des limites de sécurité du pilote, pas un SLA de performance. Les exports de politique simple et validation sont limités à 1 Mio ; les comparaisons à 3 Mio, pour rester compatibles avec les importeurs du site. ### Confidentialité Clés : 256 bits aléatoires ; seules leurs empreintes SHA-256 sont stockées. La création écrit le secret une seule fois dans un nouveau fichier privé 0600. Le registre SQLite réside dans un dossier privé 0700, distinct de la base du jeu. Pas de journalisation des programmes ou clés par le worker. Les journaux nginx et proxies doivent également exclure Authorization et les corps de requêtes. Artefacts : disponibilité 24 heures après terminaison. L'accès refuse un fichier expiré immédiatement, même si le nettoyage n'a pas tourné. Le worker supprime les contenus expirés au plus toutes les 30 secondes lorsqu'il tourne. Si le worker est arrêté, exécuter `cleanup` régulièrement : l'inaccessibilité n'est pas une promesse d'effacement physique instantané. SQLite utilise secure_delete et le nettoyage demande un checkpoint WAL. Les sauvegardes sont à exclure ou à purger selon une politique compatible ; elles ne sont pas effacées par HTTP. La commande opérateur `backup` produit une copie privée de récupération des métadonnées, pas des programmes ni des artefacts. Les clés y sont révoquées et les projets désactivés. `restore` refuse un fichier destination déjà existant et n'active aucun accès : réconcilier l'activité postérieure au snapshot avant de remettre de nouvelles clés. Une sauvegarde ancienne ne reconstitue pas les demandes reçues après sa création ; elle n'est pas une garantie de reprise sans perte. Exporter les résultats reste nécessaire. Ces snapshots sont valables 24 h. Le dossier géré `recovery/` à côté du registre est purgé par le worker toutes les 30 secondes lorsqu'il tourne. Les dossiers opérateur alternatifs doivent être purgés avec `purge-backups`. Aucune copie automatique nouvelle n'est créée ; la sauvegarde est explicite. Les métadonnées de travaux de plus de 89 jours sont exclues du snapshot pour ne pas étendre leur conservation au-delà des 90 jours. L'expiration empêche la restauration, mais la suppression physique exige un worker actif ou la purge opérateur. Les programmes soumis sont supprimés du champ de file dès la fin du calcul ; les exports réussis peuvent les contenir jusqu'à expiration/suppression. Métadonnées (dates, opération, hashes, usage, erreurs techniques) : 90 jours. La liste des clients et des clés révoquées est conservée jusqu'à clôture opérateur du registre. Ne soumettez pas de secret personnel dans GardenScript. Le SHA-256 identifie des octets, pas l'identité d'une IA ni la vérité physique. Un export contient la preuve rejouable prévue par le moteur ; une capture ou carte sociale ne la remplace pas. Rien n'est publié automatiquement. ## Exploitation locale et activation Python 3.11+, Linux/WSL, `prlimit`, `nice`, binaire Rust compilé requis. Aucun nouveau paquet Python pour la couche Pro. Les dépendances web existantes suffisent. 1. Compiler/tester le noyau comme pour le site ; ne pas substituer une autre release en production sans préparation. `Cargo.toml` et `rust_engine/LICENSE` indiquent désormais MIT ; `publish=false` demeure inchangé. 2. Choisir `GARDENARENA_PRO_DB` hors des répertoires servis et sauvegardes publiques. 3. Provisionner un NOUVEAU registre avec `python -m api_pro init`. Cette commande refuse d'écraser un registre existant, vérifie les catalogues Rust et fige le SHA du binaire. Un changement de binaire fera échouer les calculs plutôt que changer silencieusement les résultats ; préparer un nouveau registre de release en phase pilote, exporter les anciens résultats avant bascule. 4. `python -m api_pro project "Atelier pilote" --units 500` renvoie l'identifiant. 5. `python -m api_pro key prj_… --out /chemin/prive/client.json` crée la clé. 6. Démarrer `python -m api_pro worker` séparément du serveur web. 7. Activer `GARDENARENA_PRO_ENABLED=1` dans le serveur web. Sans cette valeur, toutes les routes du pilote retournent 503 et le jeu gratuit fonctionne. `GARDENARENA_PRO_BINARY` peut sélectionner un binaire **opérateur**, jamais via HTTP. Web et worker doivent pointer sur le même registre local ; le pilote n'est pas conçu pour une base SQLite sur NFS ou plusieurs VPS indépendants. Le verrou OS global survit dans le processus Rust si son parent est interrompu. Le worker ne consomme aucun quota ou sémaphore du parcours gratuit. Il partage toutefois le CPU/disque physique du VPS : pas de promesse d'isolation matérielle. Commandes de gestion : ```bash python -m api_pro status python -m api_pro configure prj_… --units 500 python -m api_pro configure prj_… --active no python -m api_pro revoke key_… python -m api_pro cleanup ``` Après sauvegarde, migrer un registre pilote v1 explicitement avec `migrate`. Les accès opérateur existants sont conservés sans échéance implicite. `project "Client" --days 30` ouvre un accès limité ; `project "Opérateur" --no-expiry` exprime une exception. `configure prj_… --days 30` prolonge explicitement depuis maintenant. `key prj_… --days 7 --out …` peut limiter une clé plus tôt ; l'échéance du projet reste toujours applicable. ```bash python -m api_pro backup --directory /var/lib/gardenarena-api-pro/recovery python -m api_pro restore --snapshot /chemin/prive/pro-backup-….sqlite3 --out /chemin/prive/nouveau/pro.sqlite3 python -m api_pro purge-backups --directory /var/lib/gardenarena-api-pro/recovery ``` L'opérateur reste authentifié par son accès système existant ; pas de deuxième login admin public. Le Hub est inchangé. Une future interface de création dans le Hub devra reprendre ses contrôles propriétaire et anti-CSRF. ## MCP, API et jeu : séparation claire Les outils MCP existants (`farm_policy_get`, `farm_policy_validate`, `farm_policy_run`, `farm_compare_get`, `farm_compare_run`) restent gratuits dans leurs limites publiques actuelles. Ce pilote ne leur greffe pas une clé commerciale implicite. Un assistant disposant d'un client HTTP peut utiliser l'API Pro avec l'autorisation et le budget finis de son utilisateur ; la clé doit rester dans la configuration du client/outillage, pas dans le prompt. ## Avant toute vente Recette d'intégration avec un client pilote, mesure coût CPU/stockage/support, choix d'un volume vendu et d'une durée d'accès contractuelle, conditions de traitement des données et de service, procédure de remise/révocation des clés, sauvegarde/restauration et purge, puis devis ou facturation manuelle. Ce lot ne prouve ni une demande payante ni un débit de production garanti. Pas d'abonnement technique ajouté, pas de nouvel LLM facturé par essai.