Project

General

Profile

Wiki » History » Revision 4

Revision 3 (Redmine Admin, 07/22/2026 08:21 PM) → Revision 4/8 (Redmine Admin, 07/22/2026 09:53 PM)

# Green Chat 0.2.0 — памятка бета-тестера 

 Спасибо, что участвуете в тестировании Green Chat. Эта памятка объясняет, 
 как подготовиться к бете, что особенно важно проверить в версии 0.2.0 и как 
 составить полезный баг-репорт. 

 # Green Chat Desktop 0.2.1 — Beta Update 

 Дата выпуска: **22 июля 2026 года**. 

 Версия 0.2.1 исправляет проблемы доставки сообщений и уведомлений, 
 обнаруженные во время бета-тестирования 0.2.0. 

 ## Главное 

 - Доставка больше не зависит только от WebSocket-событий. Клиент сверяет 
   локальное состояние с сервером после подключения, при ошибке live-доставки 
   и каждые две минуты, пока соединение активно. 
 - Пропущенные во время офлайна сообщения автоматически догружаются в 
   правильном порядке вместе с необходимыми MLS-коммитами. 
 - Счётчики непрочитанных, список тредов и сохранённые сообщения обновляются 
   после каждой сверки с сервером. 
 - Для сообщений, полученных через фоновую сверку, показывается одно сводное 
   уведомление вместо серии попапов, даже если окно получило фокус сразу после 
   выхода ноутбука из сна. Если звук сообщений включён, сводное уведомление 
   сопровождается нативным звуком. попапов. Настройки DND, mute, quiet hours и режим 
   уведомлений канала продолжают учитываться. 

 ## Исправление личных сообщений после повторного входа 

 - Исправлена ситуация, когда после logout и повторного входа личный чат 
   оставался доступен, но новые сообщения фактически шифровались без устройства 
   собеседника. 
 - Клиент автоматически обнаруживает отсутствующее устройство участника и 
   повторно добавляет его в MLS-группу личного чата. 
 - Одновременное восстановление несколькими устройствами защищено коротким 
   серверным lease: проигравший клиент останавливается до изменения локальной 
   MLS-эпохи. 
 - Пока устройство собеседника ещё не восстановлено в личном чате, поле ввода 
   заменяется сообщением о синхронизации, а отправка временно блокируется. 
   Отметка `✓✓` в этом состоянии заменяется честным предупреждением 
   `not delivered`. 
 - После успешного восстановления чат разблокируется по долговременному 
   состоянию клиента, даже если соответствующее WebSocket-событие потерялось. 
 - Если KeyPackage нового устройства ещё загружается, повторная попытка теперь 
   выполняется через несколько секунд с постепенным увеличением интервала. Чат 
   больше не зависает в состоянии `re-syncing` из-за двухминутного ожидания, 
   которое при каждом перезапуске начиналось заново. 
 - Исправлена ложная блокировка отправки после password login или привязки 
   устройства: старые клиенты создавали пустую MLS BasicCredential, поэтому 
   два реальных листа ошибочно считались одним пользователем. Готовность личного 
   чата теперь проверяется по фактическому MLS roster, а новые устройства 
   сохраняют credential с серверным username. 
 - После выхода ноутбука из сна клиент больше не ждёт до 90 секунд, считая старый 
   WebSocket подключённым. Resume watchdog обнаруживает паузу системных часов, 
   переподключается в течение нескольких секунд, сразу забирает пропущенные 
   сообщения и восстанавливает видимый другим устройствам presence. 

 ## Надёжность и диагностика 

 - Ошибка обработки live-сообщения теперь запускает ускоренную сверку с 
   сервером вместо ожидания следующего переподключения. 
 - Исправлена потеря полной проверки групп, если переподключение совпало по 
   времени с уже выполняющейся фоновой сверкой. 
 - Отложенные reconcile-задачи корректно отменяются при logout. 
 - Desktop-клиент пишет диагностический лог в `glchat.log` в каталоге данных 
   приложения. 
 - Добавлена ротация лога при достижении 5 MiB с сохранением одной предыдущей 
   копии `glchat.log.old`, включая повторную ротацию на Windows. 

 ## Сервер 

 - Добавлены авторизованные endpoints состояния синхронизации: хвосты сообщений 
   по группам и отсутствующие membership-листы. 
 - Добавлен одноразовый lease-token для безопасного восстановления membership. 
 - Добавлена метрика Prometheus для количества обнаруженных membership gaps. 
 - Добавлена миграция `022_membership_repair_claims.sql`. 

 Содержимое сообщений, ключи и настройки уведомлений по-прежнему не передаются 
 серверу в открытом виде. Новые endpoints работают только с уже известными 
 серверу метаданными групп, устройств и последовательностей сообщений. 

 ## Обновление 

 Для проверки исправлений установите **Green Chat Desktop 0.2.1 на все свои 
 устройства**. Сервер также должен быть обновлён и иметь применённую миграцию 
 `022_membership_repair_claims.sql`. 

 Особенно важно повторно проверить: 

 1. получение сообщений после временного отключения сети; 
 2. непрочитанные, звук и системный попап после фоновой догрузки; 
 3. личный чат после logout и повторного входа одного из участников; 
 4. одновременную работу двух устройств одного аккаунта; 
 5. наличие `glchat.log` после перезапуска desktop-приложения. 



 Полный список изменений находится в 
 [changelog версии 0.2.0](beta-changelog-0.2.0.md). 

 # VERSIONS CHANGE LOG ## Перед началом тестирования 

 1. Установите версию **0.2.0 на все свои устройства**. Старые клиенты 
    несовместимы с новой синхронизацией участников каналов и могут работать 
    некорректно. 
 2. Проверьте номер версии в **Settings → Profile**. 
 3. По возможности подготовьте два тестовых аккаунта и два устройства для 
    одного из аккаунтов. Это позволит проверить доставку, роли и 
    мультиустройство. 
 4. Не используйте единственный рабочий аккаунт для сценариев с выходом из 
    системы: logout безвозвратно удаляет историю на текущем устройстве. 
 5. Бета-версия может содержать ошибки. Не отправляйте через неё данные, 
    потеря которых будет критичной. 

 ## Как устроено хранение сообщений 

 Green Chat Desktop 0.2.1Beta Update корпоративный мессенджер со сквозным шифрованием MLS. Сервер 
 хранит сообщения и файлы в зашифрованном виде и не располагает ключами для 
 их чтения. 

 Дата выпуска: **22 июля 2026 года**. Из этого следуют важные ограничения: 

 Версия 0.2.1 исправляет проблемы доставки сообщений - история расшифровывается и уведомлений, хранится на устройствах пользователя; 
 обнаруженные во - сервер и служба поддержки не могут прочитать переписку или восстановить 
   уничтоженные ключи; 
 - выход из аккаунта очищает локальную историю и ключи на этом устройстве; 
 - если выйти со всех устройств, прежнюю историю восстановить будет нельзя; 
 - для поиска ошибки особенно важны точное время бета-тестирования 0.2.0. события, участники, канал и 
   последовательность действий. 

 ## Главное Что особенно важно проверить в версии 0.2.0 

 ### 1. Обычные сообщения и восстановление соединения 

 - Доставка больше не зависит только от WebSocket-событий. Клиент сверяет 
   локальное состояние с сервером после подключения, при ошибке live-доставки 
   Отправьте сообщения в канал и каждые две минуты, пока соединение активно. личный чат. 
 - Пропущенные Проверьте доставку текста, эмодзи, форматирования и ответов в треде. 
 - Полностью отключите сеть на одном из устройств на несколько минут, затем 
   включите её обратно. 
 - Убедитесь, что клиент подключился самостоятельно и получил сообщения, 
   отправленные во время офлайна сообщения автоматически догружаются в офлайна. 
 - Проверьте, что статус online/offline обновляется без повторного открытия 
   правильном порядке вместе с необходимыми MLS-коммитами. канала. 

 Сообщение со статусом `sent`, которое после восстановления соединения так и 
 не появилось у получателя, считается важным багом. 

 ### 2. Треды 

 - Счётчики непрочитанных, список Создайте несколько тредов в разных каналах. 
 - Откройте раздел **Threads** и сохранённые сообщения обновляются проверьте сортировку по последней активности. 
 - Переключите фильтры **All** и **Unread**. 
 - Нажмите на тред в списке и убедитесь, что открылись правильный канал и 
   после каждой сверки исходное сообщение. 
 - Ответьте с сервером. `@mention`, добавьте вложение или перетащите файл в область 
   ответа. 
 - При наличии второго устройства проверьте синхронизацию прочитанности 
   тредов. 

 ### 3. Роли и участники каналов 

 Для сообщений, полученных через фоновую сверку, показывается одно сводное 
   уведомление вместо серии попапов, даже если окно получило фокус полноценной проверки нужны минимум три аккаунта: владелец, модератор и 
 обычный участник. 

 1. Создайте приватный канал и пригласите двух участников. 
 2. Убедитесь, что создатель отмечен как owner. 
 3. Назначьте одного участника модератором и затем снимите роль. 
 4. Проверьте, что owner может приглашать и исключать участников. 
 5. Проверьте, что moderator может управлять обычными участниками, но не 
    владельцем или другим модератором. 
 6. Исключите обычного участника: канал должен сразу после 
   выхода ноутбука исчезнуть у него из сна. Если звук сообщений включён, сводное уведомление 
   сопровождается нативным звуком. Настройки DND, mute, quiet hours 
    интерфейса, а новые сообщения не должны быть доступны. 
 7. Повторно пригласите участника и режим 
   уведомлений канала продолжают учитываться. убедитесь, что устаревшее событие удаления 
    не убирает канал снова. 

 ## Исправление личных сообщений после повторного входа Дополнительно можно проверить выход из канала: 

 - Исправлена ситуация, когда после logout обычный участник и повторного входа личный чат 
   оставался доступен, модератор могут выйти самостоятельно; 
 - owner с другими участниками должен сначала назначить модератора; 
 - при выходе owner владение автоматически переходит назначенному модератору; 
 - из DM выйти нельзя, но новые сообщения фактически шифровались без устройства 
   собеседника. его можно скрыть через **Remove for me**; 
 - Клиент автоматически обнаруживает отсутствующее устройство для публичного канала исключение участника недоступно, поскольку он может 
   вступить обратно самостоятельно. 

 ### 4. Профили 

 - Заполните аватар, должность, описание и 
   повторно добавляет его в MLS-группу личного чата. рабочий телефон. 
 - Одновременное восстановление несколькими устройствами защищено коротким Откройте карточку профиля из сообщения и панели участников. 
 - Проверьте копирование email и телефона. 
 - Измените аватар или данные профиля на одном устройстве и убедитесь, что 
   серверным lease: проигравший клиент останавливается до изменения локальной появились у другого пользователя без перезапуска приложения. 

 Поля профиля видны всем пользователям организации — это справочная информация, 
 а не приватная часть переписки. 

 ### 5. Поиск и действия с сообщениями 

 - Найдите старое сообщение через поиск и перейдите к нему. 
 - Убедитесь, что чат прокрутился к правильному сообщению и выделил его. 
 - Проверьте доступные контекстные действия: ответ, редактирование, сохранение, 
   MLS-эпохи. закрепление и удаление там, где они разрешены. 
 - Пока устройство собеседника ещё не восстановлено Отредактируйте длинное сообщение и ответ в личном чате, треде: поле ввода должно 
   заменяется сообщением о синхронизации, увеличиваться вместе с текстом. 
 - Попробуйте превысить допустимую длину сообщения. Клиент должен показать 
   понятное ограничение, а отправка временно блокируется. 
   Отметка `✓✓` не зависнуть или молча потерять текст. 

 Поиск работает по локально доступной истории устройства. Отсутствие сообщения, 
 которого никогда не было на этом устройстве, само по себе не является багом. 

 ### 6. Файлы, изображения и GIF 

 - выберите файл через кнопку вложения и убедитесь, что он сначала появился в этом состоянии заменяется честным предупреждением 
   `not delivered`. области подготовки к отправке; 
 - После успешного восстановления удалите подготовленный файл, не отправляя сообщение; 
 - перетащите файлы в основной чат разблокируется по долговременному и отдельно в открытый тред; 
 - вставьте изображение из буфера обмена; 
 - отправьте несколько файлов и проверьте, что они остались в исходном чате, 
   состоянию клиента, даже если соответствующее WebSocket-событие потерялось. во время загрузки переключиться на другой канал; 
 - Если KeyPackage нового устройства ещё загружается, повторная попытка теперь 
   выполняется через несколько секунд откройте изображение во встроенном просмотрщике; 
 - проверьте воспроизведение GIF и отсутствие чрезмерной нагрузки интерфейса; 
 - удалите собственное сообщение с постепенным увеличением интервала. Чат 
   вложением и убедитесь, что файл больше не зависает в состоянии `re-syncing` из-за двухминутного ожидания, 
   которое при каждом перезапуске начиналось заново. доступен из чата; 
 - Исправлена ложная блокировка отправки скачайте файл и проверьте его содержимое после password login расшифровки. 

 Ошибки загрузки, повреждённый скачанный файл, вложение в неправильном канале 
 или привязки зависшая подготовка файла считаются багами. 

 ### 7. Сохранённые сообщения и загрузки 

 - Сохраните сообщения из разных каналов через контекстное меню. 
 - Откройте раздел **Saved**, перейдите из него к исходному сообщению и удалите 
   устройства: старые клиенты создавали пустую MLS BasicCredential, поэтому 
   два реальных листа ошибочно считались одним пользователем. Готовность личного 
   чата теперь проверяется по фактическому MLS roster, а новые закладку. 
 - При наличии второго устройства проверьте, что список сохранённых сообщений 
   сохраняют credential с серверным username. синхронизировался. 
 - После выхода ноутбука Скачайте несколько файлов и откройте раздел **Downloads**. 
 - Проверьте действия **Open file**, **Show in folder** и 
   **Remove from history**. 

 Сохранённые сообщения синхронизируются между устройствами и видны только 
 владельцу аккаунта. История загрузок хранится только на конкретном устройстве. 
 Удаление записи из сна клиент больше Downloads не ждёт удаляет сам файл с диска. Файлы, скачанные до 90 секунд, считая старый 
 установки 0.2.0, в историю автоматически не добавляются. 

 ### 8. Уведомления и звук 

 - В **Settings → Notifications** нажмите **Send test**. 
 - Оставьте окно приложения без фокуса и попросите другого тестера отправить 
   WebSocket подключённым. Resume watchdog обнаруживает паузу системных часов, DM — должен появиться системный попап и прозвучать звук. 
 - Проверьте `@mention` в канале. Обычное сообщение без упоминания по умолчанию 
   переподключается не показывает попап. 
 - Отключите звук в течение нескольких секунд, сразу забирает пропущенные настройках и убедитесь, что новые сообщения приходят без 
   сообщения звукового сигнала. 
 - Проверьте DND, mute канала и восстанавливает видимый другим устройствам presence. 

 ## Надёжность quiet hours. 
 - Полностью закройте приложение через tray → **Quit**, отправьте на аккаунт 
   DM и диагностика проверьте email-уведомление, если SMTP включён на сервере. 

 Попапы показывает запущенное приложение. После полного выхода через **Quit** 
 desktop-клиент не может показать системное уведомление; в этом случае для DM 
 может прийти только email. 

 ### 9. Несколько устройств 

 - Ошибка обработки live-сообщения теперь запускает ускоренную сверку Войдите на второе устройство по паролю или привяжите его по QR-коду. 
 - Создайте приватный канал и пригласите пользователя с несколькими активными 
   сервером вместо ожидания следующего переподключения. устройствами. 
 - Исправлена потеря полной проверки групп, если переподключение совпало по Убедитесь, что канал, его название и новые сообщения появились на всех 
   времени устройствах приглашённого. 
 - Проверьте синхронизацию прочитанности, черновиков, сохранённых сообщений и 
   скрытых чатов. 
 - Измените аватар и убедитесь, что он обновился на других клиентах. 
 - Закройте одно устройство, продолжите работу на втором, затем верните первое 
   в сеть и проверьте восстановление состояния. 

 ### 10. Выход со всех устройств 

 Этот сценарий выполняйте только на специально созданном тестовом аккаунте. 
 Перед выходом убедитесь, что клиент подключён к серверу. 

 1. Выйдите из аккаунта на последнем активном устройстве и подтвердите 
    предупреждение об удалении истории. 
 2. У другого пользователя аккаунт должен получить отметку **Logged out** в 
    списке DM, профиле, панели участников и выборе пользователя. 
 3. В существующем DM история должна остаться читаемой, но поле отправки должно 
    замениться предупреждением. 
 4. Создание нового DM с уже выполняющейся фоновой сверкой. вышедшим пользователем должно быть заблокировано. 
 - Отложенные reconcile-задачи корректно отменяются 5. Отправьте в канал сообщение с его персональным `@mention`: сообщение 
    должно отправиться остальным участникам, а автор должен увидеть 
    предупреждение о недоставке упомянутому пользователю. 
 6. Снова войдите этим аккаунтом. Отметка Logged out должна исчезнуть у других 
    пользователей. 

 Повторный вход создаёт новое активное устройство, но не возвращает историю, 
 уничтоженную при logout. 

 ## Что обязательно считать багом 

 - Падение, зависание или бесконечная загрузка приложения. 
 - Desktop-клиент пишет диагностический лог Потеря уже отправленного сообщения или его появление в `glchat.log` в каталоге данных неправильном чате. 
 - Ошибка расшифровки, нечитаемый текст или повреждённый файл. 
 - Получение доступа к чужому каналу, профилю или данным без разрешения. 
 - Возможность обычного участника выполнить действие owner/moderator. 
 - Доступ исключённого участника к новым сообщениям приватного канала. 
 - Расхождение каналов, ролей, сохранённых сообщений или прочитанности между 
   приложения. устройствами, которое не исправляется после переподключения. 
 - Добавлена ротация лога Отсутствие DM или `@mention`-уведомления при достижении 5 MiB с сохранением одной предыдущей выполненных условиях доставки. 
 - Неправильный адресат, канал или тред у вложения. 
 - Неработающая кнопка, обрезанный интерфейс или нечитаемый текст, особенно в 
   копии `glchat.log.old`, включая повторную ротацию на Windows. тёмной теме. 

 Проблемы безопасности, потерю данных и воспроизводимые падения отмечайте 
 приоритетом **High**. 

 ## Сервер Известные ограничения беты 

 - Добавлены авторизованные endpoints состояния синхронизации: хвосты сообщений Вход обычно доступен только по приглашению; вкладки создания свободного 
   по группам и отсутствующие membership-листы. аккаунта может не быть. 
 - Добавлен одноразовый lease-token для безопасного восстановления membership. Автоматического обновления нет — новую версию нужно устанавливать вручную. 
 - Добавлена метрика Prometheus для количества обнаруженных membership gaps. Windows может показать SmartScreen с предупреждением о неизвестном 
   издателе. 
 - Добавлена миграция `022_membership_repair_claims.sql`. Неподписанная macOS-сборка может быть заблокирована Gatekeeper. После 
   переноса приложения в `/Applications` выполните: 

   ```sh 
   xattr -cr "/Applications/Green Chat.app" 
   ``` 

 Содержимое сообщений, ключи - На macOS системные попапы бета-сборки могут отображаться от имени 
   **Script Editor**. 
 - На части серверов отправка файлов и настройки уведомлений по-прежнему не передаются email-уведомления могут быть отключены. 
 серверу - Числовой бейдж учитывает DM и упоминания; обычное непрочитанное сообщение в открытом виде. Новые endpoints работают только с уже известными 
   канале отображается точкой. 
 серверу метаданными групп, устройств - Сообщение `SPKI pin mismatch` после плановой смены серверного ключа требует 
   повторного входа. Клиент намеренно не принимает новый ключ молча. 

 Если поведение не перечислено здесь и последовательностей сообщений. выглядит неправильным, лучше отправить 
 репорт. 

 ## Обновление Как оставить баг-репорт 

 Для проверки исправлений установите **Green Трекер: 
 <https://bug.green-lab.space/projects/greenchat/issues/new>. Регистрация не 
 нужна, репорт можно отправить анонимно. 

 ### Что указать 

 ```text 
 Краткое название: что сломалось и где 

 Шаги: 
 1. … 
 2. … 
 3. … 

 Ожидал: … 
 Получил: … 

 Окружение: 
 - Green Chat Desktop 0.2.1 на все свои 0.2.0 
 устройства**. - ОС и версия 
 - один или несколько аккаунтов/устройств 
 - название канала или DM 
 - точное время события и часовой пояс 

 Особенно важно повторно проверить: Воспроизводится: всегда / иногда / один раз 
 Дополнительно: скриншот или короткое видео 
 ``` 

 Для проблем синхронизации укажите ОС и версию клиента **на каждой стороне**, 
 а также какое устройство было офлайн. 

 Трекер публичный. Не прикладывайте пароли, invite-коды, ключи, приватные 
 логи или скриншоты с конфиденциальной перепиской. Перед отправкой замажьте 
 лишние данные. 

 ### Приоритет 

 | Приоритет | Когда использовать | 
 |---|---| 
 | `Normal` | Большинство ошибок интерфейса и поведения | 
 | `High` | Падение, потеря данных, недоставка сообщений, нарушение прав или безопасности | 
 | `Urgent` / `Immediate` | Не выбирайте без отдельной просьбы команды | 

 ## Быстрая диагностика уведомлений 

 1. получение сообщений после временного отключения сети; Нажмите **Settings → Notifications → Send test**. 
 2. непрочитанные, звук Если тест пришёл, проверьте DND, mute, quiet hours и системный попап после фоновой догрузки; фокус окна. 
 3. личный чат после logout и повторного входа одного из участников; Для канала используйте персональный `@mention`; обычное сообщение может не 
    создавать попап. 
 4. одновременную работу двух устройств одного аккаунта; Если приложение было закрыто через tray → Quit, системного попапа быть не 
    должно. 
 5. наличие `glchat.log` после перезапуска desktop-приложения. 

 ## Если Send test не работает при разрешённых уведомлениях ОС, создайте 
    баг-репорт и обязательно укажите операционную систему. 


 # glchat Desktop 0.2.0 — Beta Update 

 Изменения с 9 по 20 июля 2026 года. 

 ## Новые возможности 

 - Добавлены роли владельца и модератора канала, управление участниками, выход из канала и локальное скрытие чатов. 
 - Появились карточки профилей с аватаром, должностью, описанием и контактами. 
 - Добавлен единый раздел «Треды» со всеми обсуждениями и фильтром непрочитанных. 
 - Сообщения теперь можно сохранять в личные закладки с синхронизацией между устройствами. 
 - Добавлена локальная история загрузок: файл можно открыть, показать в папке или убрать из списка. 
 - Изображения открываются во встроенном просмотрщике, добавлена безопасная анимация GIF. 
 - Изображения из буфера обмена можно вставлять прямо в сообщение. 
 - Добавлены звуковые уведомления о новых сообщениях и настройка звука. 
 - Пользователи, вышедшие со всех устройств, теперь отмечаются в интерфейсе. Перед отправкой им личного сообщения или упоминания показывается предупреждение. 

 ## Улучшения интерфейса 

 - Добавлены контекстные действия для сообщений. 
 - Улучшены редакторы сообщений и ответов в тредах. 
 - Добавлены упоминания пользователей в ответах треда. 
 - Улучшена работа с вложениями: предварительная подготовка, drag-and-drop в треды и удаление отправленных файлов. 
 - Поиск теперь прокручивает чат до найденного сообщения и ограничивает слишком тяжёлые запросы. 
 - Улучшены индикаторы присутствия, подсчёт участников и расположение боковых панелей. 
 - После отправки сообщения чат автоматически прокручивается к нему. 
 - Исправлено восстановление окна приложения из системного трея. 

 ## Исправления и стабильность 

 - Исправлена синхронизация каналов, участников и метаданных между несколькими устройствами. 
 - Восстановлена доставка уведомлений после длительного офлайна. 
 - Статус пользователя обновляется сразу после подключения. 
 - Исправлен учёт непрочитанных сообщений при переключении фокуса окна. 
 - Исключённые каналы сразу удаляются из интерфейса, а устаревшие события больше не удаляют канал после повторного вступления. 
 - Исправлены отображение закреплённых файлов и привязка вложений к исходному чату. 
 - Добавлена корректная обработка максимальной длины сообщений. 
 - Аватары профилей теперь обновляются в реальном времени. 
 - Улучшено восстановление личных чатов после выхода всех участников со всех устройств. 
 - При выходе устройство отзывается на сервере, чтобы не оставлять неактивные устройства и ключи. 

 ## Сервер и эксплуатация 

 - Добавлены Prometheus-метрики для HTTP, WebSocket, PostgreSQL, Redis и Go runtime. 
 - Подготовлены базовые правила мониторинга и алертов. 
 - Улучшена конфигурация TLS для файлового хранилища. 

 Итого: **40 коммитов и 178 изменённых файлов** в ветке `main`.