feat(skills,cli): promote-to-prod replay (ADR-0003 capstone) + supplier payment fix
The human-gated path that carries a reviewed sandbox change to prod.
- promote-plan.sh: render a manifest (JSON array of write ops with symbolic @refs
instead of ids — portable sandbox->prod) as a human-readable change-set.
- promote-apply.sh <manifest> --target sandbox|prod: replay it, resolving each
@ref to the id actually created during the run (dependent ops wire up). sandbox
rehearses via dol-write.sh; prod via dol-prod-write.sh.
- dol-prod-write.sh: the ONLY prod-write path. Prod key read from the ENVIRONMENT
only (DOLIBARR_PROD_WRITE_KEY, never a stored .env); every write refused unless
ARCO_PROMOTE_CONFIRM=I-UNDERSTAND-THIS-WRITES-PROD.
- create scripts take a DOL_WRITE override so promote-apply reuses them per target.
- bin/arcodange: `promote {plan|apply}` group + example manifest.
- payment-record.sh: fixed supplier payments (payment_mode_id + closepaidinvoices).
Proven live: plan renders; apply --target sandbox replays a 3-op chain with refs
resolved (@tp1->id, invoice socid=@tp1, payment invoice=@inv1); --target prod
without the confirm flag is REFUSED before sending. Supplier payment now works
end-to-end via the script.
Limitation (documented): manifests reference entities they create (@ref);
pre-existing prod entities need business-key resolution (follow-up).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,10 +38,12 @@ human promotes the reviewed change to prod.
|
||||
key is read-only and lives in a different skill's `.env`.
|
||||
- **Resettable.** Anything written here is wiped by `ops/sandbox/sandbox-lifecycle.sh
|
||||
refresh-from-prod`, so mistakes cost a reset, not data.
|
||||
- **Promotion to prod is NOT in this skill.** Rehearse here → capture a reviewable
|
||||
diff with the read-only `dolibarr-data-snapshot` skill (before/after) → a human
|
||||
approves → the same operations are replayed against prod under a separate,
|
||||
human-held prod-write credential. Never wire a prod-write key into this skill.
|
||||
- **Promotion to prod is gated, not automatic.** Rehearse here → review the
|
||||
change-set (`promote-plan.sh`) → replay it on prod (`promote-apply.sh --target
|
||||
prod`). The prod write key is supplied via the **environment at apply time**
|
||||
(`DOLIBARR_PROD_WRITE_KEY`), never stored in any `.env`, and `dol-prod-write.sh`
|
||||
refuses every prod write unless `ARCO_PROMOTE_CONFIRM=I-UNDERSTAND-THIS-WRITES-PROD`.
|
||||
See "Promote to prod" below.
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -115,6 +117,35 @@ A customer invoice of `type=2` referencing `source_invoice` (`fk_facture_source`
|
||||
amounts come out negative (a credit). `validate:true` turns the draft into a
|
||||
numbered `AVC…` avoir. Emits `{id, ref, total_ht, total_ttc, fk_facture_source, statut}`.
|
||||
|
||||
## Promote to prod (rehearse → review → replay)
|
||||
|
||||
The ADR-0003 capstone: take a change rehearsed in the sandbox and apply the **same
|
||||
operations** to prod, with a human in the loop. The unit is a **manifest** — a JSON
|
||||
array of write ops using **symbolic refs** (`@name`) instead of ids, so it is
|
||||
portable from sandbox to prod (an invoice references `@tp1`, the thirdparty created
|
||||
earlier in the run). See `examples/promote-manifest.json`.
|
||||
|
||||
```sh
|
||||
scripts/promote-plan.sh change.json # 1. human-readable review
|
||||
scripts/promote-apply.sh change.json --target sandbox # 2. rehearse the replay (safe)
|
||||
# 3. promote — writes PROD; the key is env-only and the confirm flag is mandatory:
|
||||
DOLIBARR_PROD_WRITE_KEY="<prod write key>" \
|
||||
ARCO_PROMOTE_CONFIRM=I-UNDERSTAND-THIS-WRITES-PROD \
|
||||
scripts/promote-apply.sh change.json --target prod
|
||||
```
|
||||
|
||||
`promote-apply` resolves each `@ref` to the id actually created during the run, so
|
||||
dependent ops wire up on the target. `--target sandbox` writes via `dol-write.sh`;
|
||||
`--target prod` writes via `dol-prod-write.sh`, which reads `DOLIBARR_PROD_WRITE_KEY`
|
||||
**from the environment only** (never a stored `.env`) and refuses any write unless
|
||||
`ARCO_PROMOTE_CONFIRM` is set exactly. Pair it with `dolibarr-data-snapshot` (prod
|
||||
before/after) to confirm only the intended records changed.
|
||||
|
||||
Limitation: a manifest references entities it **creates** (via `@ref`). Referencing
|
||||
a *pre-existing* prod entity by a sandbox id won't match — resolve those by business
|
||||
key (name/code/ref) first. Self-contained change-sets (new thirdparty + its invoice
|
||||
+ payment) replay cleanly today.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Validate before paying.** A draft (`statut=0`, ref `PROV…`) cannot be paid.
|
||||
|
||||
Reference in New Issue
Block a user