diff --git a/.env.example b/.env.example index 2a76628..2d8d031 100644 --- a/.env.example +++ b/.env.example @@ -31,6 +31,11 @@ VAPID_PRIVATE_KEY=your-vapid-private-key # SendGrid API key for transactional email (optional — app works without it) # SENDGRID_API_KEY=SG.xxxxxxxxxxxx +# Row Level Security (изоляция tenant'ов на уровне БД). +# ОБЯЗАТЕЛЬНО для production: без него процесс не стартует (fatal при NODE_ENV=production). +# В dev можно не задавать (safe default — политики существуют, но не активны). +# ENABLE_RLS=true + # ============================================= # Database — choose ONE of the two modes below # ============================================= diff --git a/DOCKER.md b/DOCKER.md index d306015..dbe9324 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -212,6 +212,11 @@ xxx... 3. Создаёт MinIO bucket если настроен S3 (автоматически) 4. Запускает сервер приложения (`npm run start`) +**Row Level Security (RLS):** при `ENABLE_RLS=true` на старте включается ENABLE+FORCE RLS +на 31 таблице с проверкой политик (schema drift, count политик) — при расхождении процесс падает. +**В production (`NODE_ENV=production`) `ENABLE_RLS=true` обязателен** — без него процесс не стартует. +В development флаг можно не задавать (политики существуют, но не активны). + --- ## Изменение схемы базы данных diff --git a/IMPLEMENTATION_LOG.md b/IMPLEMENTATION_LOG.md index acbce58..e71b6d5 100644 --- a/IMPLEMENTATION_LOG.md +++ b/IMPLEMENTATION_LOG.md @@ -429,3 +429,16 @@ - Что осталось (прод, с подтверждения): 1) добавить ENABLE_RLS=true в .env сервера и перезапустить app, проверить; 2) затем задеплоить fatal-проверку (NODE_ENV=production без ENABLE_RLS → процесс не стартует) + пометки в .env.example/DOCKER.md. - Влияние на поиск/UX: нет. - Подводные камни: порядок важен — fatal-проверку деплоить ТОЛЬКО после включения флага на проде, иначе app не поднимется. + +--- + +## [0.1] RLS обязательным в production — завершение + +- Статус: ✅ done +- Что сделано после локальной проверки (см. запись выше): + 1. Прод: бэкап БД (crm-20260908-075039.dump.gz), `ENABLE_RLS=true` в /opt/crm/.env, recreate app — старт-лог «Startup RLS: active — ENABLE+FORCE verified on 31 tables, 31 policies», health 200, поиск/списки через API работают. + 2. Код: `server/index.ts` — при NODE_ENV=production без ENABLE_RLS=true — fatal (процесс не поднимается); dev — предупреждение. + 3. Документация: `.env.example` (обязательность для production), `DOCKER.md` (sequence при старте + блок про RLS). +- Как проверялось: на проде подтверждено включение (pg_class relrowsecurity+relforcerowsecurity=31), smoke через API; локально — полный цикл на копии прод-БД. +- Влияние на поиск/UX: нет. +- Подводные камни: при переносе на новый сервер — сначала ENABLE_RLS=true в .env, иначе app не поднимется (это и есть цель шага). diff --git a/server/index.ts b/server/index.ts index 472aef1..a567301 100644 --- a/server/index.ts +++ b/server/index.ts @@ -985,8 +985,15 @@ async function runStartupDataPatches() { } log(`Startup RLS: active — ENABLE+FORCE verified on ${rlsVerified} tables, ${policyVerified} policies`); + } else if (process.env.NODE_ENV === "production") { + // Шаг 0.1: в production RLS обязателен — без изоляции tenant'ов на уровне БД + // процесс не поднимается. + throw new Error( + "Startup RLS: ENABLE_RLS=true is REQUIRED in production. " + + "Set ENABLE_RLS=true in the environment and restart." + ); } else { - log("Startup RLS: ENABLE_RLS not set — policies exist but inactive (safe default)"); + log("Startup RLS: ENABLE_RLS not set — policies exist but inactive (safe default, dev only)"); } const seedDir = path.resolve(