feat(multi-env): Phase D3 — erp iac creates erp-sandbox Vault auth + creds + KV #12
Reference in New Issue
Block a user
Delete Branch "claude/phaseD-erp-sandbox-iac"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase D3 of ADR-0002 — the erp-repo Vault layer.
iac/main.tfiteratesenvs = ["prod", "sandbox"], so theapp_rolesmodule + the admin-bootstrap resources are materialised per environment.What the apply adds (sandbox) — expected ~5 add, 0 change, 0 destroy
module.app_roles["sandbox"].vault_kubernetes_auth_backend_role.roleauth/kubernetes/role/erp-sandbox(token_policies["default","erp-sandbox"]— the policy from tools#3)module.app_roles["sandbox"].vault_database_secret_backend_role.role[0]postgres/creds/erp-sandbox— dynamic role GRANTserp_sandbox_role(the snake owner role from factory#17), REVOKEs on DATABASEerp-sandboxrandom_password.admin_initial_password["sandbox"]random_uuid.dolibarr_id["sandbox"]vault_kv_secret_v2.dolibarr_admin_setup["sandbox"]kvv2/erp-sandbox/configThe
movedblocks — why nothing is destroyedIntroducing
for_eachchanges every resource's address (X→X["prod"]). Without migration that's a destroy+create — andrandom_uuid.dolibarr_idcarriesprevent_destroy = true(it is the prod Dolibarr encryption id + paid-module binding), so a wrong/absentmovedwould hard-fail the apply rather than silently lose it. The fourmovedblocks re-key the existing prod resources into the map under"prod". The module's own internalmoved(role→role[0]) chains with the module re-key.I verified the exact compound scenario (state on the pre-Phase-A module → new module's
count+internal-movedand thefor_eachre-key landing in one apply) with two standalonetofu planruns:env=prodrenders byte-identical to the single-env baseline (module elision rule), so the prod erp auth role, dynamic creds, admin secret + KV are unchanged.Merge gate
CI
tofu applymust show: prod resources moved (not destroyed/replaced), sandbox resources created, 0 destroyed. (prevent_destroyondolibarr_idis the ultimate backstop — a bad plan errors instead of touching prod data.)Phase D sequence
erp-sandboxApplication🤖 Generated with Claude Code
ADR-0002 Phase D, erp-repo layer. iac/main.tf iterates `envs = ["prod", "sandbox"]` so the app_roles module + the admin-bootstrap resources are materialised per environment: - module.app_roles["sandbox"] → auth/kubernetes/role/erp-sandbox + postgres/creds/erp-sandbox (dynamic role GRANTs erp_sandbox_role — the snake-case owner role created in factory#17 — and REVOKEs on DATABASE erp-sandbox; token_policies ["default","erp-sandbox"] = the policy from tools#3). - random_password.admin_initial_password["sandbox"], random_uuid.dolibarr_id ["sandbox"], and vault_kv_secret_v2.dolibarr_admin_setup["sandbox"] (kvv2/erp-sandbox/config) → the sandbox Dolibarr's own admin password + encryption id. State migration via `moved` blocks: the pre-existing single-env resources are re-keyed into the for_each map under "prod" so introducing for_each does NOT destroy+recreate them. Critical for random_uuid.dolibarr_id (prevent_destroy = true — prod encryption id + paid-module binding): a wrong/absent moved would HARD-FAIL the apply rather than lose it. The module's internal moved (role -> role[0]) chains with the module re-key. Verified the exact compound (old-module state → new module count+moved + for_each, one apply) with two standalone tofu plans: both show "X moved", sandbox created, 0 destroyed. env=prod renders byte-identical to the single-env baseline (module elision rule), so the prod erp Vault auth role, dynamic creds, admin secret + KV are unchanged. D3 of Phase D. D1 = factory#17 (DB+role, merged). D2 = tools#3 (Vault policies, merged). D4 (ArgoCD Application) is next. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>