KNOTTA research & development

Сервисы и порты

Детальный разбор пяти сервисов NG-Metrics — стек, ответственность, локальные порты и точки входа.

Сервисы и порты

Frontend (Next.js)

Директория: frontend/ Стек: Next.js 15 (App Router), TypeScript, Tailwind CSS 4, Supabase Auth, next-intl, Zustand, TanStack Query, SurveyJS. Менеджер пакетов: Yarn 1.22.

Ответственность. Веб-интерфейс для всех ролей: вход, дашборд бригадира/сотрудника, страница рецензирования отчёта, публичная страница отчёта, страница отписки от уведомлений, страницы аутентификации (sign-in / sign-up / forgot-password / invite / callback).

Маршрутизация. Локали в URL: /{ru|en}/.... Авторизованная зона лежит в группе (auth)/{locale}/dashboard/reports. Публичные страницы: /{locale}/report/{id}, /{locale}/unsubscribe.

Дашборд. На пути /{locale}/dashboard/reports живёт основной интерфейс рецензирования. Поддерживает desktop- и mobile-варианты (компоненты в dashboard/reports/components/{desktop,mobile}/). Принимает query-параметр ?visit=<id> — для прямых ссылок на конкретный наряд.

API-роуты Next.js. Используются как прокси к бэкенду для SurveyJS lazy loading (/api/survey/materials, /api/survey/services, /api/survey/workers) и для Open Graph картинок (/api/og).

Команды:

yarn dev                # dev-сервер (Turbopack + Sentry Spotlight)
yarn build && yarn start
yarn test               # Vitest unit-тесты
yarn test:e2e           # Playwright
yarn storybook          # Storybook на :6006
yarn check:types        # tsc --noEmit
yarn lint:fix

Backend / Garden (Django)

Директория: garden/ Стек: Django 5.2, Django REST Framework, drf-spectacular (OpenAPI), PostgreSQL 17, simple-history, KSUID, MJML, Resend, Celery 5.4 (Redis broker). Менеджер пакетов: UV.

Ответственность. Ядро бизнес-логики и единственный владелец схемы БД. Реализует REST API, рендерит email через MJML, отправляет уведомления через Resend и Redis Stream, хранит загруженные файлы в Supabase S3.

В проде сервис разворачивается в два контейнера:

  • web (ng-metrics-backend) — gunicorn, обслуживает HTTP, применяет миграции при старте.
  • worker (ng-metrics-backend-worker) — celery -A ng_metrics worker, исполняет фоновые задачи (сейчас — отправка уведомлений). Использует тот же образ; entrypoint очищен, чтобы не запускать миграции повторно.

В dev по умолчанию CELERY_TASK_ALWAYS_EAGER=true — задачи выполняются синхронно, отдельный воркер не нужен.

Модули (garden/modules/):

МодульЧто в нём
accountМодель User, аутентификация Supabase, эндпоинт /api/workers/, signal-обработчики
clientClient, ClientObject, ContactPerson, ClientInvite — клиенты, объекты, контактные лица, приглашения
service_visitServiceVisit, ServiceVisitMember — наряды и состав бригад; экшены смены статуса
reportReport, ReportSurveyTemplate, FileAttachment, ReportDelivery — отчёты, шаблоны, вложения, история доставок
notificationNotificationPreference, NotificationRouter, бэкенды, recipient resolvers, webhook-приёмники
materialMaterial, MaterialPrice, ServiceVisitMaterial — материалы и расход на наряде
serviceService, ServicePrice, ServiceVisitService — услуги и факт выполнения
communicationChatwootContact — связь пользователя с записью в Chatwoot
sharedБазовые классы (BaseModel, KSUID, аутентификация)
workDeprecated. Сохранён как unmanaged-модель для исторических FK в старых миграциях. Использовать service_visit.

Команды:

uv sync
python manage.py migrate
python manage.py runserver        # :8000 (dev)
python manage.py seed_report_templates
make lint    # ruff + mypy
make test    # pytest

Порты: 8000 в dev, 7000 в проде (отличие важно).

Telegram-бот

Директория: bot/ Стек: Aiogram 3.20, FastAPI, SQLAlchemy 2.0, Alembic, Redis, MyPy strict. Менеджер пакетов: UV.

Ответственность. Доставка уведомлений в Telegram, привязка Telegram-аккаунтов к пользователям, поддержка через Chatwoot, кнопка Mini App.

Точки входа:

  • bot/app/__main__.py — главный entrypoint. Запускает либо webhook-режим, либо polling.
  • bot/app/endpoints/telegram.py — Aiogram-хендлеры (команды бота).
  • bot/app/endpoints/chatwoot.py — приёмник входящих сообщений из Chatwoot.
  • bot/app/endpoints/healthcheck.py/health.
  • bot/app/runners/{webhook,polling}.py — режимы запуска.
  • bot/app/services/redis/ — подписка на Redis Stream от Garden.
  • bot/app/services/postgres/ — read-only SQLAlchemy для зеркал моделей Django.

База данных. Бот использует PostgreSQL только в режиме чтения для тех таблиц, что владеет Django. Для собственных «горячих» данных (FSM-состояния Aiogram, сессии Chatwoot) используется Redis (DB2).

Команды:

make app-run-db         # стартовать PG + Redis в Docker
make run                # запустить бота локально (polling)
make app-build && make app-run    # всё в Docker
make lint               # mypy + ruff

Порт: 8080 (FastAPI для webhook от Telegram + Chatwoot).

Supabase

Директория: supabase/ Стек: PostgreSQL 17, Supabase Auth, Supabase Storage (S3-совместимый), Deno Edge Functions, Resend. Менеджер пакетов: Supabase CLI.

Ответственность. Базы данных, аутентификация, S3-хранилище, тонкий webhook-слой для Auth-событий и транзакционных писем.

Edge Functions (supabase/functions/):

ФункцияТриггерЧто делает
send-emailSupabase Auth send-email hookШлёт письма приглашения / сброса пароля / смены email через Resend. Шаблоны на React Email (TSX), двуязычные (ru/en по user_metadata.lang).
auth-syncWebhook Supabase Auth (USER_CREATED / USER_UPDATED)Передаёт событие в Django для синхронизации User.supabase_uid.
set-roleHTTP вызов из фронтаОбновляет app_metadata.role в Supabase Auth (вызывается при изменении роли пользователя).

Локальные порты:

ЧтоПорт
Supabase API (Kong)54321
PostgreSQL54322
Supabase Studio54323
Inbucket (тестовый SMTP)54324
Edge Functions (make serve)8000

Команды:

make start              # PostgreSQL + Auth + Storage + Studio
make serve              # локальный запуск Edge Functions
make tunnel             # Tuna-туннели для тестирования вебхуков
make migrate

Инфраструктура (Ansible)

Директория: ansible/ Стек: Ansible 11.1, Docker, Traefik (единый reverse-proxy с Let's Encrypt), Infisical (секреты). Менеджер пакетов: Poetry.

Ответственность. Деплой всех сервисов на одном хосте через Docker. Управление секретами через Infisical. HTTPS через Traefik (single reverse-proxy, заменивший связку Caddy + Nginx).

Главный плейбук: playbooks/prod/ng-metrics.yaml. Порядок ролей:

  1. infisical — загрузка секретов.
  2. common — базовое окружение, docker, swap.
  3. supabase — БД, Auth, Storage, Edge Functions.
  4. system — Docker-сети (ng_metrics), Redis, Traefik (reverse-proxy + HTTPS).
  5. ng-metrics-backend — Django на порту 7000.
  6. ng-metrics-frontend — Next.js на порту 3000.
  7. ng-metrics-botотключено в текущей версии (закомментировано).
  8. chatwootотключено в текущей версии.

Redis распределён по базам:

  • DB0 — Django (Redis Stream + кэш).
  • DB1 — Chatwoot (когда включён).
  • DB2 — Telegram-бот (FSM-состояния, сессии).

Локальные порты — единая таблица

СервисПортКонтекст
Frontend (Next.js)3000Прод и dev
Backend (Django dev)8000Только dev
Backend (Django prod)7000Только прод
Telegram-бот FastAPI8080Прод и dev
Supabase API (Kong)54321Локально
PostgreSQL54322Локально
Supabase Studio54323Локально
Inbucket54324Локально (Mailhog-аналог)
Edge Functions8000Локально (make serve)
Storybook6006Только dev

Порядок запуска локально

# 1. Supabase — без него ничего не работает
cd supabase && make start

# 2. Backend — миграции и API
cd ../garden && python manage.py migrate
python manage.py runserver

# 3. Frontend
cd ../frontend && yarn dev

# 4. Telegram-бот (если нужен)
cd ../bot && make app-run-db && make run

# 5. Туннели (если тестируете webhook'и от Supabase)
cd ../supabase && make tunnel

Tuna-туннели публикуют сервисы в РФ-регионе:

  • Frontend: web-knotta.ru.tuna.am
  • Supabase API: service-knotta.ru.tuna.am
  • Backend API: api-knotta.ru.tuna.am
  • Telegram-бот: bot-knotta.ru.tuna.am
На странице