mirror of
https://github.com/dev993848/lastochka-messenger.git
synced 2026-05-23 13:45:50 +00:00
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:
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: Баг-репорт
|
||||
about: Сообщить об ошибке или неожиданном поведении
|
||||
title: "[BUG] "
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Описание
|
||||
|
||||
Что происходит? Что должно происходить?
|
||||
|
||||
## Шаги для воспроизведения
|
||||
|
||||
1. Открыть ...
|
||||
2. Нажать ...
|
||||
3. Увидеть ошибку
|
||||
|
||||
## Ожидаемое поведение
|
||||
|
||||
Что должно было произойти?
|
||||
|
||||
## Скриншоты / логи
|
||||
|
||||
Если применимо, добавьте скриншоты или текст ошибки из консоли.
|
||||
|
||||
## Окружение
|
||||
|
||||
- **Компонент**: (Web / Android / Desktop / iOS / Сервер)
|
||||
- **Версия / коммит**:
|
||||
- **ОС / браузер**:
|
||||
|
||||
## Дополнительный контекст
|
||||
|
||||
Любые другие детали, которые могут помочь.
|
||||
@@ -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), не этот шаблон
|
||||
- [ ] Потенциальная проблема безопасности
|
||||
- [ ] Недокументированное поведение
|
||||
- [ ] Вопрос о прозрачности (не уязвимость)
|
||||
|
||||
## Контекст
|
||||
|
||||
Ссылки, инструменты анализа, дополнительные находки.
|
||||
@@ -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 / отладочного кода
|
||||
- [ ] Документация обновлена (если нужно)
|
||||
@@ -0,0 +1,29 @@
|
||||
# Правила поведения в сообществе
|
||||
|
||||
## Наши принципы
|
||||
|
||||
Мы хотим, чтобы участие в проекте было комфортным для всех, независимо от уровня опыта, страны, возраста или любых других характеристик.
|
||||
|
||||
Мы ожидаем:
|
||||
- Уважения к другим участникам
|
||||
- Конструктивной критики (направленной на код, а не на людей)
|
||||
- Готовности объяснить своё решение и выслушать чужое
|
||||
|
||||
Мы не принимаем:
|
||||
- Оскорбления и агрессию в любой форме
|
||||
- Троллинг и намеренное провоцирование
|
||||
- Публикацию личных данных других людей без согласия
|
||||
|
||||
## Как это применяется
|
||||
|
||||
Правила действуют во всех пространствах проекта: Issues, Discussions, Pull Requests, Telegram-чат.
|
||||
|
||||
Нарушения сообщайте мейнтейнеру (личное сообщение на GitHub). Реакция: предупреждение → временный бан → постоянный бан.
|
||||
|
||||
## Дух, а не буква
|
||||
|
||||
Правила — не инструмент для бюрократии. Если что-то явно некомфортно — это нарушение, даже если формально не попадает ни под один пункт. И наоборот: строгое следование форме при добрых намерениях — не нарушение.
|
||||
|
||||
---
|
||||
|
||||
За основу взят [Contributor Covenant](https://www.contributor-covenant.org/), адаптированный под наш проект.
|
||||
+158
@@ -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.
|
||||
@@ -1,38 +1,99 @@
|
||||
# 🕊️ Мессенджер «Ласточка»
|
||||
# Ласточка — Мессенджер с открытым исходным кодом
|
||||
|
||||
Защищённый мессенджер с открытым исходным кодом, построенный на базе **Tinode** (Go-сервер) с кастомным фронтендом.
|
||||
Защищённый мессенджер с Telegram-like интерфейсом, построенный на базе [Tinode](https://github.com/tinode/chat) (Go-сервер).
|
||||
Серверы в РФ. Compliance с ФЗ-152.
|
||||
|
||||
## Возможности
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[](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
@@ -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` (по желанию).
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user