DEUX CHOSES, dont une inachevée et dite comme telle. 1. LA SAUVEGARDE N'AVAIT AUCUNE GARDE DE CLUSTER. 24 appels kubectl nus, aucun contexte épinglé — alors que le script lit des secrets, crée des Jobs et sait RESTAURER une base. Lancé sur le contexte courant d'une station de travail, il serait parti chercher les secrets Longhorn du cluster d'un client. Même patron que ops/sandbox : ERP_KUBE_CONTEXT, wrapper K(), empreinte positive vérifiée avant tout dispatch. Testé contre le cluster client et contre un contexte inexistant : il refuse les deux. Sauvegarde de production passée dans la foulée. La base a été dédupliquée à juste titre — rien n'avait été écrit depuis la sauvegarde automatique de 01:00. Au passage, le CronJob quotidien tourne bien depuis juillet ; il était encore noté comme à faire. 2. LE MODE VIERGE PURGE MAIS NE RECONSTRUIT PAS. `blank --yes` vide la base du bac à sable (295 tables -> 0, vérifié) avec trois protections empilées : refus sans --yes, garde de cluster, et une relecture de current_database() DANS le Job lui-même — une purge sur la mauvaise base ne se rattrape pas par un refresh, contrairement à la bonne. Mais l'instance ne se reconstruit pas. Premier essai : install.lock vit sur le volume documents, que la purge ne touche pas, si bien que Dolibarr servait un login sur un schéma inexistant. Correctif appliqué — retrait du verrou puis redémarrage. Second essai : le verrou reste absent, et le schéma reste à ZÉRO table. L'entrypoint de l'image ne lance aucune installation automatique. CE QU'IL MANQUE est donc nommé dans le script : un « golden empty », pg_dump d'une instance fraîchement installée — schéma et données de référence, aucune donnée métier. `blank` le restaurerait au lieu de laisser la base vide, comme refresh-from-prod restaure le dump de production. Seule la source change. En l'état `blank` laisse le bac à sable inutilisable, et le script le dit. Le bac à sable a été remis iso-prod avant de rendre la main. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
ERP
CLI — bin/arcodange
Read-only operational CLI for the Arcodange Dolibarr at erp.arcodange.lab. One entry point, subcommands per domain:
bin/arcodange ping # Dolibarr version + liveness
bin/arcodange whoami # confirm auth as ai_agent
bin/arcodange invoice list # KissMetrics invoices with payment state
bin/arcodange invoice audit 12 # JSON facts + PDF mandatory-mention audit
bin/arcodange payments state # per-invoice TTC vs payments reconciliation
bin/arcodange payments timeline --year 2026 # cash receipts with cumulative balance
bin/arcodange tva summary # CA3-ready collectée − déductible per month
bin/arcodange thirdparty audit-all # completeness audit, country-aware
bin/arcodange templates inspect 1 # recurring template health (frequency, next fire, …)
bin/arcodange snapshot --out /tmp/erp.json # full state dump with content_hash
bin/arcodange help # full command tree
Read-only by design. The underlying API key (ai_agent) has no write permissions; corrections go through the Dolibarr UI.
Credentials. Reads .claude/skills/dolibarr/.env (mode 600, gitignored). Setup instructions: .claude/skills/dolibarr/README.md.
Source of behaviour. Each subcommand delegates to a script under .claude/skills/<skill>/scripts/. The skills' SKILL.md files document the business logic and are also discoverable by Claude Code via skill triggers.
Dolibarr
Premiers démarrages
Si l'application log au démarrage l'erreur suivante:
Importing custom SQL from update_table_ownership.sql ...
sed: couldn't open temporary file /var/www/scripts/before-starting.d/sedwHcRlQ: Read-only file system
Il faudra prendre la main du shell du pod et executer:
kubectl exec -n erp `kubectl get pod -n erp -l app.kubernetes.io/name=erp -o=name` -c erp -- sh -c 'PGPASSWORD=${DOLI_DB_PASSWORD} psql -U ${DOLI_DB_USER} -h ${DOLI_DB_HOST} -p ${DOLI_DB_HOST_PORT} ${DOLI_DB_NAME} \
-f /var/www/scripts/before-starting.d/update_table_ownership.sql'
Sous peine de ne plus avoir les droits de consulter la base de données une fois les crédentials mis à jour par vault. Dans ce cas executer la commande mais avec les credentials d'admin postgres.