Как устроено и что хранится
Не обещания «мы всё зашифровали» — а прямые ссылки на то, что реально делает код: где живёт вход в Google, что лежит в базе и сколько, чем зашифрованы мастер-токены, что не хранится никогда, как отключить доступ и какие действуют лимиты частоты.
Где живёт вход в Google
Пароль и второй фактор Google на сервер не попадают. Это не обещание, а свойство схемы: сервер физически не видит пароль, потому что весь вход происходит в браузере на твоей машине.
Скрипт /onboard_local.js открывает настоящий браузер на твоей машине и захватывает одноразовый oauth_token и email после того, как ты сам вошёл в Google и нажал Enter в терминале — сервер этот момент не видит. Дальше ты передаёшь пару {email, oauth_token} инструменту add_account_token (или в POST /v1/onboard/token): сервер обменивает одноразовый токен на мастер-токен через библиотеку gpsoauth, проверяет его одним читающим вызовом и сохраняет уже зашифрованным.
oauth_token одноразовый и живёт минуты. Если обмен не произошёл сразу, токен протухает и процедуру нужно повторить — это не баг, а короткое окно жизни самого токена от Google.
Что хранится и сколько
Ниже — реальные таблицы из service/db.py и файл мастер-токенов, а не пересказ. Один пункт списка — одно поле таблицы.
задачи · jobs
- params — промпт и параметры вызова
- status, error, attempts — что произошло с задачей
- account_used, owner — каким аккаунтом и от чьего имени
- created_at / started_at / updated_at — время постановки, старта, обновления
витрина · showcase
- prompt, model — то, что видно публично на главной
- file, w, h — локальный файл кадра и его размер
- строки нет = публикация включена по умолчанию; отключение — платный тариф, удаляет уже опубликованное, а не прячет
ключи доступа · users
- key_hash — только SHA-256 хэш ключа, сам ключ не хранится нигде
- key_prefix, name — по какому обрезку узнать ключ и как ты его назвал
- active, status — включён ли ключ прямо сейчас
Google-аккаунты · accounts
- email, project, reset_day — какой аккаунт подключён и когда сбрасывается квота
- сам мастер-токен в этой таблице не лежит — он в отдельном зашифрованном файле, смотри следующий блок
вход через Google, GitHub, Telegram · identities
- provider_user_id — неизменный id у провайдера (Google, GitHub или Telegram), ключ записи
- login — для показа и связи: подтверждённая почта у Google, логин у GitHub, @username у Telegram. Привязка не на нём: смена почты или логина не рвёт доступ и не отдаёт его чужому
- пароль, токены доступа провайдера и список контактов — не хранятся: берём только имя и почту или публичный профиль в момент входа
посещения сайта · visits
- vid — хэш адреса и браузера с солью, которая меняется каждый день: посчитать людей за день можно, узнать того же человека завтра — нет
- day, path, source, ref — день, страница и откуда пришли (домен, без полного адреса)
- country, device, lang — страна по локальной базе DB-IP Lite (CC BY 4.0), тип устройства и язык браузера
- сам IP-адрес и строка браузера в этой таблице не хранятся; сторонних счётчиков на сайте нет
откуда пришёл и профиль · owner_source, identity_profiles
- owner_source — канал первого захода, метка кампании, первая страница, чем подключаешься (Claude, Cursor…), страна — один раз, в момент регистрации
- identity_profiles — то, что провайдер входа отдаёт сам: у GitHub публичный профиль (имя, компания, город, сайт), у Google имя, язык и фото, у Telegram имя и фото
- owner_notes — заметки оператора, чтобы помнить договорённости
персонажи · characters
- name, description — как карточка называется и что в ней
- portrait_media_id — какой кадр несёт сходство лица
- entity_id, project, account — карточка в самом Flow
подписка и оплата · subscriptions, payment_orders
- status, until — активна ли подписка и до какого момента
- amount, currency, provider, status — заказ на оплату, без данных карты: их принимает платёжный провайдер, не openFlow
согласие и выход · owner_settings, session_epochs
- terms_accepted_at — когда принял правила
- epoch — счётчик выходов: «выйти» обнуляет разом все ранее выданные сессии этого владельца
Чем зашифрованы мастер-токены
Мастер-токен Google-аккаунта — это полный доступ к нему. Он не в базе данных: он в отдельном файле, зашифрованном AES-256-GCM.
алгоритм
- AES-256-GCM: шифрование и проверка подлинности в одном шаге
- формат значения —
base64(nonce[12] || ciphertext+tag) - подменённый файл не расшифруется тихо в мусор — GCM это заметит
ключ
- лежит отдельно от файла с токенами — утечка одного файла не значит утечку ключа
- права
600, владелецroot - без ключа зашифрованный файл — просто байты
Честно про границу защиты: от человека, получившего root на самом сервере, это не спасает — там ключ читается вместе с данными. Схема защищает от утечки ФАЙЛА (бэкап, rsync, случайный коммит) — это самый вероятный сценарий из двух, но не единственный.
Что не хранится и как отключить доступ
- Пароль и второй фактор Google — сервер их физически не видит, вход целиком проходит в твоём браузере.
- Сам MCP-ключ — в базе только его SHA-256 хэш; ключ показывается один раз в момент выпуска.
- Генерации с твоими загруженными фото (персонаж из фото,
image_inputs, control-изображения) — не попадают в публичную витрину ни при каких настройках и тарифах.
Отозвать один ключ
В кабинете — кнопка у конкретного ключа (/me/keys/{prefix}). Ключ на другой машине продолжает работать: отзыв всегда точечный.
Выключить публикацию
На платном тарифе в кабинете. Уже опубликованные работы удаляются из витрины, а не прячутся.
Отключить Google-аккаунт целиком
В кабинете, раздел «Google-аккаунты» — кнопка × у аккаунта (DELETE /me/accounts/{email}). Генерации через него прекращаются сразу. Зашифрованный мастер-токен при этом остаётся на сервере — чтобы стереть и его, напиши оператору в Telegram.
Метки на сгенерированном
Две разные вещи, и обе стоит знать до генерации, а не после скачивания.
Невидимая метка SynthID — есть всегда
Google встраивает её в каждый кадр и каждый ролик Veo и Imagen. Отключить её нельзя ни настройкой, ни через нас: это метка Google, а не наша. Она не видна глазом, но по ней содержимое определяется как сгенерированное ИИ.
Видимая «искорка» в углу — зависит от аккаунта
С 28 июля 2026 у Flow есть настройка «Visible watermarking» в аккаунте Google, под которым идёт генерация. По умолчанию она выключена не везде: умолчание задаёт регион аккаунта, а в части стран знак нельзя отключить вовсе.
Что делаем мы
Проверяем каждый готовый файл и возвращаем ответ в результате задачи полем visible_watermark. Если посмотреть не смогли — так и пишем, а не выдаём это за «чисто».
На 29 июля 2026 свежие генерации выходят без видимого знака. Ролики, сделанные до 28 июля, «искорку» содержат — они уже сгенерированы, и снять её нельзя.
Лимиты частоты
Очередь одна на всех, но выдача справедливая: следующую задачу получает тот, у кого меньше всего работает сейчас. Поэтому чужая пачка на тысячу генераций не отодвигает твою одну. Пределы ниже — минимумы, и они растут вместе с числом подключённых Google-аккаунтов: за это отвечает service/api.py::_admit, через которую проходит любая постановка задачи.
Логика простая: один аккаунт делает одну генерацию одновременно, поэтому смысл имеет ровно та ёмкость, которую ты подключил. Десять аккаунтов — это десять параллельных генераций и 1200 в час, а не «три, потому что так решили».
Отказ — HTTP 429 с заголовком Retry-After и текстом, который называет предел, текущее число и через сколько секунд отпустит: чужой лимит не тратится, а свой не пропадает молча.
Отдельно от частоты — недельный бесплатный лимит: без подписки 200 картинок и 3 видео в неделю, счётчик обнуляется в понедельник в 00:00 UTC. Упавшие генерации не считаются. Проверку делает
service/api.py::_gate_weekly
Отказ — HTTP 402 с датой сброса и ценой подписки; когда лимит на исходе, агент узнаёт об этом заранее, в ответе на готовую задачу.