SyncBuy - система для помощи группе людей в организации совместных покупок.
- Покупки, участники, задачи: создание, назначение, завершение.
- Фиксация распределения.
- Долги (Intents) и платёжные попытки (Attempts).
- Интеграция с провайдерами: вебхуки (HMAC), авто-обновление статусов.
- Ledger (двухзаписная книга фактов оплаты).
- Отчёты.
- Уведомления (пока Telegram).
- Аутентификация: регистрация/логин через Telegram (внешняя идентичность) и/или пароль.
- API Gateway — входная точка (TLS, JWT, CORS; ограничение частоты запросов).
- Identity Service — регистрация/логин (/auth/register, /auth/token), /me; хранит users и user_identities.
- Purchase Service — покупки, участники, задачи, lock-distribution.
- Calculation Service — расчёт intents (v1: accruals; легко заменить).
- Payments Service — intents/attempts, вебхуки ЮKassa (HMAC + дедупликация), ledger, outbox→Kafka.
- Reporting Service — асинхронные отчёты (jobs).
- Notification Service — подписчик доменных событий, отправка в Telegram.
- Инфраструктура: PostgreSQL (один инстанс, разные схемы), Kafka (events), RabbitMQ (jobs), мониторинг и метрики (Prometheus/Grafana/Jaeger).
/docs
/contracts
public-api.yaml
description.md
usecases.md
README.txt
- Регистрация: POST /auth/register
- Варианты: name+password или provider+proof (Telegram).
- Если внешняя учётная запись уже привязана — возвращается токен существующего user_id (идемпотентно).
- Логин: POST /auth/token
- grant_type: password | external_identity | refresh_token.
- Для external_identity: если внешняя учётка не найдена — ошибка EXT_IDENTITY_NOT_FOUND.
- /me — профиль текущего пользователя по sub в JWT.
-
Kafka: передаёт доменные факты, которые важны многим сервисам (например, «платёж прошёл», «покупка зафиксирована»); слушатели реагируют каждый по-своему — обновляют проекции, шлют уведомления, строят отчёты.
-
RabbitMQ: передает конкретные фоновые задачи «кому-то одному» (например, «собери отчёт» или «отправь напоминание»).
-
Ограничение частоты запросов (rate-limit)
- Применяется в API Gateway.
-
Дедупликация вебхуков платёжного провайдера
- Каждый webhook имеет уникальный event_id.
- Обрабатываем только «первое» событие; последующие с тем же event_id игнорируются.
- Записи живут ограниченное время (покрыть окно возможных ретраев провайдера).
-
Идемпотентность создающих POST-запросов
- Клиент передаёт заголовок Idempotence-Key (UUID).
- Первый POST создаёт сущность и сохраняет «результат по ключу» на ограниченное время.
- Повторный POST с тем же ключом возвращает тот же результат, не создавая дублей.
- Рекомендуемые TTL: покупки/задачи ~10 мин; платёжные попытки ~30 мин; тяжёлые операции (отчёт) до 1 часа.
- Реализуется в самих сервисах, которые создают сущности (Purchase, Payments).
- Метрики: Prometheus.
- Дашборды: Grafana.
- Трейсинг: Jaeger.
- Intent — внутренний долг (payer → payee → amount).
- Attempt — попытка оплатить intent у провайдера.
- Ledger — бухгалтерская книга фактов (двухзаписная).
- Outbox — таблица для надёжной публикации событий в Kafka.
- Idempotence-Key — ключ для защиты создающих POST от дублей.
- Dedup (webhook) — защита от повторной обработки одного и того же event_id.