fix(chart): template Postgres owner role in update_ownership.sql for multi-env #13
Reference in New Issue
Block a user
Delete Branch "claude/fix-chart-owner-role"
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?
The bug
chart/scripts/update_ownership.sql(a Dolibarr before-start step, embedded into a ConfigMap bychart/templates/scripts-config.yaml) hardcoded the Postgres owner roleerp_role. After install it reassigns ownership of allpublic-schema objects to that role.For any non-prod environment the owner role differs. By the multi-env elision rule (ADR-0002 / ADR-0003) it is snake-case
<app>_rolefor prod and<app>_<env>_rolefor non-prod — so the sandbox owner role iserp_sandbox_role.With the literal
erp_role, once Dolibarr installs inerp-sandboxthe script would reassign sandbox tables to prod'serp_role, which:erp_sandbox_role, noterp_role; andDROP OWNED BY erp_sandbox_role.The fix — make the owner role env-aware via a chart value
A new chart value
db.ownerRolecarries the per-env role:chart/values.yaml— defaultownerRole: erp_role(prod) in the existingdb:block.chart/values-sandbox.yaml— overrideownerRole: erp_sandbox_role.chart/scripts/update_ownership.sql— all'erp_role'literals →'{{ .Values.db.ownerRole }}'(single quotes preserved so the rendered output is still a quoted SQL string literal). All four occurrences replaced, so the comment +RAISE NOTICElines render the real role too.chart/templates/scripts-config.yaml— render that one SQL file throughtplso the value is substituted:{{- tpl (.Files.Get "scripts/update_ownership.sql") . | nindent 4 }}. The other script (update_conf_db_credentials.sh, no template vars) stays on plain.Files.Get. The SQL's$$,%I,format(...),RAISE NOTICEare not Go-template syntax, sotplonly substitutes the added{{ .Values.db.ownerRole }}.Proof: prod renders byte-identical
ConfigMap rendered from
origin/mainvs this branch, both with onlychart/values.yaml:Both still contain
erp_role.helm lint ./chartpasses, no worse than origin/main (same single[INFO] icon is recommended).Proof: sandbox renders the right role
erp_sandbox_roleappears 5× in the rendered SQL; bare'erp_role'appears 0×.Scope / follow-up
Full end-to-end validation — that sandbox tables actually end up owned by
erp_sandbox_roleafter a real Dolibarr install — is deferred to Phase E1, when Dolibarr is installed intoerp-sandbox. This PR is chart text only (no secrets introduced).Cross-links: [
factory vibe/ADR/0003-sandbox-state-lifecycle.md] — the sandbox state-lifecycle ADR that defines theDROP OWNED BY <app>_<env>_rolereset this fix unblocks (also relevant: ADR-0002 per-application-environments / the elision rule).🤖 Generated with Claude Code
The Dolibarr before-start step `chart/scripts/update_ownership.sql` (embedded into a ConfigMap by `chart/templates/scripts-config.yaml`) hardcoded the Postgres owner role `erp_role`. It reassigns ownership of all public-schema objects to that role after install. For any non-prod environment the owner role differs — by the multi-env elision rule (ADR-0002/0003) it is snake-case `<app>_role` for prod and `<app>_<env>_role` for non-prod, so the sandbox owner role is `erp_sandbox_role`. With the literal `erp_role`, installing Dolibarr in `erp-sandbox` would reassign sandbox tables to prod's `erp_role`, which (a) breaks the sandbox runtime (its dynamic DB creds are a member of `erp_sandbox_role`, not `erp_role`) and (b) breaks the ADR-0003 reset (`DROP OWNED BY erp_sandbox_role`). Fix: make the owner role env-aware via a new chart value `db.ownerRole`. - values.yaml: default `ownerRole: erp_role` (prod). - values-sandbox.yaml: override `ownerRole: erp_sandbox_role`. - update_ownership.sql: all `'erp_role'` literals → `'{{ .Values.db.ownerRole }}'`. - scripts-config.yaml: render that one SQL file through `tpl` so the value is substituted (the other script has no template vars and stays on `.Files.Get`). The SQL's `$$`, `%I`, `format(...)`, `RAISE NOTICE` are not Go-template syntax, so `tpl` only substitutes the added `{{ .Values.db.ownerRole }}`. Verified: the prod ConfigMap render (values.yaml only) is byte-identical to origin/main (empty diff, still `erp_role`); the sandbox render (-f values.yaml -f values-sandbox.yaml) now contains `erp_sandbox_role` and no bare `erp_role`; `helm lint` passes (no worse than origin/main). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>