platform-boundaries

Межі Project Platform

Коротке рішення про поділ сервісів, доступ до спільних колекцій та передачу даних.

Реалізація

№ЧастинаРепозиторійЗадачаМасштабування
00Contracts packagecontracts / @it-monkeys/contractsFrontend-safe interfaces, DTO, schemas та HTTP/RMQ contracts без backend-залежностейPackage, не deployable service
01Backend common packagebackend-common / @it-monkeys/backend-commonAuth middleware, RMQ, errors, logging, Mongo schemas і repositories без бізнес-модулівPackage, не deployable service
02StackstackЯк і зараз: login, users, roles і власні внутрішні модуліПоки без змін
03Project Application APIproject-application-apiОдне HTTP API для нашого frontend та Electron; спільні серверні бізнес-модуліStateless, кілька instances у cluster
04Electronstack-electronУніверсальний workspace оператораОдна desktop-програма на operator
05Electron Runtime / Gatewaystack-electron-gatewayПідключення Electron, socket sessions і передача команд та подійStateful process; спочатку один instance
06Проєктні сервісинові project-*Partner API clients, session/auth, типізовані responses проєкту та справді специфічні operations/workersКожен проєкт масштабується окремо

stack-commons залишається legacy package на час міграції. Нові contracts та backend primitives туди не додаємо; після переходу всіх споживачів package архівується.

Frontend і Electron routes лежать в одному project-application-api, бо мають однаковий stateless runtime та спільні бізнес-модулі. stack-electron-gateway залишається окремим через довгі socket-з’єднання і state операторів.

project-application-api обслуговує наш frontend та Electron. Поточний prototype electron-api у stack-electron-gateway переноситься сюди; у Gateway залишається socket runtime.

HTTP

RouteСервісДоступ
Поточні routesstack і legacy проєктні сервісиЯк зараз
/v2/*project-application-apiНаш frontend та Electron
Без публічного routeproject-*RMQ та внутрішня Docker network

JSON API зберігає HTTP 200. Реальний результат передається в body через code:

{ "success": true, "code": 200, "data": {} }
{ "success": false, "code": 401, "data": null, "message": "Invalid or expired token" }

Stack залишається issuer токенів. project-application-api перевіряє чинний Bearer JWT тим самим secret і записує payload у request.user. Проєктні сервіси project-* Stack token secret не отримують.

Схема

Сервіси та RMQ

flowchart LR
    Front["Наш frontend"] --> Stack["stack<br/>auth · users · roles"]
    Front --> PlatformAPI["project-application-api cluster<br/>frontend · Electron API"]
    Electron["Electron"] --> Gateway["Electron Gateway<br/>connect · socket sessions"]
    Electron --> PlatformAPI

    Stack <--> RMQ{{"RMQ<br/>команди · події"}}
    PlatformAPI <--> RMQ
    Gateway <--> RMQ

    RMQ <--> Projects["Нові проєктні сервіси<br/>Golden · Prime · Chathouse · Udate"]
    Projects -->|"HTTP / GraphQL"| Partners["Партнерські API<br/>Golden · Prime · Chathouse · Udate"]

Великі дані для фронту

flowchart LR
    Partners["Партнерські API"] -->|"raw data"| Projects["Проєктні сервіси"]
    Projects -->|"типізований response проєкту"| PlatformAPI["project-application-api"]
    PlatformAPI -->|"canonical adapter + business flow"| Storage[("Mongo / ClickHouse")]
    Storage -->|"repository read"| PlatformAPI
    PlatformAPI --> Front["Наш frontend"]

RMQ є каналом керування: запустити sync, виконати коротку дію або повідомити про зміну. Mongo і ClickHouse є каналом даних. У поточному Admin/TU vertical slice проєктний сервіс project-* не пише TU: він парсить partner response, project-application-api нормалізує його та виконує canonical business flow. Для майбутніх workers writer визначається окремо для кожної collection.

Колекції

  • Спільні schemas, indexes і repositories описуються один раз у @it-monkeys/backend-common.
  • Сервіси можуть напряму читати спільну БД через repository.
  • Для кожної колекції окремо фіксуємо writer-ів, reader-ів і scope проєкту.
  • Спочатку scope контролює repository; окремі Mongo users/roles можна додати пізніше.
  • Перенесення колекції або БД змінює repository/config, а не бізнес-логіку споживачів.
  • Під час міграції legacy-сервіс читає canonical schema тільки через один compatibility repository; старий Mongoose model не направляємо на нову collection.
  • Owner визначається для capability/поля. Два сервіси не виконують одну partner mutation або зміну одного assignment паралельно.
  • Завершена capability не має постійного dual-write у legacy і canonical collections.

Обмін даними

КаналДля чого
Mongo / ClickHouseCanonical data, великі вибірки й агрегати
RMQКоманди та події з невеликим payload
RedisPartner sessions, online, locks і cache

Великі списки не повертаємо через RMQ: проєктний сервіс project-* записує нормалізовані дані у спільну collection, а споживач читає їх напряму.