From b837254b83d92ea1fd83e3c1bd2d2c2fe23c6a76 Mon Sep 17 00:00:00 2001 From: Anton Budylin Date: Fri, 17 Apr 2026 10:47:37 +0300 Subject: [PATCH] docs: add open-source repository structure for contributors and auditors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .github/ISSUE_TEMPLATE/bug_report.md | 35 +++ .github/ISSUE_TEMPLATE/feature_request.md | 32 +++ .github/ISSUE_TEMPLATE/transparency_audit.md | 30 ++ .github/PULL_REQUEST_TEMPLATE.md | 37 +++ CODE_OF_CONDUCT.md | 29 ++ CONTRIBUTING.md | 158 ++++++++++ README.md | 282 +++++++++++------- SECURITY.md | 72 +++++ docs/ARCHITECTURE.md | 286 +++++++++++++++++++ 9 files changed, 858 insertions(+), 103 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/transparency_audit.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md create mode 100644 docs/ARCHITECTURE.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..58bc348 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Баг-репорт +about: Сообщить об ошибке или неожиданном поведении +title: "[BUG] " +labels: bug +assignees: '' +--- + +## Описание + +Что происходит? Что должно происходить? + +## Шаги для воспроизведения + +1. Открыть ... +2. Нажать ... +3. Увидеть ошибку + +## Ожидаемое поведение + +Что должно было произойти? + +## Скриншоты / логи + +Если применимо, добавьте скриншоты или текст ошибки из консоли. + +## Окружение + +- **Компонент**: (Web / Android / Desktop / iOS / Сервер) +- **Версия / коммит**: +- **ОС / браузер**: + +## Дополнительный контекст + +Любые другие детали, которые могут помочь. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..5632fb2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,32 @@ +--- +name: Предложение функции +about: Предложить новую возможность или улучшение +title: "[FEATURE] " +labels: enhancement +assignees: '' +--- + +## Проблема / мотивация + +Какую проблему решает эта функция? Что сейчас неудобно? + +## Предлагаемое решение + +Опишите, как вы видите реализацию. + +## Альтернативы + +Рассматривали ли другие подходы? Почему этот лучше? + +## Компонент + +- [ ] Web-клиент +- [ ] Android +- [ ] Desktop +- [ ] iOS +- [ ] Сервер +- [ ] Документация + +## Дополнительный контекст + +Скриншоты, ссылки, примеры из других приложений — всё, что поможет понять идею. diff --git a/.github/ISSUE_TEMPLATE/transparency_audit.md b/.github/ISSUE_TEMPLATE/transparency_audit.md new file mode 100644 index 0000000..1e0ce4e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/transparency_audit.md @@ -0,0 +1,30 @@ +--- +name: Аудит прозрачности +about: Вопрос или замечание по открытости кода, безопасности или обработке данных +title: "[AUDIT] " +labels: transparency, security +assignees: '' +--- + +## Компонент + +Какой именно файл / функция / поведение вызвало вопрос? + +## Наблюдение + +Что именно вы нашли или что вам непонятно? + +## Ожидаемое поведение / документация + +Как это должно быть задокументировано или работать, на ваш взгляд? + +## Серьёзность + +- [ ] Критическая уязвимость → используйте [SECURITY.md](../../SECURITY.md), не этот шаблон +- [ ] Потенциальная проблема безопасности +- [ ] Недокументированное поведение +- [ ] Вопрос о прозрачности (не уязвимость) + +## Контекст + +Ссылки, инструменты анализа, дополнительные находки. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..32c23e3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.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 / отладочного кода +- [ ] Документация обновлена (если нужно) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..00acaf5 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,29 @@ +# Правила поведения в сообществе + +## Наши принципы + +Мы хотим, чтобы участие в проекте было комфортным для всех, независимо от уровня опыта, страны, возраста или любых других характеристик. + +Мы ожидаем: +- Уважения к другим участникам +- Конструктивной критики (направленной на код, а не на людей) +- Готовности объяснить своё решение и выслушать чужое + +Мы не принимаем: +- Оскорбления и агрессию в любой форме +- Троллинг и намеренное провоцирование +- Публикацию личных данных других людей без согласия + +## Как это применяется + +Правила действуют во всех пространствах проекта: Issues, Discussions, Pull Requests, Telegram-чат. + +Нарушения сообщайте мейнтейнеру (личное сообщение на GitHub). Реакция: предупреждение → временный бан → постоянный бан. + +## Дух, а не буква + +Правила — не инструмент для бюрократии. Если что-то явно некомфортно — это нарушение, даже если формально не попадает ни под один пункт. И наоборот: строгое следование форме при добрых намерениях — не нарушение. + +--- + +За основу взят [Contributor Covenant](https://www.contributor-covenant.org/), адаптированный под наш проект. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b23a4a3 --- /dev/null +++ b/CONTRIBUTING.md @@ -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. diff --git a/README.md b/README.md index bf43f86..45940dc 100644 --- a/README.md +++ b/README.md @@ -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` diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..751f6ea --- /dev/null +++ b/SECURITY.md @@ -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` (по желанию). diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..34fb484 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -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.