# Agent Action Assurance 0.1.0 beta — intégré au service

Le moteur contrôle et réserve une action déclarée, puis comptabilise son commit. Il n'effectue aucun paiement, mutation externe ou exécution d'outil. Un rapport ES256 protège l'intégrité de ce contrôle : `external_execution:false`, niveau interne L1. Il ne constitue pas une preuve L3 d'une exécution chez un tiers.

## Endpoints disponibles dans `xynthera-ai-agent-action`

| POST | Entrée hors `request_id` de transport | Effet |
|---|---|---|
| `/v1/policies` | `policy` | Créer/configurer la politique du tenant ; `x-management-key` obligatoire. |
| `/v1/approvals` | `request`, `subject` | Émettre un jeton aléatoire lié à l'empreinte précise ; `x-management-key` obligatoire. |
| `/v1/actions/reserve` | `request` | Réserver le budget après politique, audience, scopes, montant et éventuelle approbation. |
| `/v1/actions/commit` | `reservation_id`, `input_hash` | Consommer une réserve non expirée ; commit idempotent. |
| `/v1/actions/cancel` | `reservation_id`, `input_hash` | Libérer la réserve ; impossible après commit. |

Toutes les opérations exigent la clé API du tenant actif et payé. Elles consomment chacune une unité du quota Workbench commun ; aucun prix ou quota supplémentaire n'est proposé. Une réponse métier DENY après admission consomme aussi une unité. La clé de gestion est distincte de la clé distribuée aux agents. Le propriétaire génère **localement** 32 octets aléatoires et conserve leur représentation hexadécimale de 64 caractères avant le bootstrap. Aucun secret de gestion n'est généré ou retourné par le serveur ; seul son SHA-256 est stocké. La première configuration doit intervenir avant de distribuer la clé API aux agents. Pas de rôle propriétaire granulaire ou de réinitialisation automatique de clé : une clé API partagée avant bootstrap pourrait configurer le tenant.

Le secret de gestion permet de modifier la politique et d'émettre les approbations. Une approbation atteste ce propriétaire de politique ; elle ne prouve pas une validation par une personne indépendante. Un jeton d'approbation est retourné une fois, hors rapport signé et hors cache persisté ; seul son hash, nonce et empreinte d'action sont stockés. Un retry de la même requête renvoie le rapport sans jeton ; créer une nouvelle demande d'approbation si la première réponse a été perdue.

`policy` contient `id`, `version`, `period` (mois UTC courant `YYYY-MM`), `validUntil` (millisecondes, futur au plus 31 jours), `budgetMinor` (0 à 100 000 000), `currency` (code majuscule trois lettres), `reservationTtlMs` (1–300 secondes), `rules` (1–20). Chaque règle fixe `agentId`, `audience`, `action`, `scopes` (au plus 20), `maxAmountMinor`, `confirmationRequired`, `confirmationMaxAgeMs` (1–300 secondes). Aucun wildcard d'audience, d'action ou de scope.

`request` contient `requestId` (identifiant métier de réserve), `agentId`, `audience`, `action`, `scopes`, `parameters` (objet JSON), `amountMinor` (entier sûr non négatif), `currency`, et éventuellement `approvalToken`. L'empreinte lie tenant, identifiants et version de politique, période, identifiant métier, scopes triés, paramètres canoniques et montant/devise. Un même identifiant avec une entrée différente est refusé. Les paramètres sont fournis par le client : le moteur ne vérifie pas le montant réellement facturé par un outil tiers. Un exécuteur externe doit consommer la réserve et appliquer le montant convenu ; cet exécuteur n'est pas livré ici.

## Contraintes et intégration

- Corps complet au plus 32 KiB, profondeur des paramètres 20, aucune requête réseau externe, aucun LLM/OCR.
- Politique conservée côté serveur, identifiant immutable et modification nécessitant une nouvelle version ; devise immutable pour une période.
- SQL verrouille le tenant avant somme du budget et mutation. Les réserves et commits des différentes versions de la même politique comptent ensemble pour le mois.
- Approbation vérifiée par hash serveur, liaison à la requête, fraîcheur et nonce unique ; consommation atomique lors de la réserve.
- SQL, RLS service-only et recontrôle d'abonnement sont fournis. `memory-store.mjs` est uniquement une référence de test, jamais un store de production.
- Ledger budgétaire conservé pour le mois courant et les deux mois précédents ; ne pas le purger à sept jours, ce qui remettrait le budget à zéro. Approbations supprimées un jour après expiration. Rapports Workbench conservés sept jours. Les paramètres originaux ne sont pas stockés par ce moteur.
- Pas de signature JWT client ou de JWKS fourni par le client. Les approbations sont des secrets aléatoires du serveur ; rapports ES256 via le matériel de signature Xynthera et JWKS existant.

Le responsable a appliqué `migration.sql`, étendu les endpoints des RPC Workbench et déployé le service. Les essais authentifiés ont vérifié gestion protégée, approbation, réserve, commit, annulation et conservation du budget entre versions. Le handler refuse les opérations de gestion avant de servir un cache lorsque la clé de gestion manque ou diffère.

## Tests

`node --test test/core.test.mjs test/adapter.test.mjs`. SQL : `PGLITE_MODULE=/chemin/index.js node --test test/sql.test.mjs` avec PGlite 0.3.14. Tests réels des RPC : gestion immutable, isolation, budget concurrent, nonce unique, commit, annulation et conservation du consommé entre versions. Les mesures de coût en production restent à établir ; aucune marge garantie ou autorisation externe revendiquée.
