docs: add open-source repository structure for contributors and auditors

- README.md: rewritten — component status, architecture overview, quick start, transparency section
- SECURITY.md: responsible disclosure policy, data flow transparency, known limitations (no E2E)
- CODE_OF_CONDUCT.md: community guidelines
- CONTRIBUTING.md: contribution workflow (was untracked, now committed)
- .github/ISSUE_TEMPLATE/: bug report, feature request, transparency audit templates
- .github/PULL_REQUEST_TEMPLATE.md: PR checklist
- docs/ARCHITECTURE.md: detailed architecture for code auditors — data flows, open vs closed components, ADRs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Anton Budylin
2026-04-17 10:47:37 +03:00
parent 5dd59fd273
commit b837254b83
9 changed files with 858 additions and 103 deletions
+35
View File
@@ -0,0 +1,35 @@
---
name: Баг-репорт
about: Сообщить об ошибке или неожиданном поведении
title: "[BUG] "
labels: bug
assignees: ''
---
## Описание
Что происходит? Что должно происходить?
## Шаги для воспроизведения
1. Открыть ...
2. Нажать ...
3. Увидеть ошибку
## Ожидаемое поведение
Что должно было произойти?
## Скриншоты / логи
Если применимо, добавьте скриншоты или текст ошибки из консоли.
## Окружение
- **Компонент**: (Web / Android / Desktop / iOS / Сервер)
- **Версия / коммит**:
- **ОС / браузер**:
## Дополнительный контекст
Любые другие детали, которые могут помочь.
+32
View File
@@ -0,0 +1,32 @@
---
name: Предложение функции
about: Предложить новую возможность или улучшение
title: "[FEATURE] "
labels: enhancement
assignees: ''
---
## Проблема / мотивация
Какую проблему решает эта функция? Что сейчас неудобно?
## Предлагаемое решение
Опишите, как вы видите реализацию.
## Альтернативы
Рассматривали ли другие подходы? Почему этот лучше?
## Компонент
- [ ] Web-клиент
- [ ] Android
- [ ] Desktop
- [ ] iOS
- [ ] Сервер
- [ ] Документация
## Дополнительный контекст
Скриншоты, ссылки, примеры из других приложений — всё, что поможет понять идею.
@@ -0,0 +1,30 @@
---
name: Аудит прозрачности
about: Вопрос или замечание по открытости кода, безопасности или обработке данных
title: "[AUDIT] "
labels: transparency, security
assignees: ''
---
## Компонент
Какой именно файл / функция / поведение вызвало вопрос?
## Наблюдение
Что именно вы нашли или что вам непонятно?
## Ожидаемое поведение / документация
Как это должно быть задокументировано или работать, на ваш взгляд?
## Серьёзность
- [ ] Критическая уязвимость → используйте [SECURITY.md](../../SECURITY.md), не этот шаблон
- [ ] Потенциальная проблема безопасности
- [ ] Недокументированное поведение
- [ ] Вопрос о прозрачности (не уязвимость)
## Контекст
Ссылки, инструменты анализа, дополнительные находки.
+37
View File
@@ -0,0 +1,37 @@
## Что сделано
Краткое описание изменений.
Closes #(номер задачи)
## Компонент
- [ ] Web-клиент (`lastochka-ui/`)
- [ ] Android (`lastochka-android/`)
- [ ] Desktop (`lastochka-desktop/`)
- [ ] iOS (`lastochka-ios/`)
- [ ] Сервер (`lastochka-server/`)
- [ ] Документация
## Тип изменений
- [ ] Новая функция
- [ ] Исправление бага
- [ ] Рефакторинг (без изменения поведения)
- [ ] Документация
## Как проверить
1. ...
2. ...
## Скриншоты
(для UI-изменений)
## Чеклист
- [ ] Код компилируется без ошибок
- [ ] Тесты проходят (`npm test` / `./gradlew test`)
- [ ] Нет console.log / отладочного кода
- [ ] Документация обновлена (если нужно)
+29
View File
@@ -0,0 +1,29 @@
# Правила поведения в сообществе
## Наши принципы
Мы хотим, чтобы участие в проекте было комфортным для всех, независимо от уровня опыта, страны, возраста или любых других характеристик.
Мы ожидаем:
- Уважения к другим участникам
- Конструктивной критики (направленной на код, а не на людей)
- Готовности объяснить своё решение и выслушать чужое
Мы не принимаем:
- Оскорбления и агрессию в любой форме
- Троллинг и намеренное провоцирование
- Публикацию личных данных других людей без согласия
## Как это применяется
Правила действуют во всех пространствах проекта: Issues, Discussions, Pull Requests, Telegram-чат.
Нарушения сообщайте мейнтейнеру (личное сообщение на GitHub). Реакция: предупреждение → временный бан → постоянный бан.
## Дух, а не буква
Правила — не инструмент для бюрократии. Если что-то явно некомфортно — это нарушение, даже если формально не попадает ни под один пункт. И наоборот: строгое следование форме при добрых намерениях — не нарушение.
---
За основу взят [Contributor Covenant](https://www.contributor-covenant.org/), адаптированный под наш проект.
+158
View File
@@ -0,0 +1,158 @@
# Участие в проекте «Ласточка»
## Принципы
### Честность
Мы не приукрашиваем статус проекта и не обещаем того, чего нет. Если компонент в статусе «stub» — мы так и пишем. Если E2E-шифрование не реализовано — мы говорим об этом прямо, а не маскируем маркетингом. От контрибьюторов мы ожидаем того же: если задача сложнее, чем казалась, или решение не работает — скажите сразу. Скрытые проблемы убивают проекты быстрее, чем плохой код.
### Открытость
Все решения, обсуждения и дорожная карта публичны. Никаких закрытых встреч для «избранных». Код доступен, документация доступна, задачи доступны. Если у вас есть идея — создайте issue. Если хотите предложить другой подход — создайте PR или начните обсуждение. Мы не требуем согласия со всем, что решено до вас — мы требуем аргументации своей позиции.
### Уважение
Мы работаем с людьми, а не с тикетами. Код ревью — это диалог, а не экзамен. Критика направлена на код, а не на автора. «Я не согласен с этим подходом, потому что...» — нормально. «Это плохой код» — нет.
### Право на ошибку
Все приходят в проект с разным опытом. Если ваш PR отклонили — это не приговор, это объяснение, почему именно так. Если вы не знаете, как подойти к задаче — спросите. Глупых вопросов нет, есть вопросы, которые никто не задал вовремя.
---
## Организация работы
### Задачи
Все задачи ведутся через **GitHub Issues**. Каждая задача:
- Имеет понятное описание **что** нужно сделать и **зачем**
- Помечена приоритетом: `P0` (критический), `P1` (важный), `P2` (обычный), `P3` (можно подождать)
- Помечена меткой компонента: `backend`, `web`, `android`, `ios`, `compliance`, `infra`, `docs`
Если задача кажется размытой — уточняйте в комментариях. Не начинайте работу, пока не поняли, что именно нужно делать.
### Ветвление
- `main` — стабильная ветка, production-ready код
- `develop` — интеграционная ветка, сюда мержатся фичи
- `feature/название` — ваша ветка для работы (создавайте от `develop`)
- `fix/название` — ветка для багфиксов
### Pull Request
1. Создайте ветку от `develop`
2. Пишите осмысленные коммиты: `feat: добавить reply-панель в чат`, а не `update`
3. Перед PR убедитесь, что код компилируется и тесты проходят
4. В описании PR: что сделано, почему так, какие тесты прошли, скриншоты (для UI)
5. Один PR = одна задача. Не мешайте фичу, рефакторинг и фикс в одну кучу
### Code Review
- Каждый PR проходит ревью хотя бы одним контрибьютором
- Ревью — это не «одобрю/отклоню», это «вот здесь проблема, потому что...»
- Автор PR отвечает на комментарии, вносит правки или аргументированно объясняет, почему оставил как есть
- Финальное решение по спорным вопросам — за мейнтейнером, но это крайняя мера
---
## Коммуникация
### Где общаемся
- **GitHub Issues** — конкретные задачи, баг-репорты, фич-реквесты
- **GitHub Discussions** — общие вопросы, идеи, обсуждения архитектуры
- **Telegram-чат** — оперативная коммуникация, вопросы «как тут у вас всё устроено»
- **Документация** — всё, что должно быть зафиксировано, пишем в `docs/` и `instructions/`
Правило: если обсуждение привело к решению — зафиксируйте его в документации. Telegram-чат не является источником истины.
### Как принимать решения
1. **Малые решения** (стиль кода, мелкий рефакторинг, уточнение документации) — принимает тот, кто работает над задачей
2. **Средние решения** (выбор библиотеки, изменение UI-паттерна, добавление нового экрана) — обсуждаются в Discussions или PR, решение принимается с учётом мнений контрибьюторов
3. **Крупные решения** (изменение архитектуры, смена технологии, новый компонент) — обсуждаются публично, решение документируется в `docs/ARCHITECTURE.md` или отдельном ADR (Architecture Decision Record)
---
## Финансирование
### Текущее состояние
Проект финансируется **из личных средств** основателя. Это значит:
- Все серверы (VPS, домены, SSL) оплачиваются лично
- Нет бюджета на оплату труда контрибьюторов
- Нет бюджета на маркетинг, дизайн-заказы, внешние подрядчиков
Мы это не скрываем и не создаём иллюзий.
### Планы
После достижения MVP и проверки гипотезы (есть ли спрос) планируется подача на **грантовую поддержку**:
- Гранты на open-source проекты (Фонд содействия инновациям, IT-гранты)
- Возможно — краудфандинг, если будет востребованность от сообщества
Если грант получен — будет публичная отчётность о расходовании средств.
### Что это значит для контрибьюторов
На текущий момент участие — **волонтёрство**. Вы вкладываете время и опыт в проект, который:
- Открытый — ваш код будет виден всем
- Реальный — это не pet-project, это production-сервис с живыми пользователями
- Портфолио — вы можете указывать это в резюме и показывать код на собеседованиях
Мы не просим работать бесплатно «вечно». Мы просим помочь дойти до точки, где проект сможет привлечь внешнее финансирование.
---
## Роли в проекте
### Контрибьютор
Любой, кто сделал PR и он был смержен. Даёт право:
- Упоминание в списке контрибьюторов
- Право создавать ветки в репозитории
- Право ревьюить чужие PR
### Мейнтейнер
Человек, который принимает решения по направлению (backend, web, android, infra). Обязанности:
- Ревью PR в своём направлении
- Приоритизация задач
- Разрешение технических споров
- Поддержание качества кода
Мейнтейнер — не начальник, а ответственный. Он не раздаёт задачи, а координирует.
### Основатель
Задаёт общее направление, принимает финальные решения по архитектуре, занимается инфраструктурой и финансированием.
---
## С чего начать
1. Прочитайте [`PROJECT_CONTEXT.md`](./PROJECT_CONTEXT.md) — общее понимание проекта
2. Прочитайте [`PLAN.md`](./PLAN.md) — дорожная карта и приоритеты
3. Посмотрите открытые **Issues** — выберите задачу по силам
4. Напишите в комментарии к задаче: «Беру в работу» — чтобы не дублировать
5. Если подходящей задачи нет — создайте Discussion с предложением
---
## Лицензии
| Компонент | Лицензия |
|---|---|
| `lastochka-server` (форк Tinode) | GPL v3 |
| `compliance` (наш сервис) | TBD (отдельная лицензия, не GPL) |
| `lastochka-ui` (Web) | TBD |
| `lastochka-android` (Android) | TBD |
| Документация | CC BY-SA 4.0 |
Лицензии для клиентских компонентов будут определены до начала активной работы контрибьюторов. Если у вас есть мнение по этому вопросу — welcome в Discussions.
+179 -103
View File
@@ -1,38 +1,99 @@
# 🕊️ Мессенджер «Ласточка»
# Ласточка — Мессенджер с открытым исходным кодом
Защищённый мессенджер с открытым исходным кодом, построенный на базе **Tinode** (Go-сервер) с кастомным фронтендом.
Защищённый мессенджер с Telegram-like интерфейсом, построенный на базе [Tinode](https://github.com/tinode/chat) (Go-сервер).
Серверы в РФ. Compliance с ФЗ-152.
## Возможности
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Platform](https://img.shields.io/badge/platforms-Web%20%7C%20Android%20%7C%20Desktop%20%7C%20iOS-lightgrey)](docs/ARCHITECTURE.md)
- **Чаты и группы** — личная переписка, групповые чаты, каналы
- **Медиа** — отправка изображений и голосовых сообщений
- **Поиск пользователей** — по логину, email, телефону
- **Тёмная тема** — автоматическое переключение
- **Офлайн-индикатор** — мониторинг подключения с автопереподключением
- **Reply, edit, delete, forward** — полноценное управление сообщениями
- **Typing indicators** — индикаторы набора в реальном времени
- **Модерация** — бан, мут, пин, управление участниками групп
---
## Платформы
## Содержание
| Платформа | Путь | Статус |
|-----------|------|--------|
| **Web** | `lastochka-ui/` | ✅ Работает |
| **Android** | `lastochka-android-compose/` | ✅ Работает |
| **iOS** | `lastochka-ios/` | ⏳ В разработке |
| **Сервер** | `lastochka-server/` | ✅ Работает |
- [О проекте](#о-проекте)
- [Статус компонентов](#статус-компонентов)
- [Архитектура](#архитектура)
- [Структура репозитория](#структура-репозитория)
- [Быстрый старт](#быстрый-старт)
- [Для контрибьюторов](#для-контрибьюторов)
- [Прозрачность и безопасность](#прозрачность-и-безопасность)
- [Лицензии](#лицензии)
---
## О проекте
**Ласточка** — это опенсорс-мессенджер. Мы не скрываем, что стоит под капотом.
Проект начат одним человеком и сейчас в стадии активной разработки. Фронтенд и Android написаны с нуля; бэкенд — форк Tinode с нашими патчами. Compliance-сервис — отдельный Go-бинарник для работы с ФЗ-152 (не является частью GPL-кода).
Мы открыли код по двум причинам:
1. Хотим, чтобы пользователи могли убедиться: нет скрытых закладок, нет сбора лишних данных.
2. Хотим привлечь разработчиков, которые разделяют ценности приватности и хотят строить что-то реальное.
---
## Статус компонентов
| Компонент | Стек | Путь | Статус |
|-----------|------|------|--------|
| **Web-клиент** | React 18 + TypeScript + Zustand + Tailwind | `lastochka-ui/` | ✅ Рабочий |
| **Android** | Kotlin + Jetpack Compose + Hilt + Room | `lastochka-android/` | ✅ Рабочий |
| **Desktop** | Electron + React + TypeScript | `lastochka-desktop/` | ✅ Сборка Windows |
| **Сервер (Tinode)** | Go (форк), PostgreSQL, Redis, MinIO | `lastochka-server/` | ✅ Docker |
| **iOS** | Swift (форк Tinode iOS) | `lastochka-ios/` | ⏳ В разработке |
---
## Архитектура
```
[Web] [Android] [Desktop] [iOS]
│ │ │ │
└──────────┴───────────┴─────────┘
wss:// (TLS 1.3)
┌──────▼──────┐
│ Nginx │ TLS-терминация, rate limit
└──────┬──────┘
┌───────────┴───────────┐
│ │
┌──────▼──────┐ ┌────────▼────────┐
│ Tinode │ │ Compliance │
│ (Go, форк) │ │ Service (Go) │
│ WebSocket │ │ (не GPL, ФЗ-152)│
└──────┬──────┘ └────────┬────────┘
│ │
┌────┴────┐ ┌────┘
│ │ │
PostgreSQL Redis MinIO ComplianceDB
```
Полная архитектура, схемы данных, принятые решения — в [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
---
## Структура репозитория
```
dev/
├── lastochka-ui/ # Web-клиент (React 18 + TypeScript + Tailwind + Zustand)
├── lastochka-android-compose/ # Android-клиент (Kotlin + Jetpack Compose + Hilt + Room)
├── lastochka-ios/ # iOS-клиент (Swift, форк Tinode)
├── lastochka-server/ # Tinode-сервер (Go, форк)
── README.md # Этот файл
lastochka/
├── lastochka-ui/ # Web-клиент (React 18 + TypeScript + Vite)
├── lastochka-android/ # Android (Kotlin + Jetpack Compose)
├── lastochka-desktop/ # Desktop (Electron + React)
├── lastochka-ios/ # iOS (Swift, форк tinode-ios)
── lastochka-server/ # Tinode-сервер (Go, форк tinode/chat)
├── docs/
│ └── ARCHITECTURE.md # Подробная архитектура для аудиторов
├── CONTRIBUTING.md # Как участвовать в разработке
├── SECURITY.md # Политика безопасности и раскрытия уязвимостей
├── CODE_OF_CONDUCT.md # Правила поведения в сообществе
└── LICENSE # GPL v3
```
---
## Быстрый старт
### Web-клиент
@@ -40,102 +101,117 @@ dev/
```bash
cd lastochka-ui
npm install
cp .env.example .env.local # при необходимости
npm run dev # http://localhost:5173
npm run build # production-сборка
npm run dev # http://localhost:5173
npm run build # production-сборка
```
### Android-клиент
По умолчанию клиент подключается к `wss://app.lastochka-m.ru`. Для локальной разработки:
```bash
cd lastochka-android-compose
./gradlew assembleDebug # сборка APK
./gradlew test # запуск тестов
cp .env.example .env.local
# VITE_TINODE_HOST=localhost:6060
# VITE_TINODE_SECURE=false
```
### Сервер
```bash
cd lastochka-server
go build -o tinode .
./tinode -config tinode.yml
```
### Docker (полный стек)
Полная инструкция по развёртыванию — в [PROJECT_CONTEXT.md](../PROJECT_CONTEXT.md) и [instructions/deploy.md](../instructions/deploy.md).
## Стек технологий
### Web
| Технология | Назначение |
|------------|------------|
| React 18 + TypeScript | UI + типизация |
| Zustand | State management |
| Tailwind CSS | Стилизация |
| Vite | Сборщик |
| tinode-sdk | WebSocket-клиент Tinode |
| lucide-react | Иконки |
### Android
| Технология | Назначение |
|------------|------------|
| Kotlin + Jetpack Compose | UI |
| Hilt | Dependency injection |
| Room | Локальная БД |
| OkHttp | WebSocket + HTTP |
| Coroutines + Flow | Асинхронность |
### Сервер
| Технология | Назначение |
|------------|------------|
| Go 1.21+ | Язык сервера |
| PostgreSQL 16 | Основная БД |
| Redis 7 | Кэш и pub/sub |
| MinIO | S3-совместимое хранилище |
## Архитектура
```
┌─────────────────┐ ┌──────────────────┐
│ Web (React) │ │ Android (Kotlin)│
└────────┬────────┘ └────────┬─────────┘
│ WebSocket (wss://) │
▼ ▼
┌────────────────────────────────────────┐
│ Tinode Server (Go, порт 6060) │
│ • Auth • Messaging • Push • Media │
└────────────┬───────────────────────────┘
┌────────┼────────┐
▼ ▼ ▼
PostgreSQL Redis MinIO (S3)
```bash
cd lastochka-android
# Открыть в Android Studio → Sync Gradle → Run
./gradlew assembleDebug # APK: app/build/outputs/apk/debug/
./gradlew test # unit-тесты
```
Пользователь подключается через WebSocket → Tinode обрабатывает аутентификацию, сообщения, присутствие → медиа хранятся в MinIO → данные пользователей и сообщения в PostgreSQL → кэш в Redis.
### Desktop (Electron)
## Лицензия
```bash
cd lastochka-desktop
npm install
npm run dev:electron # dev-режим
npm run build:electron # сборка installer
```
Серверная часть (форк Tinode) распространяется под **GPL v3**. Клиентские компоненты — см. лицензию в каждом подпроекте.
### Сервер (локально через Docker)
Подробности — файл [LICENSE](./LICENSE) в корне этого репозитория.
```bash
cd lastochka-server
docker compose -f docker/docker-compose.dev.yml up -d
curl http://localhost:6060/v0/health # должен вернуть 200
```
## Участие
---
Мы приветствуем контрибьюторов! Смотрите [CONTRIBUTING.md](../CONTRIBUTING.md) в корневой директории проекта.
## Для контрибьюторов
### С чего начать
Прочитайте [`CONTRIBUTING.md`](CONTRIBUTING.md) — там подробно о процессе работы, ветвлении, ревью и принципах проекта.
1. Прочитайте этот README и [CONTRIBUTING.md](../CONTRIBUTING.md)
2. Посмотрите открытые **Issues** — выберите задачу по силам
3. Напишите в комментарии к задаче: «Беру в работу»
4. Создайте ветку от `develop`, работайте, отправляйте MR
Вкратце:
1. Выберите задачу в **Issues** (метки: `good first issue`, `help wanted`)
2. Напишите в задаче «Беру в работу»
3. Создайте ветку от `develop`: `feature/название` или `fix/название`
4. Откройте PR с описанием: что сделано, как проверить, скриншоты (для UI)
5. Дождитесь ревью
Нет подходящей задачи — создайте Discussion с предложением.
---
## Прозрачность и безопасность
Этот раздел для тех, кто проверяет код на открытость и отсутствие скрытых функций.
### Что сервер получает от клиента
- Учётные данные (логин/пароль) при авторизации — не хранятся в открытом виде
- Сообщения — передаются по WebSocket, хранятся в PostgreSQL на сервере
- IP-адреса — логируются Nginx (стандартное поведение)
- Push-токены — при включении FCM-уведомлений на Android
Клиент **не** отправляет: контакты телефона, геолокацию, метаданные устройства (кроме стандартных HTTP-заголовков).
### Compliance-сервис
Отдельный Go-бинарник (`compliance/`, не в этом репозитории, не GPL). Задача: выполнение требований российского законодательства (ФЗ-152). Хранит:
- Audit-лог действий (append-only)
- Сессионные данные для государственных запросов
Исходный код compliance-сервиса закрыт по юридическим причинам. Это зафиксировано честно, а не скрыто.
### Зависимости
| Компонент | Основные зависимости |
|-----------|---------------------|
| Сервер | [tinode/chat](https://github.com/tinode/chat) (GPL v3), PostgreSQL, Redis |
| Web | tinode-sdk (npm), React, Zustand, Tailwind CSS |
| Android | tinodesdk (jar), Jetpack Compose, Hilt, Room, OkHttp |
| Desktop | Electron, tinode-sdk |
Все зависимости — публичные библиотеки с открытым кодом. Нет проприетарных SDK (кроме FCM для Push, по выбору пользователя).
### Политика безопасности
Уязвимости — в [`SECURITY.md`](SECURITY.md).
---
## Лицензии
| Компонент | Лицензия |
|-----------|----------|
| `lastochka-server` (форк Tinode) | [GPL v3](LICENSE) |
| `lastochka-ui` | Apache 2.0 |
| `lastochka-android` | Apache 2.0 |
| `lastochka-desktop` | Apache 2.0 |
| `lastochka-ios` | Apache 2.0 |
| Документация (`docs/`) | CC BY-SA 4.0 |
Compliance-сервис (`compliance/`) — отдельный проект, не входит в этот репозиторий.
---
## Связь
- **Issues** — баг-репорты, фич-реквесты
- **Discussions** — идеи, обсуждения архитектуры
- **Email** — вопросы к мейнтейнерам
- **Баги и фичи**: [GitHub Issues](../../issues)
- **Обсуждения**: [GitHub Discussions](../../discussions)
- **Уязвимости**: см. [SECURITY.md](SECURITY.md)
- **Сервер**: `app.lastochka-m.ru`
+72
View File
@@ -0,0 +1,72 @@
# Политика безопасности — Ласточка
## Раскрытие уязвимостей
Если вы нашли уязвимость в безопасности — пожалуйста, **не создавайте публичный Issue**.
Напишите на почту мейнтейнера (указана в профиле GitHub) с темой `[SECURITY] Ласточка — краткое описание`.
Мы стараемся ответить в течение 72 часов. После исправления проблема будет раскрыта публично (Coordinated Disclosure).
## Область применения
Этот репозиторий покрывает:
- Web-клиент (`lastochka-ui/`)
- Android-клиент (`lastochka-android/`)
- Desktop-клиент (`lastochka-desktop/`)
- iOS-клиент (`lastochka-ios/`)
- Форк Tinode-сервера (`lastochka-server/`)
Compliance-сервис (`compliance/`) — закрытый компонент, его уязвимости сообщайте тем же способом.
## Что проверять аудиторам кода
### Протокол передачи данных
- Клиент ↔ Сервер: **WebSocket over TLS (wss://)** — стандарт Tinode.
- REST API для загрузки медиа: **HTTPS**.
- Сертификаты: Let's Encrypt, автообновление.
Нет кастомных протоколов, нет дополнительных HTTP-вызовов к третьим сторонам из клиентского кода (кроме FCM на Android — опционально).
### Аутентификация
- Стандартный механизм Tinode: `basic` auth (логин + bcrypt-хэш пароля).
- Сессионные токены хранятся в localStorage (Web) / DataStore (Android). Срок действия — 7 дней.
- 2FA: реализован в Compliance-сервисе (TOTP), не в Tinode-ядре.
### Хранение данных на сервере
- Сообщения и вложения — PostgreSQL, контролируемый нами сервер в РФ.
- Медиафайлы — MinIO (S3-совместимое), тот же сервер.
- Redis — только кэш сессий, TTL 24ч.
### Что клиент НЕ делает
- Не читает контакты телефона.
- Не отправляет геолокацию.
- Не собирает аналитику (нет Google Analytics, Firebase Analytics, Sentry).
- Не использует рекламные SDK.
### Известные ограничения
- **End-to-end шифрование не реализовано.** Сообщения хранятся на сервере в открытом виде (относительно сервера). Это стандартное поведение Tinode. E2E — в планах.
- **Ключи шифрования** находятся у оператора сервера.
- **Compliance-сервис** имеет доступ к метаданным сообщений (по требованию ФЗ-152).
Мы не скрываем эти ограничения и фиксируем их явно.
## Версионирование
| Компонент | Текущая версия |
|-----------|----------------|
| Web-клиент | 0.1.0 |
| Android | 0.1.0 |
| Desktop | 0.1.0 |
| Tinode-сервер (форк) | см. `lastochka-server/go.mod` |
Поддерживается только последняя версия. Уязвимости в старых версиях не исправляются отдельными патчами.
## Благодарности
Исследователи безопасности, ответственно раскрывшие уязвимости, будут упомянуты в `CHANGELOG` (по желанию).
+286
View File
@@ -0,0 +1,286 @@
# Архитектура Ласточки
> Документ для технических аудиторов и разработчиков, изучающих устройство системы.
---
## Содержание
1. [Обзор системы](#1-обзор-системы)
2. [Компоненты и их роли](#2-компоненты-и-их-роли)
3. [Потоки данных](#3-потоки-данных)
4. [Безопасность и шифрование](#4-безопасность-и-шифрование)
5. [Что открыто, что закрыто](#5-что-открыто-что-закрыто)
6. [Зависимости](#6-зависимости)
7. [Принятые архитектурные решения](#7-принятые-архитектурные-решения)
---
## 1. Обзор системы
```
Клиенты
──────────────────────────────────────────────────
[Web] [Android] [Desktop] [iOS]
│ │ │ │
└────┬────┘ │ │
│ └────────┘
│ wss:// (WebSocket + TLS 1.3)
│ https:// (REST для загрузки медиа)
──────────────────────────────────────────────────
Инфраструктура
──────────────────────────────────────────────────
┌─────────────────────────────────────────────┐
│ Nginx │
│ TLS-терминация, rate limiting (req/s), │
│ проксирование на Tinode и Compliance │
└───────────────┬─────────────────────────────┘
┌───────────┴───────────┐
│ │
┌───▼────────────┐ ┌──────▼──────────────┐
│ Tinode Server │ │ Compliance Service │
│ (Go, форк) │ │ (Go, закрытый) │
│ порт 6060 │ │ порт 8080 │
└───────┬────────┘ └──────┬───────────────┘
│ │
┌─────┴──────┐ ┌─────┴──────┐
│ │ │ │
PostgreSQL Redis ComplianceDB MinIO
(сообщения, (сессии, (audit_log, (медиа,
топики, кэш) gov data) файлы)
пользов.)
```
---
## 2. Компоненты и их роли
### lastochka-server (Go, форк Tinode)
**Путь:** `lastochka-server/`
**Лицензия:** GPL v3
**Оригинал:** [github.com/tinode/chat](https://github.com/tinode/chat)
Основной backend для обмена сообщениями. Реализует:
- Протокол Tinode поверх WebSocket (JSON)
- Аутентификацию: `basic` (login/bcrypt-hash)
- Модель данных: Users → Topics (p2p, grp, fnd, me)
- REST API: `/v0/file/u/` — загрузка медиа, `/v0/health` — healthcheck
- Push-уведомления через FCM (опционально)
- Поиск пользователей через `fnd`-топик и теги
**Наши патчи** относительно upstream Tinode:
- Конфигурация для PostgreSQL (вместо MySQL по умолчанию)
- Настройка кластеризации
- MinIO как S3-бэкенд для медиа
Diff от upstream смотрите через `git log` в `lastochka-server/`.
### lastochka-ui (React)
**Путь:** `lastochka-ui/`
**Лицензия:** Apache 2.0
**Стек:** React 18 + TypeScript + Zustand + Tailwind CSS + Vite + tinode-sdk
Написан с нуля. Не является форком Tinodius или другого официального клиента.
Ключевые части:
| Путь | Назначение |
|------|-----------|
| `src/lib/tinode-client.ts` | Singleton-обёртка над tinode-sdk |
| `src/store/` | Zustand stores: auth, chats, ui |
| `src/components/chat/` | Основной UI чата |
| `src/components/admin/` | Панель администратора |
| `src/hooks/` | useMessages, useTyping, useOnlineStatus |
### lastochka-android (Kotlin + Compose)
**Путь:** `lastochka-android/`
**Лицензия:** Apache 2.0
MVVM-архитектура:
```
UI (Compose) → ViewModel → Repository → TinodeHttpClient (OkHttp WebSocket) + Room DB
```
**Не является форком** Android-клиента Tinode (Tindroid). Написан с нуля с использованием tinodesdk.jar.
### lastochka-desktop (Electron)
**Путь:** `lastochka-desktop/`
**Лицензия:** Apache 2.0
Electron-обёртка над той же кодовой базой, что и `lastochka-ui`, с адаптациями:
- Нативные уведомления ОС
- Автозапуск
- Tray-иконка
### lastochka-ios (Swift)
**Путь:** `lastochka-ios/`
**Лицензия:** Apache 2.0
**Основа:** форк [tinode/ios](https://github.com/tinode/ios)
Статус: ⏳ В разработке. Адаптация официального iOS-клиента Tinode.
### Compliance Service
**Путь:** не в этом репозитории
**Лицензия:** проприетарная (не GPL)
Отдельный Go-сервис. Назначение: выполнение требований ФЗ-152 (хранение audit-лога, TOTP 2FA для государственных запросов). Хранит метаданные — не содержимое сообщений.
Причина закрытости: юридические требования и ограничения.
---
## 3. Потоки данных
### Отправка текстового сообщения
```
Пользователь вводит текст → UI (Zustand store)
→ tinode-sdk.publish(topic, drafty_content)
→ WebSocket → Nginx (TLS) → Tinode Server
→ PostgreSQL: INSERT INTO messages
→ Tinode Server → WebSocket → получатель
```
Сообщение никогда не проходит через Compliance-сервис.
### Загрузка изображения
```
Пользователь выбирает файл → сжатие на клиенте (canvas API)
→ multipart POST /v0/file/u/ → Tinode Server
→ MinIO (S3) → возвращает URL
→ tinode-sdk.publish с ref на URL
```
### Авторизация
```
login/password → tinode-sdk.loginBasic()
→ WebSocket hi + login пакеты → Tinode Server
→ bcrypt.Compare(password, hash) в PostgreSQL
→ session token (JWT-подобный) → localStorage / DataStore
```
### Поиск пользователей
```
Запрос → tinode-sdk.subscribe('fnd', ...) + setMeta(query)
→ Tinode Server → PostgreSQL: SELECT ... WHERE tags @> ARRAY[query]
→ результаты топиков → клиент
```
---
## 4. Безопасность и шифрование
### Transport Security
- **TLS 1.3** на всём входящем трафике (Nginx с Let's Encrypt)
- HSTS preload, HSTS max-age=31536000
- Заголовки: `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`, `Content-Security-Policy`
### Хранение паролей
- bcrypt с cost factor 11 (в Tinode по умолчанию)
- Пароль никогда не хранится в открытом виде
### Сессионные токены
- Tinode генерирует собственные токены (см. `lastochka-server/server/auth/`)
- Срок жизни: 7 дней по умолчанию
- Хранение: localStorage (Web), DataStore (Android)
### E2E шифрование
**Не реализовано.** Сообщения хранятся на сервере в незашифрованном виде.
Это стандартное поведение Tinode. E2E — в backlog.
### Rate Limiting
- Nginx: 100 req/s per IP на `/v0/`
- Compliance: 10 req/s per IP (chi-rate)
---
## 5. Что открыто, что закрыто
| Компонент | Статус | Обоснование |
|-----------|--------|-------------|
| `lastochka-server/` | Открыт (GPL v3) | Форк открытого Tinode, GPL обязателен |
| `lastochka-ui/` | Открыт (Apache 2.0) | Наш код |
| `lastochka-android/` | Открыт (Apache 2.0) | Наш код |
| `lastochka-desktop/` | Открыт (Apache 2.0) | Наш код |
| `lastochka-ios/` | Открыт (Apache 2.0) | Форк открытого tinode/ios |
| Compliance Service | **Закрыт** | Юридические требования ФЗ-152 |
| Конфигурация production (`.env`) | **Закрыта** | Секреты (ключи, пароли) |
| Nginx-конфиг production | Закрыт | IP-адреса серверов |
---
## 6. Зависимости
### Tinode-сервер (Go)
Основные внешние зависимости из `lastochka-server/go.mod`:
- `jackc/pgx` — PostgreSQL драйвер
- `go-redis/redis` — Redis клиент
- `minio/minio-go` — MinIO/S3 клиент
- `appleboy/go-fcm` — Firebase Cloud Messaging
### Web-клиент (npm)
Основные из `lastochka-ui/package.json`:
- `tinode/tinode-sdk` — официальный SDK Tinode
- `react` 18 — UI framework
- `zustand` — state management
- `tailwindcss` — стили
- `lucide-react` — иконки
Нет: аналитических SDK, рекламных библиотек, трекеров.
### Android
Основные:
- `tinodesdk.jar` — официальный SDK Tinode для Android
- `androidx.compose.*` — Jetpack Compose
- `com.google.dagger:hilt` — DI
- `androidx.room.*` — локальная БД
- `com.squareup.okhttp3` — WebSocket
Нет: Firebase Analytics, Crashlytics, рекламных SDK.
FCM (`firebase-messaging`) — только для push-уведомлений, опционально.
---
## 7. Принятые архитектурные решения
### ADR-001: PostgreSQL вместо MySQL
Tinode поддерживает оба. Выбран PostgreSQL из-за лучшей поддержки массивов (для тегов поиска `users.tags @>`) и более широкого распространения в РФ-хостинге.
### ADR-002: Compliance-сервис как отдельный бинарник
Не встроен в Tinode-форк, чтобы:
1. Не загрязнять GPL-код проприетарной логикой
2. Независимое масштабирование
3. Возможность аудита Tinode-форка отдельно от compliance-логики
### ADR-003: Web-клиент написан с нуля (не форк Tinodius)
Официальный веб-клиент Tinode (Tinodius) использует AngularJS. Мы выбрали React + TypeScript для более современного стека и glassmorphism-дизайна.
### ADR-004: Android написан с нуля (не форк Tindroid)
Tindroid (официальный Android-клиент) использует XML layouts + Java. Мы выбрали Kotlin + Jetpack Compose для современного Material 3 UI.
### ADR-005: MinIO для медиа
Избегаем зависимости от облачных провайдеров (AWS S3, GCS). MinIO развёрнут на том же сервере, совместим с S3 API.