Карта сервісів
Архітектура в діаграмах показує, як влаштований сам моноліт. Ця сторінка ширша: які сервіси стоять навколо нього, де кожен живе і хто з ким говорить. Лілейка розкладена між двома хмарами. Azure тримає застосунок і його дані. Cloudflare стоїть попереду всього як DNS і проксі, а ще тримає легкі сервіси на Workers: каталог, сторінку статусу й сайт довідки.
Запит людини
Section titled “Запит людини”Людина ніколи не звертається до Azure напряму. Кожен запит спершу потрапляє на край Cloudflare в найближчому до неї місті (з України це Варшава або Відень), і вже звідти йде далі. Пунктир — те, що API робить у фоні, не затримуючи відповідь.
flowchart TB
USER["Людина<br/>браузер або PWA"]
EDGE["Край Cloudflare<br/>DNS · TLS · проксі"]
subgraph az["Azure · Poland Central"]
direction LR
SWA["Static Web Apps<br/>фронтенд"]
API["App Service B1<br/>ProjectK.API"]
SQL[("Azure SQL")]
BLOB[("Blob Storage")]
KV["Key Vault"]
AI["Application Insights"]
end
PAGES["Cloudflare Pages<br/>сайт і довідка"]
subgraph ext["Сторонні служби"]
direction LR
RESEND["Resend<br/>пошта"]
GH["GitHub<br/>звіти про проблеми"]
TG["Telegram<br/>алерти"]
end
USER --> EDGE
EDGE --> SWA
EDGE --> API
EDGE --> PAGES
API --> SQL
API --> BLOB
API -.-> KV
API -.-> AI
API --> RESEND
API --> GH
API -.-> TG
Сам App Service приймає лише IP-адреси Cloudflare: запит в обхід проксі отримає 403. Секрети API
читає не з налаштувань, а з Key Vault через посилання (@Microsoft.KeyVault(...)).
Фонові зв’язки
Section titled “Фонові зв’язки”Те, що відбувається без людини: за розкладом або раз на добу. Крон Cloudflare запускається будь-де у світі, тому перевірки він передає Durable Object, який завжди сидить у Стокгольмі. Чому так — на сторінці статусу.
flowchart LR
API["ProjectK.API<br/>прод"]
SELF["Self-host<br/>інсталяції"]
subgraph cf["Cloudflare Workers"]
direction TB
CAT["Каталог<br/>Worker + D1"]
subgraph status["Сторінка статусу"]
direction TB
CRON["Крон · 2 хв<br/>будь-яка локація"]
STW["Worker<br/>projectk-status"]
PROBER["Durable Object<br/>Prober · Стокгольм"]
SD1[("D1 status")]
end
end
TARGETS["API · фронтенд ·<br/>каталог · довідка"]
GH["GitHub<br/>релізи"]
TG["Telegram"]
API -- "щогодини каталог" --> CAT
API -- "раз на добу пінг" --> STW
SELF -.-> CAT
SELF -.-> STW
CRON --> STW
STW -- "перевір" --> PROBER
PROBER -- "GET /health" --> TARGETS
STW --> SD1
STW -.-> GH
STW -.-> TG
Де що живе
Section titled “Де що живе”| Сервіс | Де | Адреса | Як деплоїться |
|---|---|---|---|
| Фронтенд (Angular) | Azure Static Web Apps | lileyka.app |
angular.yml: пуш у dev → staging, реліз → прод; PR у dev чи main → превʼю SWA |
API (ProjectK.API) |
Azure App Service, Linux B1, Poland Central | api.lileyka.app |
dotnet.yml: пуш у dev → staging, реліз → прод. Збірка ReadyToRun |
| База | Azure SQL, Basic (5 DTU) | — | міграції EF на старті API |
| Файли | Azure Blob Storage | підписані посилання | — |
| Секрети | Azure Key Vault kv-projectk-prod |
— | посилання з налаштувань App Service |
| Логи | Application Insights + Telegram | — | — |
| Сайт і довідка | Cloudflare Pages | docs.lileyka.app |
git-інтеграція Cloudflare збирає site/ з продової гілки; site.yml лише перевіряє збірку |
| Статичне демо | Cloudflare Pages, разом із сайтом | /demo/ на сайті |
разом із сайтом |
| Публічне демо | окремо від проду, середовище Demo |
— | демо-курінь, вхід без пароля (api/demo/login), щоночі о 03:00 UTC база повертається до засіяного стану |
| Каталог проб і вмілостей | Cloudflare Worker + D1 | catalog.lileyka.app |
окремий репозиторій |
| Сторінка статусу і телеметрія | Cloudflare Worker + D1 + Durable Object | status.lileyka.app |
репозиторій ProjectK.Status, пуш у main через Workers Builds |
Прод деплоїться лише з опублікованого релізу GitHub (або вручну workflow_dispatch з main). Пуш у
main не деплоїть нічого: він приходить перед самим релізом і привіз би збірку 0.0.0-dev поверх
нього.
Staging має той самий набір в іншій підписці Azure. Пастка з назвами: застосунок
api-projectk-prod — це staging, а прод називається api-projectk-prod-new.
Залишки старого домену: продовий CORS (EnvCorsOrigin, список через кому) ще пускає
https://projectk.rostyslav-mukha.dev, поки той не переадресовує на lileyka.app, а відповідь на
листи прод і staging досі спрямовують на [email protected] (Email:ReplyTo). Непродові фронтенди (дев, staging, tailscale)
посилаються на довідку docs-dev.lileyka.app.
Що відбувається за розкладом
Section titled “Що відбувається за розкладом”| Що | Як часто | Хто кличе кого |
|---|---|---|
| Перевірки стану | кожні 2 хв | крон → projectk-status → Prober → чотири цілі |
| Оновлення каталогу | щогодини | API → каталог, остання копія лягає на диск (catalog-cache) |
| Анонімний пінг телеметрії | раз на добу, перший за 5 хв після старту | API (прод і self-host) → POST /v1/ping |
| Найновіший реліз | щогодини | projectk-status → GitHub, віддається інстансам у відповіді на пінг |
| Прибирання статусу | щодня о 03:00 UTC | projectk-status чистить старі лічильники в D1 |
| Фонові служби API | від годин до доби | аудит, перестороги, фото-сироти, архів задач (див. Архітектуру) |