# 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.`, внутри — тот же 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` не должен попадать в `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/`) при их реализации.