🚚 chore!: переименование инфраструктуры CustoCRM/hub → Chatballs с миграцией

- каталог code/custocrm → code/chatballs; CLI custocrm → chatballs; пакеты
  hub_platform → chatballs, hub_backend → chatballs_backend (app labels прежние)
- переменные CUS_* и CUSTOCRM_* → CHATBALLS_*; образы chatballs-*; compose-проект
  и база chatballs (были edevs_hub); роли Postgres chatballs_* (были custocrm_*);
  схема RLS chatballs и GUC chatballs.organization_id; cookie chatballs_*
- CI: APP_DIR code/chatballs, DEPLOY_ROOT /opt/chatballs
- deploy/migrate/rename-to-chatballs.sh — миграция существующей установки без
  потери данных: остановка старого проекта, .env (с резервной копией),
  переименование суперпользователя initdb через временную роль, остальных ролей,
  базы, схемы и функции RLS; проверено на локальном стеке
- dev-стек хранит Postgres в bind-mount data/postgres, как prod (именованный том
  compose.dev был устаревшим снимком и вводил в заблуждение)
- снятие демо удаляет объекты, созданные поверх демо-данных тестировавшим
  (звонки по демо-диалогу), вместо падения на PROTECT
- реальные домены *.custocrm.ru и идентификаторы документов не тронуты

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
AndreyandClaude Fable 5.1 committed 2026-09-05 22:21:12 +03:00
1 parent dbd7ae3150
commit 1a61780dec
628 files changed
+5839 -5622

No files matched your search

+12 -12
View File
@@ -17,14 +17,14 @@ psql --set=ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
--set=migration_password="$POSTGRES_MIGRATION_PASSWORD" <<'SQL'
CREATE EXTENSION IF NOT EXISTS vector;
SELECT 'CREATE ROLE custocrm_runtime_app NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS'
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'custocrm_runtime_app')
SELECT 'CREATE ROLE chatballs_runtime_app NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS'
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'chatballs_runtime_app')
\gexec
SELECT 'CREATE ROLE custocrm_runtime_platform NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS'
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'custocrm_runtime_platform')
SELECT 'CREATE ROLE chatballs_runtime_platform NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS'
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'chatballs_runtime_platform')
\gexec
SELECT 'CREATE ROLE custocrm_schema NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS'
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'custocrm_schema')
SELECT 'CREATE ROLE chatballs_schema NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS'
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'chatballs_schema')
\gexec
SELECT format('CREATE ROLE %I LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS', :'app_user', :'app_password')
@@ -37,15 +37,15 @@ SELECT format('CREATE ROLE %I LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATER
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = :'migration_user')
\gexec
SELECT format('GRANT custocrm_runtime_app TO %I', :'app_user') \gexec
SELECT format('GRANT custocrm_runtime_platform TO %I', :'platform_user') \gexec
SELECT format('GRANT custocrm_schema TO %I', :'migration_user') \gexec
-- Runtime roles must not inherit the permissive custocrm_schema_access policy:
SELECT format('GRANT chatballs_runtime_app TO %I', :'app_user') \gexec
SELECT format('GRANT chatballs_runtime_platform TO %I', :'platform_user') \gexec
SELECT format('GRANT chatballs_schema TO %I', :'migration_user') \gexec
-- Runtime roles must not inherit the permissive chatballs_schema_access policy:
-- membership in the schema-owner role would bypass tenant RLS entirely.
REVOKE custocrm_schema FROM custocrm_runtime_app, custocrm_runtime_platform;
REVOKE chatballs_schema FROM chatballs_runtime_app, chatballs_runtime_platform;
SELECT format('GRANT CONNECT ON DATABASE %I TO %I', current_database(), :'app_user') \gexec
SELECT format('GRANT CONNECT ON DATABASE %I TO %I', current_database(), :'platform_user') \gexec
SELECT format('GRANT CONNECT, CREATE, TEMPORARY ON DATABASE %I TO %I', current_database(), :'migration_user') \gexec
SELECT format('GRANT USAGE, CREATE ON SCHEMA public TO %I', :'migration_user') \gexec
GRANT USAGE, CREATE ON SCHEMA public TO custocrm_schema;
GRANT USAGE, CREATE ON SCHEMA public TO chatballs_schema;
SQL
@@ -1,14 +1,14 @@
-- Нормализация владельца объектов public-схемы под роль миграций.
--
-- Контекст: при раздельных ролях (custocrm_migration / custocrm_app /
-- custocrm_platform) Django-миграции от migration-user требуют, чтобы
-- Контекст: при раздельных ролях (chatballs_migration / chatballs_app /
-- chatballs_platform) Django-миграции от migration-user требуют, чтобы
-- выполняющий был ВЛАДЕЛЬЦЕМ изменяемой таблицы («must be owner of table …»).
-- Таблицы, созданные/импортированные иначе (суперпользователем postgres,
-- app-role или до ввода разделения ролей), оказываются «осиротевшими», и
-- AddField/AlterField на них падает в deploy.
--
-- Скрипт переписывает владение всей public-схемы на custocrm_schema — роль,
-- в которую входит custocrm_migration (см. init-runtime-roles.sh). После этого
-- Скрипт переписывает владение всей public-схемы на chatballs_schema — роль,
-- в которую входит chatballs_migration (см. init-runtime-roles.sh). После этого
-- любой migration-user может мигрировать любые таблицы.
--
-- Выполнять под суперпользователем postgres (не под app/migration role):
@@ -19,8 +19,8 @@
\set ON_ERROR_STOP on
-- 1. Таблицы, последовательности, функции, типы → custocrm_schema.
ALTER SCHEMA public OWNER TO custocrm_schema;
-- 1. Таблицы, последовательности, функции, типы → chatballs_schema.
ALTER SCHEMA public OWNER TO chatballs_schema;
DO $$
DECLARE
@@ -30,14 +30,14 @@ BEGIN
FOR r IN
SELECT tablename FROM pg_tables WHERE schemaname = 'public'
LOOP
EXECUTE format('ALTER TABLE public.%I OWNER TO custocrm_schema', r.tablename);
EXECUTE format('ALTER TABLE public.%I OWNER TO chatballs_schema', r.tablename);
END LOOP;
-- Последовательности (включая owned-последовательности таблиц).
FOR r IN
SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'public'
LOOP
EXECUTE format('ALTER SEQUENCE public.%I OWNER TO custocrm_schema', r.sequence_name);
EXECUTE format('ALTER SEQUENCE public.%I OWNER TO chatballs_schema', r.sequence_name);
END LOOP;
-- Функции/процедуры в public.
@@ -47,7 +47,7 @@ BEGIN
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'public'
LOOP
EXECUTE format('ALTER FUNCTION %s(%s) OWNER TO custocrm_schema', r.proname, r.args);
EXECUTE format('ALTER FUNCTION %s(%s) OWNER TO chatballs_schema', r.proname, r.args);
END LOOP;
END $$;