VFLIN
ВойтиСкачать

docs · docs/50-cloud/DEPLOY.md#0 · перевод от 2026-09-12 · с английской ревизии 4704131cc842

Что сервер видит и чего не видит

прочитано из базы данных работающего сервера: что в открытом виде, что запечатано

0. Что сервер видит и чего не видит — прочитайте, прежде чем что-либо арендовать

Обещание продукта — хранение с нулевым разглашением (zero-knowledge; ADR-0014, ADR-0019): сервер хранит то, что ему нужно для координации, и не может прочитать профиль. Это было перемерено, а не перечитано, 2026-09-04 — запросами к базе данных и листингом bucket после полного круга между двумя устройствами [MEASURED]:

где в открытом виде запечатано / захэшировано (сервер не может прочитать)
accounts адрес почты · флаг totp_enabled · дата создания (S10: для неподтверждённого адреса — время его ПОСЛЕДНЕЙ регистрации: замещающая регистрация перезапускает 24-часовой отсчёт) · 16-байтная соль входа (не секретна по замыслу) · verified_at (S8: когда адрес подтверждён кодом из письма; NULL = зарегистрирован, но не подтверждён — войти нельзя, удаляется через 24 h после последней регистрации) · email_code_failures (бюджет неверных кодов, 0–5) · auth_kdf (S10, ADR-0040: версия вывода сохранённого верификатора — NULL = прежний, auth-v1; метка, записанная вместе с верификатором и объявляемая на login-init, которая говорит клиенту, как выводить, и никогда не позволяет выводить что-либо серверу) password_hash — хэш Argon2id верификатора, выведенного на клиенте, а не парольной фразы (ADR-0019 C1) · totp_seed_enc 60 байт, AEAD под VFLIN_TOTP_KEY
plans (S12) прайс владельца как ДАННЫЕ: код, цена за месяц, потолки (NULL — потолка нет), продаётся ли тариф ещё. Это не про какой-то аккаунт; строка здесь потому, что правка цены не должна быть релизом
email_codes (S8) relay_response + relayed_at (S12, ISSUE-204: что ответил почтовый релей, когда взял письмо, — строка состояния и, у большинства релеев, id очереди. Это про КОНВЕРТ: кода там нет никогда, и именно это владелец предъявляет провайдеру, когда письмо потерялось) · для какого аккаунта код, его назначение (verify — активирует аккаунт; device — допускает одно новое устройство и привязан к хэшу этого устройства), срок действия (15 min), использован ли он — и HMAC под секретом сервера от 6-значного кода (code_hash), а не сам код; строка с NULL вместо аккаунта — это приманка, которую при resend-code оставляет неизвестный или уже подтверждённый адрес, чтобы обе ветви делали одинаковую работу сам код (отправляется один раз, одна попытка, 15 min)
devices id устройства (UUID демона) · имя устройства · когда было в сети последний раз refresh_token_hash (43 символа; сам токен никогда не хранится) · secret_hash (S9, 43 символа: SHA-256 секрета устройства, который последний вход выдал этому устройству, — то, что делает его «знакомым»; заменяется при каждом входе, исчезает с device.revoke, NULL, пока устройство снова не войдёт с кодом из письма; сам секрет никогда не хранится)
profiles_meta id профиля · ключ блоба · хэш содержимого · размер шифртекста · wallets (S12: сколько кошельков держит профиль — число, которое ЗАЯВЛЯЕТ клиент при push/commit, а не считает сервер; именно против него проверяется потолок кошельков в тарифе, то есть потолок ограничивает честного клиента, а не изменённого, и контракт это говорит) · вектор версий (id устройств → счётчики) · fence (S5: fence синхронизационной аренды последнего принятого push, монотонный счётчик — метаданные координации, не выведенные ни из какого открытого текста) · состояние · дата обновления
account_keyrings JSON-конверт: version, параметры KDF (mCost/tCost/pCost), saltKek, реестр ключей устройств (id устройства → 32-байтный открытый ключ подписи), accountPub wrappedMkPassword, wrappedMkRecovery, wrappedAccountPriv (nonce AEAD + шифртекст) · MK-MAC
bucket vflin-blobs для каждого блоба — открытый манифест (VFB1 + JSON): id профиля · id устройства · вектор версий · coreVersion · payloadSize открытого текста · внутренний хэш содержимого — описан в PROFILE_STORAGE_SYNC.md §«манифест (открытый, с защитой целостности)» wrappedDek · sealedRecord (имя / отпечаток / прокси) · полезная нагрузка — AEAD, непрозрачные байты
audit_log, orgs, shares, subscriptions пусты после этого круга: демон никогда не отправляет записи журнала действий (log.append для него недостижим), команда не создавалась, тариф не покупался
password_resets (S4) для какого аккаунта сброс, его срок действия, использован ли он — и хэш отправленного токена (token_hash), а не сам токен; строка с NULL вместо аккаунта — приманка, которую оставляет неизвестный адрес, чтобы reset-init делал одинаковую работу в обеих ветвях сам токен сброса (отправляется один раз, 30 min, одноразовый)
billing_events (S4) для какого аккаунта событие, его тариф/статус, номер заказа у провайдера, когда оно пришло — чтение истории платежей для счетов в кабинете

Итак, оператор с root-доступом к VPS узнаёт: кто завёл аккаунт, сколько у него устройств и профилей, какого размера каждый профиль, какая версия Chromium открывала его последней и когда он менялся. Он не узнаёт ни парольной фразы, ни содержимого профиля, ни cookies, ни отпечатка, ни прокси. Говорите пользователям именно это; не говорите «сервер ничего не хранит».