diff --git a/ops/db-bootstrap/set_tradein_fdw_password.sql b/ops/db-bootstrap/set_tradein_fdw_password.sql index c0742ab2..0daf946a 100644 --- a/ops/db-bootstrap/set_tradein_fdw_password.sql +++ b/ops/db-bootstrap/set_tradein_fdw_password.sql @@ -10,18 +10,26 @@ -- Combined with the regex whitelist on the backend side (fdw.py _PASSWORD_RE) -- this gives defense-in-depth. -- --- Extracted from deploy.yml inline DO block (PR #493 deploy/1156 incident). --- The original block used multi-line backslash continuations inside a double-quoted --- bash string with $$-dollar-quoting + psql variable substitution — fragile escaping --- that likely caused the bootstrap step to fail before `compose up -d` ran. --- Using `-f ` with psql-native variable substitution via `-v pw=` is safe. +-- psql variable substitution (:'pw') НЕ интерполируется внутри dollar-quoted +-- блока ($$...$$) — это правило psql, не bug. Поэтому password передаём в DO +-- через сессионный GUC (set_config), который psql интерполирует ВНЕ dollar +-- quote, и читаем внутри через current_setting(). +-- Reference incident: deploy 2026-05-24 (post-merge PR #503) упал на +-- "syntax error at or near ':'" в LINE 4 этого файла — :'pw' дошёл до сервера +-- as literal вместо интерполяции. + +SELECT set_config('app.fdw_pw', :'pw', false); DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'tradein_fdw_reader') THEN - EXECUTE format('ALTER ROLE tradein_fdw_reader WITH PASSWORD %L', :'pw'); + EXECUTE format('ALTER ROLE tradein_fdw_reader WITH PASSWORD %L', current_setting('app.fdw_pw')); RAISE NOTICE 'tradein_fdw_reader password set'; ELSE RAISE NOTICE 'tradein_fdw_reader role missing — migration 100_tradein_fdw_role.sql not applied yet'; END IF; END $$; + +-- Clear GUC after use (defense-in-depth — не оставляем password в session state +-- даже на short connection). +SELECT set_config('app.fdw_pw', '', false);