Вчера вечером я включил Row Level Security в Supabase — это базовая защита, без которой любой браузер может прочитать твою клиентскую базу. А сегодня вечером, после выступления, закрыл все остаточные задачи: отключил устаревшие JWT-ключи, ротировал секреты, прошёл smoke-тест. Семь пунктов за вечер. Ни один рабочий скрипт не упал. И я — не программист.
Эта история не про SQL. Она про то, как вайб-кодер принимает архитектурные решения в живой инфраструктуре, где работает 10 AI-агентов, крутится cron, n8n, идут данные с Tilda-лендингов — и ничего нельзя сломать.
Почему это важно
Supabase — это моя основная база данных. Там CRM-лиды из AmoCRM, ученики из GetCourse, сегменты, события. Если её взломают или она просто утечёт в публичный HTML — это потеря всей оперативной памяти бизнеса.
Вчерашний аудит безопасности показал: старые ключи (anon JWT, service_role JWT) светились где-то в переписке с Claude, могли попасть в git-историю, HTML-файлы тащили публичный ключ прямо в браузер. Без включённого RLS любой посетитель лендинга мог бы прочитать всю таблицу лидов.
RLS — это как закрытая на ключ дверь в базу данных. Даже если кто-то достанет ключ, он сможет открыть только те комнаты, на которые у него есть разрешение.
7 задач безопасности — разбор
Вечером я сел и пошёл по плану, который Claude подготовил утром. Семь пунктов. Вот что оказалось важным.
1. «Перезапустить все процессы» — не потребовалось
Claude проверил, что на сервере работает: lead-api.js (обрабатывает формы лендинга), n8n (оркестратор) и его worker. Grep показал — lead-api.js вообще не использует Supabase. А cron-скрипты сами подхватывают свежий .env при каждом запуске. Значит перезагружать нечего. Классическая ловушка — следовать плану буквально, когда реальность проще.
2. n8n credentials — чисто
В n8n было 4 workflow: обработка лидов интенсива (Tilda → Telegram + AmoCRM), синхронизация Google Calendar с Notion, лид-алерт, AI-скоринг лидов. Прошли canvas каждого по очереди. Ни один workflow не обращается к Supabase напрямую. Credentials тоже чистые — только Google Calendar и Notion. Архитектура оказалась правильной: n8n не знает паролей от базы, он только маршрутизирует события.
3. Tilda — ещё чище
Открыл настройки форм. Десять подключенных сервисов: семь разных TildaCRM, AmoCRM, SendPulse, Telegram. Supabase нигде. Значит данные в мою базу попадают не с клиента, а через серверные синкающие скрипты, которые раз в 3 часа читают AmoCRM и кладут в Supabase через service_role. Это правильно — secret-ключ никогда не должен оказаться в браузере.
4. Ротация публичного ключа — внезапный дефект
А вот тут всплыла дырка. В .env на сервере уже стоял новый publishable key, а в двух HTML-файлах дашборда (index.html и os-dashboard.html) — ещё старый. Если бы старый ключ уже был отозван, дашборд в браузере просто перестал бы показывать данные. Нашли, заменили, сделали один коммит — f357367 — и отправили в main. Vercel автодеплой подхватил сам.
Урок: единый источник правды (в данном случае — переменные окружения на сервере) — это хорошо, но только если все потребители действительно из него читают. Здесь HTML-файлы были исключением, хардкоднутым местом.
5. Отключение Legacy JWT — самое страшное
Supabase переводит всех на новые ключи формата sb_publishable_ / sb_secret_. Старые JWT (те, что начинаются с eyJhbG...) всё ещё работают, пока не нажмёшь красную кнопку «Disable JWT-based API keys». Нажмёшь — и если что-то где-то ещё использует старый ключ, оно сразу упадёт.
Поэтому перед нажатием — grep по eyJhbG во всех .js, .html, .env на сервере и на ПК. Везде пусто. Что n8n, что Tilda — не используют. После этого уверенно ввёл «disable» в окно подтверждения и нажал. Ключи отозваны. Инфраструктура работает.
6. Ротация secret — безопасная схема
Старый service_role key засветился в переписке с агентом. Даже если канал безопасен, по best-practice его надо пересоздать. Но как сделать это, не сломав ни один скрипт?
Схема: 1) создать новый secret в Supabase рядом со старым, 2) обновить .env на сервере через nano, 3) сделать бэкап .env.backup, 4) запустить smoke-тест — крон-скрипт синхронизации CRM с таблицами в Supabase. Если скрипт пишет «Синхронизация GetCourse... Синхронизация AmoCRM... CRM данные записаны» — значит новый ключ работает. 5) Только после этого отозвать старый.
Ни секунды простоя. Ни одного 401. Бэкап на случай отката — под рукой.
7. «Удалить проект ikigai-analytics» — постой, а зачем?
В списке Supabase у меня оказалось два проекта: основной ikigai-ai-office и второй — ikigai-analytics. Второй был помечен как мусор для удаления. Но я засомневался: вдруг к нему подвешена Yandex Metrica или GTM?
Claude через MCP Supabase проверил: проект активен, 5 таблиц (courses, clients, payments, leads, client_courses) — все пустые, RLS выключен. К GTM/GA4/Yandex Metrica не привязан (да он и не может быть привязан — эта аналитика живёт на Google/Yandex). По всей видимости, это была заготовка под план unified dashboard, которую не доделали.
Решение: не удалять. Завтра разберёмся по git-истории, что это было. Пустой Free-tier проект ничего не стоит. А вот удалить и потом понять, что он был нужен, — будет обидно.
Главный архитектурный инсайт вечера
Пока разбирался со всеми этими пунктами, наконец-то увидел целостную картину пайплайна данных. Tilda-формы отправляют данные в TildaCRM, AmoCRM, SendPulse и Telegram. Серверные cron-скрипты раз в 3 часа читают CRM и перекладывают в Supabase через защищённый ключ. HTML-дашборды читают Supabase только через публичный ключ и Row Level Security.
Клиенты (браузеры, формы Tilda) секретного ключа никогда не видят. Маркетинговая аналитика (GTM, GA4, Yandex Metrica, FB Pixel, Clarity) живёт отдельной жизнью — на уровне сайтов Tilda и облачных систем Google/Yandex. В Supabase она не попадает. И это нормально: разные системы для разных задач.
Что открылось попутно (на завтра)
- Smoke-тест показал warning: cron под пользователем ikigai не может писать в директорию пользователя root. Исторически сложилось, что две учётки работают параллельно. Завтра — аудит: унифицировать на одного user (предположительно ikigai с least privilege), удалить мёртвые процессы.
- Проект ikigai-analytics — разобраться по git-истории и планам, что он должен был делать, и принять решение: использовать / переиспользовать / удалить.
Итог: 7 задач, 1 коммит, 0 поломок
- Закрыто 7 из 7 задач Supabase RLS
- Два ключа ротированы (anon publishable + secret service_role)
- Legacy JWT API keys отключены
- Supabase Security Advisor: 0 issues
- Один git-коммит (f357367) с обновлением HTML, запушен в main
- Ни одной поломанной интеграции
Что забираю с собой
Безопасность инфраструктуры — не про «разобраться с SQL». Это про инвентаризацию: где у тебя живут ключи, кто их читает, что произойдёт, если один из них исчезнет. Вайб-кодер с Claude в проводнике может провести такую инвентаризацию за один вечер. Сам я на это никогда бы не отважился — слишком много незнакомых терминов. Но когда агент говорит: «сейчас grep по eyJhbG на сервере покажет, используется ли старый ключ», — это становится проверяемым шагом, а не магией.
Раньше безопасность для меня была «чёрным ящиком». Теперь это просто ещё одна операционная задача, которую я могу пройти по чек-листу вместе с AI-инженером.
Завтра — аудит серверной инфраструктуры: кто у меня там живёт под какими учётками, что реально работает, что можно удалить. И разборка с загадочным вторым Supabase-проектом. Продолжение следует.
16 апреля 2026
#вайбкодинг #AI #бизнес #предпринимательство #операционнаясистема #IKIGAIpromotion
Мы проводим AI-интенсив за 1 день — 8 часов практики, после которых у вас уже работает Claude Code, подключены Telegram, Gmail, Notion, настроены агенты и автоматизации.
88 000 ₸ · Кол-во мест ограничено · Узнать подробности и записаться →
Хотите глубже? Полное погружение за 23 дня: Программа курса →
Сергей Конев · Со-основатель IKIGAI PROMOTION · Победители Digital Qazaqstan Awards 2026