LoVisual/backend/STRUCTURE.md

56 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Backend Structure (продумано заранее, 2026-09-23)
Rust workspace (`backend/Cargo.toml`), один сервис — один крейт. Планировка
на все три подсистемы платформы (см. `TODO.md`, Фаза 10) сразу, чтобы не
переизобретать layout при переходе от Подсистемы 1 к 2/3.
```
backend/
Cargo.toml # workspace root — members растёт по мере реализации
STRUCTURE.md # этот файл
common/ # РЕАЛИЗОВАН — общий контракт: JWT, внутренние заголовки,
# proto/accounts.proto (gRPC AuthenticateDevice,
# GetPublicProfiles для авторов витрины)
accounts-service/ # РЕАЛИЗОВАН — backend/PLAN.md (Подсистема 1, часть 1)
gateway/ # РЕАЛИЗОВАН — gateway/PLAN.md: единственная публичная
# точка, identity, рейт-лимиты, CORS, reverse proxy
configs-service/ # РЕАЛИЗОВАН — configs-service/PLAN.md: 4 слота конфигов,
# share-коды, витрина publish/browse/detail/copy
# (Подсистема 1, часть 2)
chat-service/ # РЕАЛИЗОВАН ЧАСТИЧНО — chat-service/PLAN.md: сейчас только GUI presence
# (в памяти, POST /presence/gui); RPC-чат, друзья, виджеты-телеметрия
# (Подсистема 2) позже, там будет WebSocket.
addons-registry/ # ПЛАН НЕ НАПИСАН — витрина аддонов, версии,
# публикация/модерация (Подсистема 3)
```
## Внутренний контракт (gateway ↔ сервисы)
Гейтвей — единственная публичная точка: он один раз резолвит вызывавшего
(JWT-access или `lvd_`-device-токен через gRPC `AuthenticateDevice`) и кладёт
аккаунт в заголовок `x-lovisual-account-id`; каждый запрос несёт общий секрет
`x-lovisual-internal-key`. Сервисы отвергают всё без этого ключа (403), поэтому
напрямую в них стучаться бесполезно. Снаружи — только REST/JSON на `api.<domain>`,
внутри — тот же REST сервисов + gRPC там, где публичного REST нет.
## Почему не добавлены в `[workspace] members` сразу
Пустой крейт без реализации — то же самое "без пустышек", что запрещено
правилами мода (см. `TODO.md`) — просто в Rust-обёртке: `cargo build
--workspace` не должен спотыкаться о нереализованные заглушки. Каждый
сервис входит в `members` в своём implementation-плане первым шагом (как
`accounts-service` в Task 1 `backend/PLAN.md`), не раньше.
## Общий код между сервисами (`common`, создан 2026-09-24)
Второй реальный потребитель появился вместе с `gateway`, поэтому общий код
уже вынесен: JWT `Claims`/`issue_access_token`/`verify_token`/`bearer_token`,
внутренний контракт (`require_internal_key`, `GatewayIdentity`, gRPC-перехватчики
ключа) и `proto/accounts.proto`. Следующий кандидат — типовой `AppError`:
сознательно НЕ вынесен, т.к. маппинг `From<sqlx::Error>` сервис-специфичен,
а `sqlx` не должен попадать в `gateway` (см. Global Constraints
`configs-service/PLAN.md`).
## Модульная структура внутри сервиса (эталон — `accounts-service`)
Домен, не технический слой: `auth/`, `accounts/`, `device/`, `avatars/` —
каждый со своими `mod.rs`/`handlers.rs`/`repo.rs` и т.п. (см. File Structure
в `backend/PLAN.md`). Тот же принцип — для `configs-service` (`slots/`,
`sharing/`, `showcase/`) и `chat-service` (`chat/`, `friends/`,
`telemetry/`) при их реализации.