Deux passages gated en production, et l'outil qui manquait pour clore le dossier client. CYCLE M4 (2026-08-24-m4-et-ecarts). Cinq opérations : le tiers Anthropic PBC — entité américaine, distincte d'Anthropic Ireland Limited — et sa facture de 90 EUR réglée le 19/07 ; le règlement Darnis de 262,20 EUR ; les deux factures du cycle M4 (part fixe 2 500 USD → 2 140,45 EUR échéance 22/09, part différée 3 000 USD → 2 568,54 EUR échéance 23/11). Les trois écarts bancaires relevés sont comblés ; Qonto tombe à 3 806,08 EUR. Le juge pré-gate a bloqué : le règlement Darnis du 14/08 précède la facture datée du 31/08. C'est un fait bancaire, pas une erreur de saisie — Darnis facture en fin de mois — et adc-008 avait EXPRESSÉMENT prévu ce blocage et autorisé le passage outre tracé. L'art. 289 du CGI qu'invoque le juge régit la numérotation des factures ÉMISES, non l'ordre entre un paiement et sa facture ; c'est la troisième fois de la session qu'il l'étend hors de son champ. CLAUSE DE PÉNALITÉS (2026-08-24-clause-bilingue). Les factures M4 sont sorties avec une clause AMPUTÉE : sans la traduction anglaise, sans la mention « Ces stipulations sont des minima légaux d'ordre public auxquels il ne peut être renoncé ». Détecté par le contrôle des mentions obligatoires sur les PDF — avant tout envoi. La note publique est rétablie dans sa rédaction de référence, à droit constant : aucun montant, aucune date, aucune ligne touchés. Deux raisons de corriger plutôt que de laisser courir. La permanence des méthodes (PCG art. 121-5, adc-011) : une clause légale identique doit être rédigée identiquement, sans quoi la variation se lit comme une intention. Et le fond : le destinataire est américain, c'est la version anglaise qui lui rend la clause opposable en fait — et c'est sur elle que s'appuie la relance. Le juge a bloqué là aussi, en supposant que la référence portait « ce montant ». Il ne l'avait pas vérifié, et son propre residual risk demandait de le faire. Vérification faite et consignée (02b-preuve-reference.txt) : FAC005 à FAC008 portent toutes « ce forfait », et la clause proposée leur est identique au caractère près — 1283 car. Le finding était inversé. test/buildInvoicePdf.ts. Valider une facture par l'API ne produit AUCUN PDF : le fichier n'existe que si quelqu'un l'a demandé. `PUT /documents/builddoc` le ferait mais répond 403 — ce droit n'est accordé à aucun scope agent. Le script emprunte donc l'interface, puis relit le fichier par l'API : on ne croit pas la page de retour, on vérifie que le PDF est déposé et lisible par un tiers. Les deux juges post-gate passent sans dérive. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
test — Dolibarr UI automation (Deno + Playwright)
A small Deno + Playwright POC that drives the Dolibarr admin UI in the fr-FR
locale. Playwright fills the same forms a human admin would, so the automation
works even where the REST API can't (e.g. generating an API key, which is
encrypted with the instance's own DOLI_INSTANCE_UNIQUE_ID).
Layout
main.ts— original entrypoint (first install, company/display/module setup).provisionSandbox.ts— entrypoint that provisions theerp-sandboxinstance for the AI agent (enable REST API, create a write-scoped user, generate its API key).scripts/login.ts— admin login / logout / whoami helpers.scripts/forms.ts—fillForm,toggleOnOff, CKEditor/ACE helpers.scripts/admin/moduleSetup.ts—configureModule,enableApiModule.scripts/admin/userSetup.ts—createUser,assignRights,generateApiKey.
Configure
Copy .env.example to .env and fill it in. .env, *.key, and
.ai_agent_sandbox.key are gitignored — never commit secrets.
cp .env.example .env
Lock the installer (after a fresh install via main.ts)
Dolibarr keeps its web installer reachable until an install.lock file exists.
After a fresh install (the main.ts flow), create it in the target pod — for the
sandbox:
kubectl -n erp-sandbox exec \
"$(kubectl get pod -n erp-sandbox -l app.kubernetes.io/instance=erp-sandbox -o name)" -- \
/bin/sh -c 'touch /var/www/documents/install.lock && chown www-data:www-data /var/www/documents/install.lock'
The path is the Dolibarr data root (/var/www/documents, a PVC) — that's where
Dolibarr checks, and being on the PVC the lock persists across pod restarts. For
prod, swap to -n erp -l app.kubernetes.io/instance=erp. A sandbox seeded from
prod still needs this: the seed (see ../ops/sandbox/) copies the DB +
documents/mycompany, not install.lock.
Provision the sandbox
Provisions erp-sandbox.arcodange.lab: enables the REST API module, creates the
write-scoped ai_agent_sandbox user, grants it its write rights, and has
Dolibarr generate the user's API key. The key is written to
test/.ai_agent_sandbox.key (gitignored) — it is never printed.
cd test
deno run --allow-all provisionSandbox.ts
Populate .env from the erp-sandbox namespace secrets first. secretkv
carries the app env (including DOLI_ADMIN_PASSWORD); vso-db-credentials
carries the database password:
# Admin password (key DOLI_ADMIN_PASSWORD inside the secretkv secret)
kubectl get secret secretkv -n erp-sandbox \
-o jsonpath='{.data.DOLI_ADMIN_PASSWORD}' | base64 -d
# Database password (key `password` inside vso-db-credentials)
kubectl get secret vso-db-credentials -n erp-sandbox \
-o jsonpath='{.data.password}' | base64 -d
Set in .env:
DOLIBARR_ADDRESS=https://erp-sandbox.arcodange.lab
DOLI_ADMIN_LOGIN=admin
DOLI_ADMIN_PASSWORD="<from secretkv above>"
DOLI_DB_PASSWORD="<from vso-db-credentials above>"
# Optional — otherwise a random password is generated and only the API key emitted:
# AI_AGENT_SANDBOX_PASSWORD="<choose one>"
After it runs
The generated API key lands in test/.ai_agent_sandbox.key. Next step (not
automated by this POC): load it into the dolibarr skill's sandbox config /
Vault at kvv2/erp-sandbox/ai_agent.
Important
The sandbox Dolibarr is not installed/provisioned yet (empty DB, fresh install wizard). Until the install wizard has been completed against the sandbox,
provisionSandbox.tswill not have a UI to drive, and the selectors inmoduleSetup.ts/userSetup.tsare best-effort (Dolibarr 22 conventions, not verified live). Confirm them on the first real run.
Write rights granted
The ai_agent_sandbox user is created non-admin and granted (the authoritative
list is WRITE_IDS in provisionSandbox.ts):
| Module | rights ids |
|---|---|
| facture | lire=11, creer=12 |
| societe | lire=121, creer=122, client voir=262 |
| societe contact | lire=281, creer=282 |
| fournisseur | lire=1181, facture lire=1231, facture creer=1232 |
| produit | lire=31, creer=32 |
| banque | lire=111 |
| user | lire=251 — requis par le probe armé GET /users/info (checkpoint status/relink-env) |