Потоки даних
Критичні наскрізні сценарії, відомі провайдери підставлені (Monobank, Google OAuth, Cloudflare Origin Pulls, Typesense).
Автентифікація — Google OAuth + JWT
Section titled “Автентифікація — Google OAuth + JWT”sequenceDiagram
actor U as Абітурієнт
participant W as Abitly Web
participant A as Abitly API (NestJS)
participant G as Google OAuth
participant DB as Postgres (shared)
U->>W: Login → Google
W->>G: redirect OAuth (client_id, redirect_uri)
G-->>U: вибір акаунту, consent
U->>G: підтверджує
G-->>W: callback з code
W->>A: POST /auth/google {code}
A->>G: exchange code → tokens
G-->>A: id_token / refresh_token
A->>DB: upsert user
A-->>W: JWT access + refresh cookies
W-->>U: авторизовано
Альтернатива: Telegram login через бот (Telegraf auth сцена) — бот пише в API з payload, який підтверджує особу через Telegram-підпис.
Оплата — Monobank
Section titled “Оплата — Monobank”sequenceDiagram
actor U as Абітурієнт
participant W as Web / Mini App
participant A as Abitly API
participant M as Monobank API
U->>W: Обирає Premium / Token purchase
W->>A: POST /payments/create {plan}
A->>M: create invoice (MONOBANK_TOKEN)
M-->>A: invoiceId + paymentUrl
A-->>W: paymentUrl
W-->>U: redirect на Monobank checkout
U->>M: оплачує
M-->>A: webhook (SUBSCRIPTION_WEBHOOK_URL / PREMIUM_WEBHOOK_URL / TOKEN_PURCHASE_WEBHOOK_URL)
A->>A: verify signature, активувати підписку
A-->>W: redirect (SUBSCRIPTION_REDIRECT_URL / ...)
Контент Strapi — через Cloudflare Authenticated Origin Pulls
Section titled “Контент Strapi — через Cloudflare Authenticated Origin Pulls”sequenceDiagram
actor U as Абітурієнт
participant W as Abitly Web
participant CF as Cloudflare proxy
participant S as Strapi (EC2)
participant DB as Postgres
U->>W: Відкриває сторінку ЗВО
W->>CF: GET /api/universities/...
CF->>S: запит з origin-cert<br/>(валідація ORIGIN_PULL_CA)
S->>S: перевірка cert OK
S->>DB: SELECT (схема strapi)
DB-->>S: рядки
S-->>CF: JSON
CF-->>W: cached / fresh
W-->>U: відрендерена сторінка
403 від Strapi → найімовірніше прострочений CF origin-cert. Деталі → domains-dns.
Telegram bot + Mini App
Section titled “Telegram bot + Mini App”sequenceDiagram
actor U as Користувач
participant T as Telegram API
participant B as Bot (Telegraf · Railway)
participant A as Abitly API
participant M as Mini App (Next.js · Railway)
U->>T: /start
T->>B: update (webhook / polling — TODO)
B->>A: getOrCreate user
A-->>B: user data
B->>T: sendMessage with web_app button
T-->>U: повідомлення + кнопка
U->>T: tap «Open App»
T->>M: launch Mini App with initData
M->>A: POST /telegram/auth {initData}
A->>A: verify HMAC(initData, bot_token)
A-->>M: JWT
M-->>U: інтерактивний UX
Аналітика — lake-house
Section titled “Аналітика — lake-house”sequenceDiagram
participant W as Abitly Web
participant GW as API Gateway HTTP<br/>(abitly-collector-dev)
participant L as Lambda collector
participant F as Kinesis Firehose
participant S as S3 Iceberg/Parquet
participant DB as Athena + Glue Catalog
W->>GW: POST /collect {events:[...]}
GW->>L: invoke
L->>L: Ajv validate vs events.schema.json
L->>L: dedup + enrich
L->>F: PutRecordBatch
F->>S: Parquet partitions
DB-.->S: каталог
Note over DB: dbt models<br/>→ Metabase dashboards
Поточний стан — dev only, prod ще не задеплоєно. Деталі → analytics.
Cross-product search (Abitly → Studsearch)
Section titled “Cross-product search (Abitly → Studsearch)”sequenceDiagram
actor U as Абітурієнт
participant W as Abitly Web
participant A as Abitly API
participant S as Studsearch backend
participant DB as Postgres<br/>(shared, різні схеми)
U->>W: пошук ЗВО з insider-відгуками
W->>S: GET /search?q=...
Note over W,S: NEXT_PUBLIC_STUDSEARCH_API_URL
S->>DB: SELECT FROM studsearch.*
DB-->>S: відгуки
S-->>W: JSON
W->>A: GET /universities/...
A->>DB: SELECT FROM abitly.*
DB-->>A: дані ЗВО
A-->>W: JSON
W-->>U: об'єднаний UX
Один і той самий Postgres, дві різні схеми, два різні API.