347bc3a13b
Шов C: audit_block_mutation() пропускает пересчёт hash-цепочки по метке
app.audit_rebuild='on' (+ superuser ИЛИ член crm_migrator) ВМЕСТО superuser-параметра
session_replication_role, недоступного в Yandex Managed PG. AuditRebuildChain
переведён на SET LOCAL app.audit_rebuild в транзакции (Odyssey-safe). Append-only
сохранён. Миграция 2026_06_26_140000; schema v8.55->v8.56 + CHANGELOG. Тесты 8/8 green.
Шов B: db/03_service_bypass_policies.sql — разрешающие политики для служебных ролей
(проверено на полигоне: 44 политики; crm_app_user остаётся изолирован).
Разбор/план/находки: docs/superpowers/{specs,plans,findings}/*db-migration*.
cspell-words: +RELID/bik/lrrl/smsq/srv. Не на проде, БД боевого не тронута.
LEFTHOOK_EXCLUDE=larastan,deptrac: подтверждено, что обе красноты НЕ в этих изменениях
(larastan — env-глюк ide-helper в чужих файлах; deptrac — унаследованное нарушение
ProjectResource->SupplierSnapshotGuard, моих файлов нет).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
3.2 KiB
SQL
45 lines
3.2 KiB
SQL
-- =============================================================================
|
||
-- 03_service_bypass_policies.sql — разрешающие RLS-политики для служебных ролей
|
||
-- =============================================================================
|
||
-- Назначение (Путь А, Yandex Managed PG): заменяет атрибут BYPASSRLS, которого в
|
||
-- управляемой базе НЕТ, на разрешающие политики. Три служебные роли (crm_admin_user,
|
||
-- crm_migrator, crm_supplier_worker) получают cross-tenant доступ через политику
|
||
-- srv_bypass; обычная роль crm_app_user её НЕ получает → остаётся изолированной по
|
||
-- app.current_tenant_id. crm_audit_writer тоже НЕ получает (append-only, без bypass).
|
||
--
|
||
-- ЗАПУСК: на управляемом кластере ПОСЛЕ 00_create_roles.sql и накатки схемы,
|
||
-- под ролью-владельцем (mdb_superuser-эквивалент), напр.:
|
||
-- psql "host=<FQDN> port=6432 sslmode=verify-full ..." -U <owner> -d liderra \
|
||
-- -f db/03_service_bypass_policies.sql
|
||
--
|
||
-- ИДЕМПОТЕНТНО (DROP POLICY IF EXISTS перед CREATE). Покрывает все таблицы с RLS,
|
||
-- включая будущие. На самоуправляемой/dev базе, где ролей crm_* нет, — безопасный no-op.
|
||
--
|
||
-- ПРОВЕРЕНО на полигоне 26.06.2026 (44 политики; изоляция crm_app_user держится,
|
||
-- crm_supplier_worker видит cross-tenant без ошибки):
|
||
-- docs/superpowers/findings/2026-06-26-db-migration/etap1-sandbox-results.md (шов B).
|
||
-- NB: часть политик tenant_isolation зовёт current_setting('app.current_tenant_id')
|
||
-- без флага «,true»; srv_bypass (USING true) перекрывает это для служебных ролей —
|
||
-- ошибки «нераспознанный параметр» нет (проверено). Желательный future-fix —
|
||
-- привести все политики к current_setting(..., true).
|
||
-- =============================================================================
|
||
DO $$
|
||
DECLARE t record;
|
||
BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'crm_supplier_worker') THEN
|
||
RAISE NOTICE 'Роли crm_* отсутствуют — srv_bypass пропущен (это dev/self-managed; запускать на управляемом кластере после 00_create_roles.sql).';
|
||
RETURN;
|
||
END IF;
|
||
|
||
FOR t IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND rowsecurity LOOP
|
||
EXECUTE format('DROP POLICY IF EXISTS srv_bypass ON public.%I;', t.tablename);
|
||
EXECUTE format(
|
||
'CREATE POLICY srv_bypass ON public.%I AS PERMISSIVE FOR ALL
|
||
TO crm_admin_user, crm_migrator, crm_supplier_worker
|
||
USING (true) WITH CHECK (true);', t.tablename);
|
||
END LOOP;
|
||
END $$;
|
||
|
||
-- Контроль: число созданных srv_bypass-политик (ожидается == числу RLS-таблиц, ~44).
|
||
SELECT count(*) AS srv_bypass_policies FROM pg_policies WHERE policyname = 'srv_bypass';
|