56 lines
4.5 KiB
Markdown
56 lines
4.5 KiB
Markdown
# 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/`) при их реализации.
|