panels-origin/db/provision/01-roles.sql
Cursor Agent b87b0205a8
db: migrar infraestructura de BD a Postgres (fase 0-1)
- Fase 0: scripts de aprovisionamiento (db/provision/) para roles, dos
  bases de datos separadas (panels_platform / panels_product con
  esquemas iam+core) y ACLs de Redis por modulo, con verificacion
  automatizada de aislamiento (verify-isolation.sh) y setup local
  reproducible (dev-local.sh).
- Fase 1: changelogs de Liquibase reescritos para Postgres
  (db/platform, db/iam, db/core reemplazan db/app + los changesets
  SQLite de platform). Baseline como estado final (no replay literal),
  tipos traducidos (IDENTITY, TIMESTAMPTZ/DATE, NUMERIC, BOOLEAN,
  CITEXT), contexts dev vs. schema/catalogos, RLS por tenant_id como
  defensa en profundidad, uploaded_by/created_by como snapshot
  desnormalizado (sin FK hacia iam).
- Migraciones ya no corren en el arranque de la API: paso explicito de
  deploy via db/update.sh con credenciales _owner.

Verificado end-to-end contra Postgres 16 + Redis local.

Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-02 20:00:49 +00:00

51 lines
2.8 KiB
SQL

-- PANELS · Postgres · Fase 0 (aprovisionamiento de roles)
--
-- Crea los 6 roles cluster-wide usados por PANELS: dos por módulo
-- (platform, iam, core), un rol "_owner" para Liquibase/migraciones y un
-- rol "_app" para runtime con privilegios acotados a su esquema/base.
--
-- Idempotente vía el idiom \gexec (solo emite el CREATE ROLE si todavía
-- no existe). Nota: la interpolación de variables de psql (:'var') NO
-- funciona dentro de bloques DO $$...$$ (dollar-quoting), por eso este
-- script arma el DDL con format(...)+\gexec en vez de un DO block.
--
-- Uso (contra un Postgres nuevo, como superuser/admin de Coolify). Los
-- valores se pasan SIN comillas propias; :'var' ya produce un literal SQL
-- correctamente escapado:
-- psql "$SUPERUSER_URL" \
-- -v platform_owner_pw="CAMBIA-ESTA-CLAVE-1" \
-- -v platform_app_pw="CAMBIA-ESTA-CLAVE-2" \
-- -v iam_owner_pw="CAMBIA-ESTA-CLAVE-3" \
-- -v iam_app_pw="CAMBIA-ESTA-CLAVE-4" \
-- -v core_owner_pw="CAMBIA-ESTA-CLAVE-5" \
-- -v core_app_pw="CAMBIA-ESTA-CLAVE-6" \
-- -f 01-roles.sql
--
-- Genera claves fuertes por ambiente con: openssl rand -hex 24
SELECT format('CREATE ROLE panels_platform_owner LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE', :'platform_owner_pw')
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'panels_platform_owner')\gexec
SELECT format('CREATE ROLE panels_platform_app LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE', :'platform_app_pw')
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'panels_platform_app')\gexec
SELECT format('CREATE ROLE panels_iam_owner LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE', :'iam_owner_pw')
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'panels_iam_owner')\gexec
SELECT format('CREATE ROLE panels_iam_app LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE', :'iam_app_pw')
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'panels_iam_app')\gexec
SELECT format('CREATE ROLE panels_core_owner LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE', :'core_owner_pw')
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'panels_core_owner')\gexec
SELECT format('CREATE ROLE panels_core_app LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE', :'core_app_pw')
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'panels_core_app')\gexec
-- Si el rol ya existía de una corrida anterior, refresca su password al
-- valor actual (para poder rotar credenciales corriendo este script de nuevo).
ALTER ROLE panels_platform_owner PASSWORD :'platform_owner_pw';
ALTER ROLE panels_platform_app PASSWORD :'platform_app_pw';
ALTER ROLE panels_iam_owner PASSWORD :'iam_owner_pw';
ALTER ROLE panels_iam_app PASSWORD :'iam_app_pw';
ALTER ROLE panels_core_owner PASSWORD :'core_owner_pw';
ALTER ROLE panels_core_app PASSWORD :'core_app_pw';