# Технологічний стек логістичної біржі — рішення v1.0

Документ фіксує вибір мов і технологій для production-рерайту Trans-Atlas як біржі з шістьма видами транспорту. Він узгоджений із рамковим ТЗ (`ТЗ-рамкове-логістична-біржа.md`) і додатком A (`ТЗ-алгоритм-пошуку-вантажів-і-маршрутів.md`): серверна СУБД як єдине джерело істини, PostgreSQL + PostGIS, кеш у пам'яті, контракти через JSON Schema та перевірки в CI.

## 1. Рішення в одному погляді

| Шар | Вибір | Мова | Чому саме так |
|---|---|---|---|
| Frontend | Next.js (App Router) + React + TypeScript | TypeScript | SSR/ISR для SEO-розділів біржі (вимоги SEO рамкового ТЗ), клієнтські таблиці заявок, один тип-контракт із бекендом |
| UI-шар | Tailwind CSS + Radix UI + TanStack Table/Query | TypeScript | Щільні табличні інтерфейси біржі, доступність, серверний кеш замість `localStorage` |
| Основний backend (API, домен) | NestJS на Node.js 24 LTS | TypeScript | Одна мова з фронтендом, модульність під розділи транспорту, зрілі валідація/DI/OpenAPI |
| ORM / доступ до даних | Prisma для CRUD + чистий SQL (`pg`) для геозапитів | TypeScript / SQL | PostGIS-функції та ранжування пишуться SQL-ом, не ORM-абстракцією |
| Пошук маршрутів (модуль SEARCH) | окремий сервіс на Go | Go | Обхід графа магістраль→фідери, `POST_DRONE`, збір і ранжування всіх варіантів; передбачувана латентність і паралелізм |
| Геодані та відстані | PostgreSQL 18 + PostGIS; OSRM або Valhalla для авто-плеча | SQL / C++ (готові сервіси) | Радіусний пошук для дрон-плеча, реальні дорожні відстані замість «по прямій» |
| СУБД | PostgreSQL 18 (Patroni або керований кластер) | SQL | Транзакційна цілісність угод, ставок, ескроу; JSONB для шаблонів заявок |
| Кеш і черги коротких задач | Redis 7 (кеш, rate limit, ідемпотентність) | — | Вимога A.4/A.11; кеш конекторів погоди та кордонів |
| Шина подій | Kafka (або Redpanda) | — | Ставки, статуси угод, аудит, вебхуки партнерам; ordered log під фінансові події |
| Повнотекстовий пошук / фільтри | PostgreSQL FTS на MVP → OpenSearch за потреби | SQL | Не вводити ще один кластер, поки Postgres тримає навантаження |
| Реальний час (ставки, чат) | WebSocket через Socket.IO або native `ws` + Redis pub/sub | TypeScript | Онлайн-стрічка заявок і ставок |
| Платежі, валюти, ескроу | окремий сервіс `settlement` на Node.js/TypeScript, decimal-арифметика | TypeScript + SQL | Валюта ціни ≠ валюта оплати: ставка, договір, платіж, курс, джерело курсу, комісія зберігаються окремими полями |
| Web3-шар (опційний) | Solidity + Foundry, EVM-мережа L2, стейблкоїн-виплати | Solidity | Смартконтрактне ескроу як додатковий розрахунковий шар, а не заміна фіатної бухгалтерії |
| Аналітика та BI | ClickHouse (події) + Metabase/Power BI поверх | SQL | Оперативна аналітика без навантаження на OLTP |
| ML/прогноз ставок і попиту | Python (FastAPI, pandas, scikit-learn/LightGBM) | Python | Окремий сервіс, викликається API; не змішується з доменним бекендом |
| Інфраструктура | Docker + Kubernetes (керований) або Nomad; Terraform | HCL / YAML | Один спосіб опису середовищ, узгоджений із наявним CI-підходом |
| CI/CD і контракти | GitHub Actions + JSON Schema + мутаційні тести + `bash -euo pipefail` | YAML / Python | Продовження вже перевіреного контрактного CI проєкту TA |
| Спостережуваність | OpenTelemetry → Grafana (Loki, Tempo, Prometheus), Sentry | — | Трасування пошуку маршрутів і платіжних операцій end-to-end |

Node.js 24 «Krypton» — поточна LTS-лінія ([nodejs.org](https://nodejs.org/en/blog/release/v24.14.1)), а Node.js 26 переходить у LTS у жовтні 2026 за новим графіком «один мажор на рік» ([графік релізів Node.js](https://nodejs.org/en/blog/announcements/evolving-node-js-release-schedule)), тому 24 — безпечна база на старт із запланованим переходом на 26. PostgreSQL 18 доступний як стабільна лінія з регулярними патчами ([PostgreSQL](https://www.postgresql.org/about/news/postgresql-18-released-3142/)).

## 2. Чому TypeScript як основна мова

- Один тип-контракт від бази до інтерфейсу: схеми Zod/JSON Schema генерують і валідацію API, і типи фронтенду — це прямо підтримує вашу практику перевірних контрактів замість описового ТЗ.
- Найбільший ринок наймання в Україні та ЦСЄ для вебпродукту такого класу; одна команда покриває фронт і бек на MVP.
- Демо-прототип і локальний Node.js-сервер TA (погода, кордони, довідник, Q&A) переносяться у production-сервіси без зміни мови — конектори лише отримують нормальні залежності, кеш і планувальник.

Обмеження TypeScript чесно позначено: важкий обхід графа маршрутів і масові розрахунки відстаней у Node дають нестабільну латентність під навантаженням. Саме тому пошук виділено в Go.

## 3. Чому Go для модуля SEARCH

- Алгоритм за блок-схемою № 3.1.1 збирає **всі** варіанти (магістраль + фідери + `POST_DRONE`) і ранжує їх — це паралельний fan-out із дедлайнами; горутини й `context` роблять це прямо, без пулів воркерів.
- Один статичний бінарник, низьке споживання пам'яті, прогнозований GC — важливо для сервісу, який викликається на кожен запит користувача.
- Контракт між API і SEARCH — gRPC + protobuf або HTTP + JSON Schema; у CI він перевіряється тими самими мутаційними тестами, що вже працюють у TA.

Rust розглянуто і відкладено: виграш у продуктивності на цьому класі задач не компенсує складність наймання і швидкість ітерацій на етапі MVP. Точка перегляду — якщо SEARCH стане вузьким місцем із стабільним профілем навантаження.

## 4. Що навмисно **не** обрано

| Відкинуто | Причина |
|---|---|
| PHP/Laravel монолiт | Слабший шлях до реального часу й до окремого високонавантаженого сервісу пошуку |
| Java/Spring | Придатний і надійний, але дорожчий у наймі та повільніший в ітераціях для команди вашого розміру |
| Python як основний backend | Залишено лише для ML і аналітики; для OLTP-домену з ескроу типізований TypeScript зручніший у контрактному CI |
| MongoDB як основна база | Угоди, ставки, ескроу потребують транзакцій і обмежень цілісності |
| Vector DB на старті Q&A | У TA вже працює локальне retrieval по курованих `wiki.json`/`outputs.json` — це MVP-достатньо |
| Повністю on-chain біржа | Юридично значущі документи й фіатні платежі лишаються off-chain; блокчейн — опційний розрахунковий шар |
| `localStorage` як сховище предметних даних | Пряма заборона рамкового ТЗ; допустимий лише втрачуваний UI-стан |

## 5. Мапа сервісів MVP

```
web (Next.js, TS)
  └─ api-gateway (NestJS, TS) ── OpenAPI + JSON Schema
       ├─ identity (KYB, тризрівневий онбординг, права на розділи транспорту)
       ├─ exchange (заявки, лоти, ставки, рейтинги)  ── Kafka
       ├─ settlement (валюта ціни / валюта оплати, курс + джерело курсу, комісія, ескроу)
       ├─ search (Go)  ── PostGIS, OSRM/Valhalla, Redis
       ├─ connectors (погода, кордони, довідники) ── Redis-кеш, деградація по джерелу
       └─ qa-portal (raw → wiki → outputs, цитати й статус перевірки)
PostgreSQL 18 + PostGIS · Redis · Kafka · ClickHouse · S3-сумісне сховище документів
```

Правило: `settlement` — єдиний сервіс, що має право створювати фінансові проведення; усі інші публікують події.

## 6. Черговість запуску

| Етап | Що входить | Технологічний приріст |
|---|---|---|
| Етап 1 (0–3 міс.) | Заявки, ставки, профілі, права на розділи, UK/EN/PL/DE, платна реєстрація | Next.js, NestJS, PostgreSQL+PostGIS, Redis, GitHub Actions |
| Етап 2 (3–6 міс.) | Модуль SEARCH за блок-схемою 3.1.1, `POST_DRONE`, реальні дорожні відстані | Go-сервіс, OSRM/Valhalla, gRPC-контракт |
| Етап 3 (6–9 міс.) | Мультивалютні угоди, ескроу, e-invoicing, локальні виплати (окреме українське плече для UAH) | `settlement`, decimal-арифметика, PSP-інтеграції |
| Етап 4 (9–12 міс.) | Аналітика, рейтинги на даних, прогноз ставок, вебхуки партнерам | ClickHouse, Python-ML, Kafka Connect |
| Етап 5 | Смартконтрактне ескроу й оракули підтвердження доставки | Solidity + Foundry, L2 |

## 7. Критерії приймання вибору стека

1. Жоден предметний запис не зберігається у сховищі браузера; очищення браузера не втрачає даних учасника.
2. Кожен публічний API-ендпойнт має JSON Schema, і мутація схеми валить CI.
3. Контракт між `api-gateway` і `search` перевіряється окремим негативним pull request (перейменування поля або job має блокувати злиття).
4. Пошук повертає **зібраний і ранжований** набір варіантів; тест підтверджує, що обхід не завершується після першого знайденого маршруту.
5. Дрон-варіант додається як альтернатива останнього авто-плеча і **не видаляє** авто-варіант.
6. В угоді ставка, договір, платіж, курс, джерело курсу, комісія та стан ескроу зберігаються окремими полями; тест на застарілий курс падає.
7. Деградація одного зовнішнього конектора дає частковий результат, а не помилку всієї сторінки.
8. Усі bash-кроки конвеєра виконуються з `bash -euo pipefail` (правило R10).

## 8. Наступний крок

Логічне продовження — розкласти цей стек у скелет репозиторію: `docker-compose` для локального середовища, міграції PostGIS для довідника `points`, protobuf-контракт `search`, і чотири GitHub Actions job з фіксованими іменами status checks під branch protection.

---

**Примітка щодо демо-сайту Trans-Atlas.** Сторінка «Технологічний стек» на сайті документує це рішення як довідкову інформацію, а не впроваджений стек: жоден із перелічених сервісів (Next.js, NestJS, Go, Kafka, ClickHouse, Kubernetes, Solidity) не розгорнутий у цьому проєкті. `index.html` лишається тим самим односторінковим файлом без збірки. Сторінка «Бекенд: Спринт 0» — перший виконаний і перевірений шматок цього ширшого плану (лише шар PostgreSQL/NestJS/Redis з розділу 1 вище, і поки що теж лише як специфікація з перевіреними артефактами, без реального розгортання).
