Closes a real safety gap and fixes a mandatory invoice mention that has been broken since January.
The gap.test/.env ships DOLIBARR_ADDRESS pointing at production (erp.arcodange.duckdns.org) and test/main.ts defaults to it too. Any Playwright admin script run with the ambient environment drives the real ERP as admin. The REST path has been structurally safe since ADR-0003 (dol-write.sh refuses non-sandbox hosts) — the UI path had no equivalent.
test/scripts/guard.ts closes it: assertSandbox() resolves the target and refuses anything that is not erp-sandbox.*. Verified live — an unqualified run now dies with the override spelled out, instead of reaching prod.
Two settings the write agent cannot reach (non-admin by design, 403 on /setup/conf), rehearsed on the sandbox:
sandboxLegalSetup.ts — capital social + multi-currency module. Finding: the capital was never missing. It was stored as 1000€; the symbol made the value unusable by the PDF template, which is why « Capital de 1 000 € » was absent from every invoice since January (mandatory mention, C. com. R.123-238). The June cohort review recorded it as "non affiché — à ajouter" and the real cause was never diagnosed. Normalised to 1000 → the mention renders.
sandboxCurrencySetup.ts — registers the USD reference rate. Enabling the module is not enough: a currency absent from the rate table makes Dolibarr silently fall back to EUR (observed on a probe invoice: multicurrency_code=USD came back EUR). With the rate registered, an invoice carries USD 3,000.00 alongside its EUR counter-value — the contractual obligation itself rather than a drifting equivalent (decision of 2026-06-30).
Both scripts are report-only when they cannot recognise a form, and screenshot what they did. Production is unchanged: these are rehearsals, and the settings reach prod through the operator's own UI session.
Closes a real safety gap and fixes a mandatory invoice mention that has been broken since January.
**The gap.** `test/.env` ships `DOLIBARR_ADDRESS` pointing at **production** (`erp.arcodange.duckdns.org`) and `test/main.ts` defaults to it too. Any Playwright admin script run with the ambient environment drives the real ERP as admin. The REST path has been structurally safe since [ADR-0003](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/ADR/0003-sandbox-state-lifecycle.md) (`dol-write.sh` refuses non-sandbox hosts) — the UI path had no equivalent.
`test/scripts/guard.ts` closes it: `assertSandbox()` resolves the target and refuses anything that is not `erp-sandbox.*`. Verified live — an unqualified run now dies with the override spelled out, instead of reaching prod.
**Two settings the write agent cannot reach** (non-admin by design, 403 on `/setup/conf`), rehearsed on the sandbox:
- `sandboxLegalSetup.ts` — capital social + multi-currency module. **Finding: the capital was never missing.** It was stored as `1000€`; the symbol made the value unusable by the PDF template, which is why « Capital de 1 000 € » was absent from every invoice since January (mandatory mention, C. com. R.123-238). The June cohort review recorded it as "non affiché — à ajouter" and the real cause was never diagnosed. Normalised to `1000` → the mention renders.
- `sandboxCurrencySetup.ts` — registers the USD reference rate. Enabling the module is not enough: a currency absent from the rate table makes Dolibarr **silently fall back to EUR** (observed on a probe invoice: `multicurrency_code=USD` came back `EUR`). With the rate registered, an invoice carries `USD 3,000.00` alongside its EUR counter-value — the contractual obligation itself rather than a drifting equivalent (decision of 2026-06-30).
Both scripts are report-only when they cannot recognise a form, and screenshot what they did. Production is unchanged: these are rehearsals, and the settings reach prod through the operator's own UI session.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
test/.env ships DOLIBARR_ADDRESS pointing at PRODUCTION and test/main.ts
defaults to it, so any Playwright admin script run with the ambient
environment drives the real ERP. The REST path has been structurally safe
since ADR-0003 (dol-write.sh refuses non-sandbox hosts); the UI path had no
equivalent. scripts/guard.ts closes that gap — assertSandbox() resolves the
target and refuses anything that is not erp-sandbox.*, with the override
spelled out in the error. Verified: an unqualified run now dies instead of
reaching prod.
Two settings the write agent cannot reach (non-admin by design, 403 on
/setup/conf), rehearsed on the sandbox:
- sandboxLegalSetup.ts — capital social + multi-currency module. Finding:
the capital was NOT missing, it was stored as "1000€"; the symbol made the
value unusable by the PDF template, which is why "Capital de 1 000 €" was
absent from every invoice since January (C. com. R.123-238). Normalised to
"1000" → the mention now renders.
- sandboxCurrencySetup.ts — registers the USD reference rate. Enabling the
module is not enough: a currency absent from the rate table makes Dolibarr
silently fall back to EUR (observed on a probe invoice). With the rate
registered, an invoice carries USD 3,000.00 with its EUR counter-value,
i.e. the contractual obligation itself rather than a drifting equivalent.
Both scripts are report-only when they cannot recognise a form, and screenshot
what they did.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes a real safety gap and fixes a mandatory invoice mention that has been broken since January.
The gap.
test/.envshipsDOLIBARR_ADDRESSpointing at production (erp.arcodange.duckdns.org) andtest/main.tsdefaults to it too. Any Playwright admin script run with the ambient environment drives the real ERP as admin. The REST path has been structurally safe since ADR-0003 (dol-write.shrefuses non-sandbox hosts) — the UI path had no equivalent.test/scripts/guard.tscloses it:assertSandbox()resolves the target and refuses anything that is noterp-sandbox.*. Verified live — an unqualified run now dies with the override spelled out, instead of reaching prod.Two settings the write agent cannot reach (non-admin by design, 403 on
/setup/conf), rehearsed on the sandbox:sandboxLegalSetup.ts— capital social + multi-currency module. Finding: the capital was never missing. It was stored as1000€; the symbol made the value unusable by the PDF template, which is why « Capital de 1 000 € » was absent from every invoice since January (mandatory mention, C. com. R.123-238). The June cohort review recorded it as "non affiché — à ajouter" and the real cause was never diagnosed. Normalised to1000→ the mention renders.sandboxCurrencySetup.ts— registers the USD reference rate. Enabling the module is not enough: a currency absent from the rate table makes Dolibarr silently fall back to EUR (observed on a probe invoice:multicurrency_code=USDcame backEUR). With the rate registered, an invoice carriesUSD 3,000.00alongside its EUR counter-value — the contractual obligation itself rather than a drifting equivalent (decision of 2026-06-30).Both scripts are report-only when they cannot recognise a form, and screenshot what they did. Production is unchanged: these are rehearsals, and the settings reach prod through the operator's own UI session.
🤖 Generated with Claude Code
https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh