diff --git a/README.md b/README.md index 8cd1756..9d71c8e 100644 --- a/README.md +++ b/README.md @@ -86,63 +86,43 @@ flowchart LR Operate["Camunda Operate
UI :8081"]:::app end - %% ===== Бизнес-сервисы ===== - subgraph APPS["💼 Бизнес-сервисы"] - direction TB - - subgraph CORE["🧩 Платформа / Core"] - direction LR - Django["django
:8000 + srx-admin"]:::app - EAV["eav
атрибуты сущностей"]:::app - CI["control-interface
UI :80"]:::app - Workspaces["workspaces"]:::app - Projects["projects"]:::app - Subs["subscriptions"]:::app - SysLog["system-log"]:::app - MsgHub["message-hub"]:::app - FaaS["faas
functions runtime"]:::app - Flows["flows
оркестрация"]:::app - end - - subgraph DOCS["📂 Документы / CDE"] - direction LR - Docs["documentations
filestream + pdm"]:::app - DocLink["document-link"]:::app - Attach["attachments
HelmRelease"]:::app - Transmittal["transmittal"]:::app - CDE["cde
common data env"]:::app - Drawings["drawings"]:::app - BIM["bim
3D-модели"]:::app - Stamp["stamp-verification"]:::app - end - - subgraph QUALITY["✅ Контроль качества"] - direction LR - Inspect["inspections"]:::app - Checklists["checklists"]:::app - Remarks["remarks"]:::app - Issues["issues"]:::app - RFI["rfi
request for info"]:::app - Reviews["reviews"]:::app - Prescr["prescriptions"]:::app - Compare["comparisons
diff чертежей"]:::app - end - - subgraph FIELD["📐 Полевые данные"] - direction LR - Measure["measurements"]:::app - Mapper["mapper"]:::app - XSection["cross-section"]:::app - Process["processing"]:::app - end - - subgraph PMG["🏗 Управление проектом"] - direction LR - PM["pm
project mgmt"]:::app - Contracts["contracts"]:::app - Resources["resources"]:::app - Notes["notes"]:::app - end + %% ===== Бизнес-сервисы (каждый в своём namespace) ===== + subgraph APPS["💼 Бизнес-сервисы — namespaces"] + direction LR + CI["ns: control-interface"]:::app + Django["ns: django"]:::app + EAV["ns: eav"]:::app + Workspaces["ns: workspaces"]:::app + Projects["ns: projects"]:::app + PM["ns: pm"]:::app + Contracts["ns: contracts"]:::app + Resources["ns: resources"]:::app + Subs["ns: subscriptions"]:::app + SysLog["ns: system-log"]:::app + MsgHub["ns: message-hub"]:::app + FaaS["ns: faas"]:::app + Flows["ns: flows"]:::app + Docs["ns: documentations"]:::app + DocLink["ns: document-link"]:::app + Attach["ns: attachments"]:::app + Transmittal["ns: transmittal"]:::app + CDE["ns: cde"]:::app + Drawings["ns: drawings"]:::app + BIM["ns: bim"]:::app + Stamp["ns: stamp-verification"]:::app + Inspect["ns: inspections"]:::app + Checklists["ns: checklists"]:::app + Remarks["ns: remarks"]:::app + Issues["ns: issues"]:::app + RFI["ns: rfi"]:::app + Reviews["ns: reviews"]:::app + Prescr["ns: prescriptions"]:::app + Compare["ns: comparisons"]:::app + Measure["ns: measurements"]:::app + Mapper["ns: mapper"]:::app + XSection["ns: cross-section"]:::app + Process["ns: processing"]:::app + Notes["ns: notes"]:::app end %% ===== GitOps потоки ===== @@ -333,12 +313,6 @@ flowchart LR BIM -. "envoy" .-> Pilot Flows -. "envoy" .-> Pilot - %% ===== Стили подгрупп бизнес-сервисов ===== - style CORE fill:#fdf2f8,stroke:#ec4899,stroke-width:1px - style DOCS fill:#fdf2f8,stroke:#ec4899,stroke-width:1px - style QUALITY fill:#fdf2f8,stroke:#ec4899,stroke-width:1px - style FIELD fill:#fdf2f8,stroke:#ec4899,stroke-width:1px - style PMG fill:#fdf2f8,stroke:#ec4899,stroke-width:1px %% ===== Стили ===== classDef ext fill:#1f2937,stroke:#9ca3af,stroke-width:2px,color:#f9fafb @@ -360,6 +334,8 @@ flowchart LR style APPS fill:#fce7f3,stroke:#ec4899,stroke-width:2px ``` +📂 **Подробные диаграммы по каждому бизнес-сервису:** [`docs/apps/`](./docs/apps/README.md) + **Легенда:** - 🟪 **Edge / Mesh** — терминация TLS, маршрутизация и mTLS между сервисами (Istio + cert-manager) - 🟦 **Платформа** — служебные компоненты (storage, secrets, S3 proxy, dashboard) diff --git a/docs/apps/README.md b/docs/apps/README.md new file mode 100644 index 0000000..e428591 --- /dev/null +++ b/docs/apps/README.md @@ -0,0 +1,58 @@ +# Диаграммы бизнес-приложений + +В этой папке для каждого бизнес-сервиса (namespace) есть отдельная mermaid-диаграмма с его зависимостями и межсервисными маршрутами. + +## Индекс + +### Платформа / Core +- [control-interface](./control-interface.md) — единая точка входа UI, API gateway +- [django](./django.md) — основной backend-монолит +- [eav](./eav.md) — Entity-Attribute-Value сервис атрибутов +- [workspaces](./workspaces.md) — рабочие пространства +- [projects](./projects.md) — проекты +- [subscriptions](./subscriptions.md) — подписки и доставка уведомлений +- [system-log](./system-log.md) — аудит-журнал +- [message-hub](./message-hub.md) — хаб уведомлений +- [faas](./faas.md) — runtime функций +- [flows](./flows.md) — оркестрация бизнес-потоков + +### Управление проектом +- [pm](./pm.md) — project management +- [contracts](./contracts.md) — контракты +- [resources](./resources.md) — ресурсы +- [notes](./notes.md) — заметки + +### Документы / CDE +- [documentations](./documentations.md) — хранилище документов +- [document-link](./document-link.md) — связи между документами +- [attachments](./attachments.md) — вложения +- [transmittal](./transmittal.md) — комплекты передачи +- [cde](./cde.md) — Common Data Environment +- [drawings](./drawings.md) — чертежи +- [bim](./bim.md) — BIM/3D-модели +- [stamp-verification](./stamp-verification.md) — верификация штампов + +### Контроль качества +- [inspections](./inspections.md) — инспекции +- [checklists](./checklists.md) — чек-листы +- [remarks](./remarks.md) — замечания +- [issues](./issues.md) — проблемы +- [rfi](./rfi.md) — Request For Information +- [reviews](./reviews.md) — ревью +- [prescriptions](./prescriptions.md) — предписания +- [comparisons](./comparisons.md) — сравнение чертежей + +### Полевые данные +- [measurements](./measurements.md) — замеры +- [mapper](./mapper.md) — картография +- [cross-section](./cross-section.md) — сечения +- [processing](./processing.md) — обработка + +## Легенда диаграмм + +- 🟪 розовый — сам сервис (текущая страница) +- 🩷 светло-розовый — соседние бизнес-сервисы +- 🟩 зелёный — БД и хранилища (PostgreSQL, Redis, MinIO) +- 🟥 красный — шины сообщений (Kafka, RabbitMQ) +- 🟦 голубой — платформенные компоненты (Vault, S3 Proxy, Istio) +- 🟧 оранжевый — Identity-провайдеры (Keycloak, Zitadel) diff --git a/docs/apps/attachments.md b/docs/apps/attachments.md new file mode 100644 index 0000000..9d16b78 --- /dev/null +++ b/docs/apps/attachments.md @@ -0,0 +1,25 @@ +# attachments + +Сервис вложений (управляется HelmRelease). Namespace: `attachments`. + +```mermaid +flowchart LR + Helm[helm-controller]:::infra + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + + subgraph NS["ns: attachments"] + HR{{HelmRelease
chart-managed}}:::cfg + App[deployment: attachments
API + workers]:::comp + HR -.-> App + end + + Helm -.->|reconcile| HR + App -->|PUT/GET| S3 --> MinIO + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/bim.md b/docs/apps/bim.md new file mode 100644 index 0000000..f2641b0 --- /dev/null +++ b/docs/apps/bim.md @@ -0,0 +1,35 @@ +# bim + +BIM / 3D-модели. Namespace: `bim`. + +```mermaid +flowchart LR + GW[Istio Gateway]:::infra + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + Kafka[[Kafka]]:::msg + KC[Keycloak]:::idp + CDE[cde]:::peer + Process[processing]:::peer + + subgraph NS["ns: bim"] + Backend[deployment: backend
Service]:::comp + end + + GW -->|/bim| Backend + CDE -->|REST| Backend + Backend --> PG + Backend -->|IFC/RVT| S3 --> MinIO + Backend -->|REST| Process + Backend -->|produce bim.processed| Kafka + Backend -. JWT .-> KC + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + classDef idp fill:#f59e0b,stroke:#92400e,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/cde.md b/docs/apps/cde.md new file mode 100644 index 0000000..53dad76 --- /dev/null +++ b/docs/apps/cde.md @@ -0,0 +1,64 @@ +# cde + +Common Data Environment с набором воркеров. Namespace: `cde`. + +```mermaid +flowchart LR + GW[Istio Gateway]:::infra + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + KC[Keycloak]:::idp + RMQ[[RabbitMQ]]:::msg + + subgraph NS["ns: cde"] + API[deployment: cde
API + backend]:::comp + Split[worker: split-pdf]:::comp + Copy[worker: copy]:::comp + Versions[worker: create-versions]:::comp + Markings[worker: markings]:::comp + Sign[worker: sign]:::comp + Bundles[worker: update-bundles]:::comp + FlowsCB[worker: flows-callback]:::comp + API -. dispatch .-> Split + API -. dispatch .-> Copy + API -. dispatch .-> Versions + API -. dispatch .-> Markings + API -. dispatch .-> Sign + API -. dispatch .-> Bundles + API -. dispatch .-> FlowsCB + end + + Docs[documentations]:::peer + Drawings[drawings]:::peer + BIM[bim]:::peer + DocLink[document-link]:::peer + Transmittal[transmittal]:::peer + Flows[flows]:::peer + + GW -->|/cde| API + DocLink -->|REST| API + Transmittal -->|REST| API + API -->|REST| Docs + API -->|REST| Drawings + API -->|REST| BIM + API --> PG + Split -->|files| S3 + Copy -->|files| S3 + Versions -->|files| S3 + Markings -->|files| S3 + Sign -->|files| S3 + Bundles -->|files| S3 + S3 --> MinIO + Split & Copy & Versions & Markings & Sign & Bundles -.->|consume jobs| RMQ + FlowsCB -.->|callback| Flows + API -. JWT .-> KC + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef idp fill:#f59e0b,stroke:#92400e,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/checklists.md b/docs/apps/checklists.md new file mode 100644 index 0000000..a1642eb --- /dev/null +++ b/docs/apps/checklists.md @@ -0,0 +1,21 @@ +# checklists + +Чек-листы. Namespace: `checklists`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Inspect[inspections]:::peer + + subgraph NS["ns: checklists"] + Backend[deployment: backend
Service]:::comp + end + + Inspect -->|REST| Backend + Backend --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/comparisons.md b/docs/apps/comparisons.md new file mode 100644 index 0000000..2aa8651 --- /dev/null +++ b/docs/apps/comparisons.md @@ -0,0 +1,34 @@ +# comparisons + +Сравнение чертежей. Namespace: `comparisons`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + Kafka[[Kafka]]:::msg + Drawings[drawings]:::peer + + subgraph NS["ns: comparisons"] + Frontend[deployment: frontend
nginx]:::comp + Backend[deployment: backend
API]:::comp + Cfg{{configmaps:
nginx, tasks-execution}}:::cfg + Frontend --> Backend + Cfg -.-> Backend + Cfg -.-> Frontend + end + + Drawings -->|REST| Backend + Kafka -->|consume drawings.uploaded| Backend + Backend --> PG + Backend -->|rendered diff| S3 --> MinIO + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/contracts.md b/docs/apps/contracts.md new file mode 100644 index 0000000..3ce49ac --- /dev/null +++ b/docs/apps/contracts.md @@ -0,0 +1,23 @@ +# contracts + +Контракты. Namespace: `contracts`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + PM[pm]:::peer + Resources[resources]:::peer + + subgraph NS["ns: contracts"] + App[deployment: contracts
Service]:::comp + end + + PM -->|REST| App + App -->|REST| Resources + App --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/control-interface.md b/docs/apps/control-interface.md new file mode 100644 index 0000000..780eb9b --- /dev/null +++ b/docs/apps/control-interface.md @@ -0,0 +1,36 @@ +# control-interface + +Единый UI и API-gateway. Namespace: `control-interface`. + +```mermaid +flowchart LR + User([👤 User]):::ext + GW[Istio Gateway]:::infra + Redis[(Redis)]:::data + KC[Keycloak]:::idp + + subgraph NS["ns: control-interface"] + UI[deployment: ui
Service :80]:::comp + end + + Django[django]:::peer + PM[pm]:::peer + Projects[projects]:::peer + Workspaces[workspaces]:::peer + + User -->|HTTPS| GW --> UI + UI -->|API| Django + UI -->|API| PM + UI -->|API| Projects + UI -->|API| Workspaces + UI -->|session| Redis + UI -. OIDC .-> KC + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef idp fill:#f59e0b,stroke:#92400e,color:#fff + classDef ext fill:#1f2937,stroke:#9ca3af,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/cross-section.md b/docs/apps/cross-section.md new file mode 100644 index 0000000..699af23 --- /dev/null +++ b/docs/apps/cross-section.md @@ -0,0 +1,30 @@ +# cross-section + +Поперечные сечения. Namespace: `cross-section`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + RMQ[[RabbitMQ]]:::msg + Mapper[mapper]:::peer + Process[processing]:::peer + + subgraph NS["ns: cross-section"] + App[deployment: cross-section
Service]:::comp + end + + Mapper -->|REST| App + RMQ -->|consume xs.jobs| App + App --> PG + App -->|профили| S3 --> MinIO + App -->|REST| Process + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/django.md b/docs/apps/django.md new file mode 100644 index 0000000..7ec1555 --- /dev/null +++ b/docs/apps/django.md @@ -0,0 +1,45 @@ +# django + +Основной Django-монолит. Namespace: `django`. + +```mermaid +flowchart LR + GW[Istio Gateway]:::infra + PG[(PostgreSQL)]:::data + Redis[(Redis)]:::data + Vault[Vault]:::infra + KC[Keycloak]:::idp + + subgraph NS["ns: django"] + Frontend[deployment: frontend
nginx :80]:::comp + Backend[deployment: backend
uwsgi :8000]:::comp + Celery[deployment: celery
worker]:::comp + SRX[deployment: srx-admin
:8000]:::comp + Cfg{{configmaps:
django, nginx, uwsgi}}:::cfg + Frontend --> Backend + Backend -. tasks via Redis .-> Celery + Cfg -.-> Backend + Cfg -.-> Frontend + end + + CI[control-interface]:::peer + EAV[eav]:::peer + + GW -->|/api| Frontend + CI -->|REST| Backend + EAV -->|schemas| Backend + Backend -->|JDBC/ORM| PG + Backend -->|cache| Redis + Celery -->|broker| Redis + Backend -. kv .-> Vault + Backend -. OIDC .-> KC + SRX --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef idp fill:#f59e0b,stroke:#92400e,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/document-link.md b/docs/apps/document-link.md new file mode 100644 index 0000000..869f62e --- /dev/null +++ b/docs/apps/document-link.md @@ -0,0 +1,27 @@ +# document-link + +Связи между документами. Namespace: `document-link`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Docs[documentations]:::peer + CDE[cde]:::peer + RFI[rfi]:::peer + Notes[notes]:::peer + + subgraph NS["ns: document-link"] + App[deployment: document-link
Service]:::comp + end + + RFI -->|REST| App + Notes -->|REST| App + App -->|REST| Docs + App -->|REST| CDE + App --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/documentations.md b/docs/apps/documentations.md new file mode 100644 index 0000000..a4dd446 --- /dev/null +++ b/docs/apps/documentations.md @@ -0,0 +1,42 @@ +# documentations + +Хранилище документов. Namespace: `documentations`. + +```mermaid +flowchart LR + GW[Istio Gateway]:::infra + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + KC[Keycloak]:::idp + + subgraph NS["ns: documentations"] + Frontend[deployment: frontend]:::comp + API[deployment: api]:::comp + Filestream[deployment: filestream
upload/download]:::comp + PDM[deployment: pdm
product data mgmt]:::comp + Frontend --> API + API --> Filestream + API --> PDM + end + + DocLink[document-link]:::peer + CDE[cde]:::peer + Transmittal[transmittal]:::peer + + GW -->|/docs| Frontend + DocLink -->|REST| API + CDE -->|REST| API + Transmittal -->|REST| API + API --> PG + PDM --> PG + Filestream -->|files| S3 --> MinIO + API -. JWT .-> KC + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef idp fill:#f59e0b,stroke:#92400e,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/drawings.md b/docs/apps/drawings.md new file mode 100644 index 0000000..555435c --- /dev/null +++ b/docs/apps/drawings.md @@ -0,0 +1,32 @@ +# drawings + +Чертежи. Namespace: `drawings`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + Kafka[[Kafka]]:::msg + CDE[cde]:::peer + Compare[comparisons]:::peer + Stamp[stamp-verification]:::peer + + subgraph NS["ns: drawings"] + App[deployment: drawings
Service]:::comp + end + + CDE -->|REST| App + App --> PG + App -->|DWG/PDF| S3 --> MinIO + App -->|produce drawings.uploaded| Kafka + App -->|REST| Compare + App -->|REST| Stamp + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/eav.md b/docs/apps/eav.md new file mode 100644 index 0000000..e75a6f6 --- /dev/null +++ b/docs/apps/eav.md @@ -0,0 +1,24 @@ +# eav + +Entity-Attribute-Value сервис. Namespace: `eav`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Django[django]:::peer + + subgraph NS["ns: eav"] + Backend[deployment: backend
Service]:::comp + Cfg{{configmap: django}}:::cfg + Cfg -.-> Backend + end + + Backend --> PG + Backend -->|schemas REST| Django + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/faas.md b/docs/apps/faas.md new file mode 100644 index 0000000..3a87f34 --- /dev/null +++ b/docs/apps/faas.md @@ -0,0 +1,31 @@ +# faas + +Function-as-a-Service runtime. Namespace: `faas`. + +```mermaid +flowchart LR + Redis[(Redis)]:::data + RMQ[[RabbitMQ]]:::msg + Vault[Vault]:::infra + Flows[flows]:::peer + Reviews[reviews]:::peer + + subgraph NS["ns: faas"] + Backend[deployment: backend
API]:::comp + ExportReviews[deployment: export-reviews
function]:::comp + end + + Flows -->|trigger| Backend + Backend -->|spawn| ExportReviews + ExportReviews -->|REST| Reviews + Backend -->|queue| Redis + RMQ -->|consume tasks.*| Backend + Backend -. approle .-> Vault + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/flows.md b/docs/apps/flows.md new file mode 100644 index 0000000..0ca9af3 --- /dev/null +++ b/docs/apps/flows.md @@ -0,0 +1,37 @@ +# flows + +Оркестрация бизнес-потоков. Namespace: `flows`. + +```mermaid +flowchart LR + Redis[(Redis)]:::data + Kafka[[Kafka]]:::msg + RMQ[[RabbitMQ]]:::msg + Vault[Vault]:::infra + FaaS[faas]:::peer + Camunda[Camunda BPM]:::peer + + subgraph NS["ns: flows"] + Frontend[deployment: frontend]:::comp + Backend[deployment: backend
API]:::comp + Celery[deployment: celery
worker]:::comp + Frontend --> Backend + Backend -. tasks .-> Celery + end + + Backend -->|state| Redis + Celery -->|broker| Redis + Backend <-->|flows.*| Kafka + Backend -->|publish tasks.*| RMQ + Backend -->|trigger| FaaS + Backend -->|start workflow| Camunda + Camunda -->|callback| Backend + Backend -. approle .-> Vault + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/inspections.md b/docs/apps/inspections.md new file mode 100644 index 0000000..1d7097d --- /dev/null +++ b/docs/apps/inspections.md @@ -0,0 +1,26 @@ +# inspections + +Инспекции. Namespace: `inspections`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Kafka[[Kafka]]:::msg + Checklists[checklists]:::peer + Issues[issues]:::peer + + subgraph NS["ns: inspections"] + Backend[deployment: backend
Service]:::comp + end + + Backend --> PG + Backend -->|REST| Checklists + Backend -->|REST| Issues + Backend -->|produce inspect.events| Kafka + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/issues.md b/docs/apps/issues.md new file mode 100644 index 0000000..06263ac --- /dev/null +++ b/docs/apps/issues.md @@ -0,0 +1,33 @@ +# issues + +Проблемы. Namespace: `issues`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Kafka[[Kafka]]:::msg + Inspect[inspections]:::peer + Remarks[remarks]:::peer + + subgraph NS["ns: issues"] + Frontend[deployment: frontend]:::comp + Backend[deployment: backend
API]:::comp + Celery[deployment: celery
worker]:::comp + Cfg{{configmap: production}}:::cfg + Frontend --> Backend + Backend -. tasks .-> Celery + Cfg -.-> Backend + end + + Inspect -->|REST| Backend + Kafka -->|consume inspect.events| Backend + Backend -->|REST| Remarks + Backend --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/mapper.md b/docs/apps/mapper.md new file mode 100644 index 0000000..fd65bb9 --- /dev/null +++ b/docs/apps/mapper.md @@ -0,0 +1,30 @@ +# mapper + +Картография / тайлы. Namespace: `mapper`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + RMQ[[RabbitMQ]]:::msg + Measure[measurements]:::peer + XSection[cross-section]:::peer + + subgraph NS["ns: mapper"] + App[deployment: mapper
Service]:::comp + end + + Measure -->|REST| App + RMQ -->|consume tile.jobs| App + App --> PG + App -->|tiles| S3 --> MinIO + App -->|REST| XSection + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/measurements.md b/docs/apps/measurements.md new file mode 100644 index 0000000..bf95ce6 --- /dev/null +++ b/docs/apps/measurements.md @@ -0,0 +1,25 @@ +# measurements + +Замеры. Namespace: `measurements`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + Mapper[mapper]:::peer + + subgraph NS["ns: measurements"] + App[deployment: measurements
Service]:::comp + end + + App --> PG + App -->|snapshots| S3 --> MinIO + App -->|REST| Mapper + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/message-hub.md b/docs/apps/message-hub.md new file mode 100644 index 0000000..fe86f3a --- /dev/null +++ b/docs/apps/message-hub.md @@ -0,0 +1,24 @@ +# message-hub + +Хаб уведомлений. Namespace: `message-hub`. + +```mermaid +flowchart LR + Redis[(Redis)]:::data + Kafka[[Kafka]]:::msg + Subs[subscriptions]:::peer + + subgraph NS["ns: message-hub"] + App[deployment: message-hub
Service]:::comp + end + + App <-->|pub/sub| Redis + App -->|produce notify.*| Kafka + App -->|deliver| Subs + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/notes.md b/docs/apps/notes.md new file mode 100644 index 0000000..7c5894d --- /dev/null +++ b/docs/apps/notes.md @@ -0,0 +1,26 @@ +# notes + +Заметки. Namespace: `notes`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + DocLink[document-link]:::peer + + subgraph NS["ns: notes"] + Frontend[deployment: frontend
nginx]:::comp + Backend[deployment: backend
API]:::comp + Cfg{{configmap: nginx}}:::cfg + Frontend --> Backend + Cfg -.-> Frontend + end + + Backend --> PG + Backend -->|REST| DocLink + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/pm.md b/docs/apps/pm.md new file mode 100644 index 0000000..cff82f3 --- /dev/null +++ b/docs/apps/pm.md @@ -0,0 +1,42 @@ +# pm + +Project management. Namespace: `pm`. + +```mermaid +flowchart LR + GW[Istio Gateway]:::infra + PG[(PostgreSQL)]:::data + Redis[(Redis)]:::data + KC[Keycloak]:::idp + + subgraph NS["ns: pm"] + Backend[deployment: backend
Service]:::comp + Celery[deployment: celery
worker]:::comp + Cfg{{configmap: backend}}:::cfg + Cfg -.-> Backend + Backend -. tasks .-> Celery + end + + CI[control-interface]:::peer + Projects[projects]:::peer + Contracts[contracts]:::peer + Resources[resources]:::peer + + GW -->|/pm| Backend + CI -->|REST| Backend + Backend -->|REST| Projects + Backend -->|REST| Contracts + Backend -->|REST| Resources + Backend --> PG + Celery -->|broker| Redis + Backend -->|cache| Redis + Backend -. JWT .-> KC + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef idp fill:#f59e0b,stroke:#92400e,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/prescriptions.md b/docs/apps/prescriptions.md new file mode 100644 index 0000000..b69f07e --- /dev/null +++ b/docs/apps/prescriptions.md @@ -0,0 +1,21 @@ +# prescriptions + +Предписания. Namespace: `prescriptions`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Reviews[reviews]:::peer + + subgraph NS["ns: prescriptions"] + App[deployment: prescriptions
Service]:::comp + end + + Reviews -->|REST| App + App --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/processing.md b/docs/apps/processing.md new file mode 100644 index 0000000..6cc39e1 --- /dev/null +++ b/docs/apps/processing.md @@ -0,0 +1,39 @@ +# processing + +Обработка тяжёлых задач. Namespace: `processing`. + +```mermaid +flowchart LR + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + Kafka[[Kafka]]:::msg + RMQ[[RabbitMQ]]:::msg + BIM[bim]:::peer + XSection[cross-section]:::peer + + subgraph NS["ns: processing"] + Frontend[deployment: frontend]:::comp + API[deployment: api]:::comp + Engine[deployment: engine
heavy compute]:::comp + EngineLow[deployment: engine-low
low priority]:::comp + Frontend --> API + API --> Engine + API --> EngineLow + end + + BIM -->|REST| API + XSection -->|REST| API + Kafka -->|consume processing.jobs| API + Engine -->|publish jobs| RMQ + EngineLow -->|publish jobs| RMQ + Engine -->|raw + результаты| S3 + EngineLow -->|raw + результаты| S3 + S3 --> MinIO + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/projects.md b/docs/apps/projects.md new file mode 100644 index 0000000..cb010f6 --- /dev/null +++ b/docs/apps/projects.md @@ -0,0 +1,25 @@ +# projects + +Проекты. Namespace: `projects`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + CI[control-interface]:::peer + PM[pm]:::peer + Workspaces[workspaces]:::peer + + subgraph NS["ns: projects"] + App[deployment: projects
Service]:::comp + end + + CI -->|REST| App + PM -->|REST| App + App -->|REST| Workspaces + App --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/remarks.md b/docs/apps/remarks.md new file mode 100644 index 0000000..9d63bb1 --- /dev/null +++ b/docs/apps/remarks.md @@ -0,0 +1,26 @@ +# remarks + +Замечания. Namespace: `remarks`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Kafka[[Kafka]]:::msg + Issues[issues]:::peer + Reviews[reviews]:::peer + + subgraph NS["ns: remarks"] + App[deployment: remarks
Service]:::comp + end + + Issues -->|REST| App + App --> PG + App -->|produce remarks.events| Kafka + Kafka -->|consume| Reviews + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/resources.md b/docs/apps/resources.md new file mode 100644 index 0000000..2bd994f --- /dev/null +++ b/docs/apps/resources.md @@ -0,0 +1,26 @@ +# resources + +Ресурсы. Namespace: `resources`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + PM[pm]:::peer + Contracts[contracts]:::peer + + subgraph NS["ns: resources"] + Backend[deployment: backend
uwsgi Service]:::comp + Cfg{{configmaps:
django, uwsgi}}:::cfg + Cfg -.-> Backend + end + + PM -->|REST| Backend + Contracts -->|REST| Backend + Backend --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef cfg fill:#fef3c7,stroke:#92400e,color:#000 + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/reviews.md b/docs/apps/reviews.md new file mode 100644 index 0000000..c08a217 --- /dev/null +++ b/docs/apps/reviews.md @@ -0,0 +1,26 @@ +# reviews + +Ревью. Namespace: `reviews`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Kafka[[Kafka]]:::msg + RFI[rfi]:::peer + Prescr[prescriptions]:::peer + + subgraph NS["ns: reviews"] + App[deployment: reviews
Service]:::comp + end + + Kafka -->|consume remarks.events| App + App -->|REST| RFI + App -->|REST| Prescr + App --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/rfi.md b/docs/apps/rfi.md new file mode 100644 index 0000000..d5f3205 --- /dev/null +++ b/docs/apps/rfi.md @@ -0,0 +1,27 @@ +# rfi + +Request For Information. Namespace: `rfi`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + DocLink[document-link]:::peer + Reviews[reviews]:::peer + + subgraph NS["ns: rfi"] + Frontend[deployment: frontend]:::comp + Backend[deployment: backend
API]:::comp + Celery[deployment: celery
worker]:::comp + Frontend --> Backend + Backend -. tasks .-> Celery + end + + Reviews -->|REST| Backend + Backend -->|REST| DocLink + Backend --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/stamp-verification.md b/docs/apps/stamp-verification.md new file mode 100644 index 0000000..d03243e --- /dev/null +++ b/docs/apps/stamp-verification.md @@ -0,0 +1,28 @@ +# stamp-verification + +Верификация штампов. Namespace: `stamp-verification`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + RMQ[[RabbitMQ]]:::msg + Drawings[drawings]:::peer + + subgraph NS["ns: stamp-verification"] + App[deployment: stamp-verification
Service]:::comp + end + + Drawings -->|REST| App + RMQ -->|consume sign.jobs| App + App --> PG + App -->|signed PDF| S3 --> MinIO + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/subscriptions.md b/docs/apps/subscriptions.md new file mode 100644 index 0000000..1fded41 --- /dev/null +++ b/docs/apps/subscriptions.md @@ -0,0 +1,26 @@ +# subscriptions + +Подписки и доставка уведомлений. Namespace: `subscriptions`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Redis[(Redis)]:::data + Kafka[[Kafka]]:::msg + MsgHub[message-hub]:::peer + + subgraph NS["ns: subscriptions"] + Backend[deployment: backend
Service]:::comp + end + + MsgHub -->|deliver| Backend + Kafka -->|consume notify.*| Backend + Backend <-->|pub/sub| Redis + Backend --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/system-log.md b/docs/apps/system-log.md new file mode 100644 index 0000000..3df62a8 --- /dev/null +++ b/docs/apps/system-log.md @@ -0,0 +1,23 @@ +# system-log + +Аудит-журнал. Namespace: `system-log`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Kafka[[Kafka]]:::msg + + subgraph NS["ns: system-log"] + Backend[deployment: backend
API]:::comp + Worker[deployment: worker
kafka consumer]:::comp + Worker -->|insert| Backend + end + + Kafka -->|consume audit.*| Worker + Backend --> PG + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef msg fill:#ef4444,stroke:#991b1b,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/transmittal.md b/docs/apps/transmittal.md new file mode 100644 index 0000000..ddde573 --- /dev/null +++ b/docs/apps/transmittal.md @@ -0,0 +1,31 @@ +# transmittal + +Комплекты передачи. Namespace: `transmittal`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + S3[S3 Proxy]:::infra + MinIO[(MinIO)]:::data + CDE[cde]:::peer + Docs[documentations]:::peer + + subgraph NS["ns: transmittal"] + Frontend[deployment: frontend]:::comp + Backend[deployment: backend
API]:::comp + Worker[deployment: worker
bundle assembly]:::comp + Frontend --> Backend + Backend -. async .-> Worker + end + + Backend --> PG + Worker -->|bundles| S3 --> MinIO + Backend -->|REST| CDE + Backend -->|REST| Docs + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + classDef infra fill:#0ea5e9,stroke:#075985,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +``` diff --git a/docs/apps/workspaces.md b/docs/apps/workspaces.md new file mode 100644 index 0000000..cbacc54 --- /dev/null +++ b/docs/apps/workspaces.md @@ -0,0 +1,27 @@ +# workspaces + +Рабочие пространства. Namespace: `workspaces`. + +```mermaid +flowchart LR + PG[(PostgreSQL)]:::data + Redis[(Redis)]:::data + CI[control-interface]:::peer + Projects[projects]:::peer + + subgraph NS["ns: workspaces"] + Frontend[deployment: frontend]:::comp + Backend[deployment: backend]:::comp + Frontend --> Backend + end + + CI -->|REST| Frontend + Projects -->|REST| Backend + Backend --> PG + Backend -->|cache| Redis + + classDef comp fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff + classDef peer fill:#fce7f3,stroke:#9d174d,color:#000 + classDef data fill:#10b981,stroke:#065f46,color:#fff + style NS fill:#fdf2f8,stroke:#ec4899,stroke-width:2px +```