From c70e30729cbcf13baa8f8b55badfe902d256cb62 Mon Sep 17 00:00:00 2001 From: emelinda Date: Mon, 13 Jul 2026 17:24:47 +0300 Subject: [PATCH] add attachments, transmittal, workspaces docs --- apps/attachments/.env.example | 46 ++++++ apps/attachments/CONFIGURATION.md | 129 +++++++++++++++ apps/transmittal/.env.example | 121 ++++++++++++++ apps/transmittal/CONFIGURATION.md | 263 ++++++++++++++++++++++++++++++ apps/transmittal/ENDPOINTS.md | 185 +++++++++++++++++++++ apps/workspaces/.env.example | 21 +++ apps/workspaces/CONFIGURATION.md | 122 ++++++++++++++ 7 files changed, 887 insertions(+) create mode 100644 apps/attachments/.env.example create mode 100644 apps/attachments/CONFIGURATION.md create mode 100644 apps/transmittal/.env.example create mode 100644 apps/transmittal/CONFIGURATION.md create mode 100644 apps/transmittal/ENDPOINTS.md create mode 100644 apps/workspaces/.env.example create mode 100644 apps/workspaces/CONFIGURATION.md diff --git a/apps/attachments/.env.example b/apps/attachments/.env.example new file mode 100644 index 0000000..2fdc878 --- /dev/null +++ b/apps/attachments/.env.example @@ -0,0 +1,46 @@ +# ============================================================================= +# Attachments — пример конфигурации (.env) +# Скопируйте в .env и заполните значения. +# ============================================================================= +# --- Приложение (необязательные, есть значения по умолчанию) --- +# Версия: 0.11.1 + +# API=/api +# NAME=Attachments +# VERSION=0.0.1 +# DESCRIPTION=Attachments + +# --- База данных PostgreSQL (обязательные) --- +DATABASE_NAME=attachments +DATABASE_USER=postgres +DATABASE_PASSWORD=change_me +DATABASE_HOST=db +DATABASE_PORT=5432 +DATABASE_SSL_MODE=disable + +# Пароль суперпользователя PostgreSQL для контейнера db (docker-compose) +POSTGRES_PASSWORD=change_me + +# --- S3 (Yandex Object Storage) --- +# Вариант 1: путь к JSON с реквизитами сервисного аккаунта. +# Файл должен содержать: {"endpoint": "...", "access_key_id": "...", "secret_access_key": "..."} +YANDEX_S3_ACCOUNT_PATH=/etc/sarex/yc-s3-storage/yc-s3-service-account.json + +# Вариант 2: задать реквизиты напрямую (если не используете JSON-файл). +# YANDEX_S3_ENDPOINT_URL=storage.yandexcloud.net +# YANDEX_S3_ACCESS_KEY_ID=change_me +# YANDEX_S3_SECRET_ACCESS_KEY=change_me + +YANDEX_S3_VERIFY=true +# YANDEX_S3_USE_SSL=true +# YANDEX_S3_REGION=ru-central1 +BUCKET_NAME=attachments-stage-2 + +# --- Логирование (префикс LOG_) --- +# LOG_LEVEL=INFO + +# --- Трейсинг / OpenTelemetry (префикс TRACING_) --- +# TRACING_USE=false +# TRACING_HOST=localhost:4317 +# TRACING_SERVICE_NAME=attachments +# TRACING_INSECURE=false diff --git a/apps/attachments/CONFIGURATION.md b/apps/attachments/CONFIGURATION.md new file mode 100644 index 0000000..b3ae384 --- /dev/null +++ b/apps/attachments/CONFIGURATION.md @@ -0,0 +1,129 @@ +# Конфигурация проекта Attachments +# Версия: 0.11.1 + +Документ описывает все переменные окружения и способы конфигурирования сервиса. + +## Способы конфигурирования + +Настройка сервиса выполняется **только через переменные окружения**. Отдельного файла с настройками (yaml/toml) в приложении нет — за конфигурацию отвечает `internal/config/settings.py` на базе `pydantic.BaseSettings`. + +Источники переменных окружения по способам запуска: + +| Способ запуска | Откуда берутся переменные | +| --- | --- | +| Локально (docker-compose) | Файл `.env` в корне (`env_file: .env` в `docker-compose.yml`), плюс `POSTGRES_PASSWORD` для контейнера БД | +| Kubernetes (Helm) | `.helm/values.yaml`: блок `envs` (обычные значения) и `secretEnvs` (значения из k8s-секретов) | +| CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна и build-args | + +Дополнительно секреты доступа к S3 не задаются напрямую, а читаются из JSON-файла (см. `YANDEX_S3_ACCOUNT_PATH` ниже). + +## Переменные приложения (класс `Settings`) + +Читаются напрямую по имени (регистрозависимо, `case_sensitive = True`). Переменные без значения по умолчанию **обязательны** — без них приложение не стартует. + +| Переменная | Тип | Обязательна | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | --- | +| `API` | str | нет | `/api` | Префикс всех HTTP-роутов | +| `NAME` | str | нет | `Attachments` | Имя сервиса (title в FastAPI/OpenAPI) | +| `VERSION` | str | нет | `0.0.1` | Версия сервиса | +| `DESCRIPTION` | str | нет | `Attachments` | Описание сервиса | +| `YANDEX_S3_ENDPOINT_URL` | str | да* | — | Endpoint S3 (без схемы; `https://`/`http://` добавляется в коде по `YANDEX_S3_USE_SSL`) | +| `YANDEX_S3_ACCESS_KEY_ID` | str | да* | — | Access Key ID для S3 | +| `YANDEX_S3_SECRET_ACCESS_KEY` | str | да* | — | Secret Access Key для S3 | +| `YANDEX_S3_USE_SSL` | bool | нет | `True` | Использовать ли HTTPS при обращении к S3 | +| `YANDEX_S3_REGION` | str | нет | `ru-central1` | Регион S3 | +| `YANDEX_S3_VERIFY` | bool | да | — | Проверять ли SSL-сертификат S3 | +| `BUCKET_NAME` | str | да | — | Имя бакета для вложений | +| `DATABASE_NAME` | str | да | — | Имя базы данных PostgreSQL | +| `DATABASE_USER` | str | да | — | Пользователь БД | +| `DATABASE_PASSWORD` | str | да | — | Пароль пользователя БД | +| `DATABASE_HOST` | str | да | — | Хост БД | +| `DATABASE_PORT` | int | да | — | Порт БД | +| `DATABASE_SSL_MODE` | str | да | — | Режим SSL при подключении к БД (напр. `disable`, `require`, `verify-full`) | + +\* Три переменные `YANDEX_S3_ENDPOINT_URL`, `YANDEX_S3_ACCESS_KEY_ID`, `YANDEX_S3_SECRET_ACCESS_KEY` формально обязательны, но при старте приложения они **проставляются автоматически** функцией `json_config_s3_account_settings()` из JSON-файла (см. `YANDEX_S3_ACCOUNT_PATH`). Задавать их вручную не нужно, если задан путь к файлу. + +## Настройки S3 через JSON-файл + +| Переменная | Обязательна | Назначение | +| --- | --- | --- | +| `YANDEX_S3_ACCOUNT_PATH` | да | Путь к JSON-файлу с реквизитами сервисного аккаунта S3 | + +При старте функция `json_config_s3_account_settings()` читает файл по этому пути и выставляет переменные окружения `YANDEX_S3_ENDPOINT_URL`, `YANDEX_S3_ACCESS_KEY_ID`, `YANDEX_S3_SECRET_ACCESS_KEY`. + +Ожидаемая структура JSON-файла: + +```json +{ + "endpoint": "storage.yandexcloud.net", + "access_key_id": "<ключ>", + "secret_access_key": "<секрет>" +} +``` + +В Kubernetes файл монтируется из секрета `attachments-s3-secret` (в prod — `yc-s3`) в `/etc/sarex/yc-s3-storage/yc-s3-service-account.json`. + +## Логирование (класс `LoggerSettings`, префикс `LOG_`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `LOG_LEVEL` | str | `INFO` | Уровень логирования (`DEBUG`, `INFO`, `WARNING`, ...). При неизвестном значении откатывается на `INFO` | +| `LOG_FORMAT` | str | JSON-шаблон с полями `timestamp`, `level`, `message` | Формат строк лога (используется `pythonjsonlogger`) | + +## Трейсинг / OpenTelemetry (класс `TraceSettings`, префикс `TRACING_`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRACING_USE` | bool | `False` | Включает OTEL-трейсинг, логгер и middleware | +| `TRACING_HOST` | str | `localhost:4317` | Адрес OTLP-коллектора | +| `TRACING_SERVICE_NAME` | str | `attachments` | Имя сервиса в трейсах | +| `TRACING_INSECURE` | bool | `False` | Небезопасное (без TLS) подключение к коллектору | + +Трейсинг активируется только при `TRACING_USE=true`. + +## Переменные инфраструктуры и сборки + +Не читаются кодом приложения, но нужны для запуска/сборки/деплоя. + +| Переменная | Где используется | Назначение | +| --- | --- | --- | +| `POSTGRES_PASSWORD` | `docker-compose.yml` (контейнер `db`) | Пароль суперпользователя PostgreSQL при локальном запуске | +| `PIP_EXTRA_INDEX_URL` | `docker/Dockerfile` (build-arg) | Доп. индекс pip для установки приватных пакетов при сборке образа | +| `GITLAB_PYPI_EXTRA_INDEX_URL` | `.gitlab-ci.yml` | Значение, пробрасываемое в `PIP_EXTRA_INDEX_URL` при сборке в CI | + +### Переменные CI/CD (`.gitlab-ci.yml`) + +Служебные переменные пайплайна: `SERVICE_NAME`, `DOCKERFILE_PATH`, `BUILD_ARGS`, `CI_TRIGGER_SOURCE`, а также подставляемые по окружениям `STAND`, `NAMESPACE`, `RELEASE_NAME`, `CHART_NAME`, `CHART_VERSION`, `K8S_HUSTLER_BRANCH`, `HELM_SET_ARGS`. Окружение выбирается по ветке/тегу: `stage` → ветка `stage`, `preprod` → ветка `master`, `production` → git-тег. + +## Переменные из Helm-чарта (`.helm/values.yaml`) + +Обычные переменные (`envs`): + +| Переменная | Значение | Примечание | +| --- | --- | --- | +| `API_ADDRESS` | `0.0.0.0:8000` | Задаётся в чарте, но **кодом приложения не читается** | +| `POSTGRES_POOL_SIZE` | `10` | Задаётся в чарте, но **кодом приложения не читается** | +| `DATABASE_SSL_MODE` | `verify-full` | | +| `YANDEX_S3_VERIFY` | `true` | | +| `YANDEX_S3_ACCOUNT_PATH` | `/etc/sarex/yc-s3-storage/yc-s3-service-account.json` | | +| `BUCKET_NAME` | `attachments-stage-2` / `attachments-prod-2` | Зависит от окружения | + +Переменные из секретов (`secretEnvs`, секрет `attachments-postgresql-secret` / `ya-pg-secret`): + +| Переменная | Ключ секрета | Примечание | +| --- | --- | --- | +| `DATABASE_PORT` | `port` | | +| `DATABASE_HOST` | `host` | | +| `DATABASE_USER` | `username` | | +| `DATABASE_PASSWORD` | `password` | | +| `DATABASE_NAME` | `database` | | +| `YC-PG-CERTIFICATE` | `ca.crt` | CA-сертификат PostgreSQL; также монтируется файлом в `/root/.postgresql/root.crt` | + +## Минимальный набор для локального запуска + +Для запуска через `docker-compose` в файле `.env` достаточно задать (см. `.env.example`): + +- `POSTGRES_PASSWORD` — для контейнера БД +- `DATABASE_*` — параметры подключения к БД +- `BUCKET_NAME`, `YANDEX_S3_VERIFY` +- `YANDEX_S3_ACCOUNT_PATH` **или** напрямую `YANDEX_S3_ENDPOINT_URL` + `YANDEX_S3_ACCESS_KEY_ID` + `YANDEX_S3_SECRET_ACCESS_KEY` diff --git a/apps/transmittal/.env.example b/apps/transmittal/.env.example new file mode 100644 index 0000000..1fa7fdd --- /dev/null +++ b/apps/transmittal/.env.example @@ -0,0 +1,121 @@ +# App +TRANSMITTAL_SERVICE_APP__NAME='Transmittal Service' +TRANSMITTAL_SERVICE_APP__LOG_LEVEL=INFO +TRANSMITTAL_SERVICE_APP__HOST=https://stage.sarex.io/transmittal +TRANSMITTAL_SERVICE_APP__ENVIRONMENT=stage + +# Auth +# Replace newlines with \n +TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY='' + +# CORS +TRANSMITTAL_SERVICE_CORS__ALLOW_ORIGINS='["*"]' +TRANSMITTAL_SERVICE_CORS__ALLOW_METHODS='["*"]' +TRANSMITTAL_SERVICE_CORS__ALLOW_HEADERS='["*"]' +TRANSMITTAL_SERVICE_CORS__ALLOW_CREDENTIALS=True + +# Uvicorn +TRANSMITTAL_SERVICE_UVICORN__HOST=127.0.0.1 +TRANSMITTAL_SERVICE_UVICORN__PORT=8001 +TRANSMITTAL_SERVICE_UVICORN__ENABLE_AUTO_RELOAD=False +TRANSMITTAL_SERVICE_UVICORN__LOG_LEVEL=info +TRANSMITTAL_SERVICE_UVICORN__NUM_WORKERS=1 +TRANSMITTAL_SERVICE_UVICORN__ROOT_PATH='' + +# Database +TRANSMITTAL_SERVICE_DATABASE__USER=postgres +TRANSMITTAL_SERVICE_DATABASE__PASSWORD=password +TRANSMITTAL_SERVICE_DATABASE__HOST=127.0.0.1 +TRANSMITTAL_SERVICE_DATABASE__PORT=5432 +TRANSMITTAL_SERVICE_DATABASE__NAME=postgres +# Ssl settings +TRANSMITTAL_SERVICE_DATABASE__ENABLE_SSL=false +TRANSMITTAL_SERVICE_DATABASE__SSL_MODE=verify-full # or verify-ca +TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH=root.crt + +# For local database +# TRANSMITTAL_SERVICE_PGDATA=/var/lib/postgresql/data/pgdata +# TRANSMITTAL_SERVICE_PGHOST=127.0.0.1 +# TRANSMITTAL_SERVICE_PGPORT=5432 + +# RabbitMQ +TRANSMITTAL_SERVICE_RABBITMQ__USER=guest +TRANSMITTAL_SERVICE_RABBITMQ__PASSWORD=guest +TRANSMITTAL_SERVICE_RABBITMQ__VHOST=/ +TRANSMITTAL_SERVICE_RABBITMQ__HOST=localhost +TRANSMITTAL_SERVICE_RABBITMQ__PORT=5672 + +# Sarex backend repository +TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASE_URL=https://stage.sarex.io +TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__TIMEOUT=30 +TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASIC_AUTH_ENCODED= + +# Resource repository +TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__BASE_URL=http://sarex-resources-service.resources-stage +TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__TIMEOUT=30 + +# Flows repository +TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__BASE_URL= +TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__TIMEOUT=30 + +# Documentations repository +TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__BASE_URL=http://api-service.documentations-stage +TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__TIMEOUT=30 + +# S3 +TRANSMITTAL_SERVICE_S3_CLIENT__MAX_POOL_CONNECTIONS=10 +TRANSMITTAL_SERVICE_S3_CLIENT__CONNECT_TIMEOUT=10 +TRANSMITTAL_SERVICE_S3_CLIENT__READ_TIMEOUT=30 +TRANSMITTAL_SERVICE_S3_CLIENT__REGION_NAME=ru-central1 +TRANSMITTAL_SERVICE_S3_CLIENT__VERIFY=True +TRANSMITTAL_SERVICE_S3_CLIENT__DEFAULT_BUCKET=transmittal-storage-stage +TRANSMITTAL_SERVICE_S3_CLIENT__ENDPOINT=storage.yandexcloud.net +TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY= +TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY= +TRANSMITTAL_SERVICE_S3_CLIENT__USE_SSL=True +TRANSMITTAL_SERVICE_S3_CLIENT__USE_PATH_STYLE=True +TRANSMITTAL_SERVICE_S3_CLIENT__REQUEST_CHECKSUM_CALCULATION=when_required +TRANSMITTAL_SERVICE_S3_CLIENT__RESPONSE_CHECKSUM_VALIDATION=when_required + +# Html to pdf converter +TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__BASE_URL=http://export-project-service.sarex-stage +TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__TIMEOUT=30 + +# Markings +TRANSMITTAL_SERVICE_MARKINGS__BASE_URL=http://pdf-markings-service.processing-stage +TRANSMITTAL_SERVICE_MARKINGS__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_MARKINGS__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_MARKINGS__TIMEOUT=30 + +# You must use exactly one of email configuration (mailgun or smtp), mailgun considered to be default +# Mailgun +TRANSMITTAL_SERVICE_MAILGUN__BASE_URL=https://api.mailgun.net/v3/ +TRANSMITTAL_SERVICE_MAILGUN__MAX_CONNECTIONS=10 +TRANSMITTAL_SERVICE_MAILGUN__MAX_KEEPALIVE_CONNECTIONS=5 +TRANSMITTAL_SERVICE_MAILGUN__TIMEOUT=30 +TRANSMITTAL_SERVICE_MAILGUN__EMAIL=some@example.com +TRANSMITTAL_SERVICE_MAILGUN__API_KEY="" + +# Smtp +# TRANSMITTAL_SERVICE_SMTP__HOST= +# TRANSMITTAL_SERVICE_SMTP__PORT= +# TRANSMITTAL_SERVICE_SMTP__EMAIL= +# TRANSMITTAL_SERVICE_SMTP__ENABLE_TLS= +# TRANSMITTAL_SERVICE_SMTP__LOGIN= +# TRANSMITTAL_SERVICE_SMTP__PASSWORD= + +# Otel +TRANSMITTAL_SERVICE_OTEL__ENABLE=True +TRANSMITTAL_SERVICE_OTEL__HOST=http://localhost:4317 +TRANSMITTAL_SERVICE_OTEL__SERVICE_NAME=backend.transmittals +TRANSMITTAL_SERVICE_OTEL__INSECURE=True \ No newline at end of file diff --git a/apps/transmittal/CONFIGURATION.md b/apps/transmittal/CONFIGURATION.md new file mode 100644 index 0000000..44ae379 --- /dev/null +++ b/apps/transmittal/CONFIGURATION.md @@ -0,0 +1,263 @@ +# Конфигурация проекта transmittal-api + +Документ описывает все переменные окружения и способы конфигурирования сервиса. + +## Способы конфигурирования + +Сервис настраивается **только через переменные окружения**. Разбор выполняется в `src/transmittal_service/infra/settings.py` через библиотеку [`pydantic-settings`](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) (класс `AppSettings`). + +Особенности разбора (`SettingsConfigDict`): + +- `env_prefix="TRANSMITTAL_SERVICE_"` — все переменные приложения начинаются с этого префикса; +- `env_nested_delimiter="__"` — вложенные секции задаются двойным подчёркиванием, напр. `TRANSMITTAL_SERVICE_DATABASE__HOST` → `database.host`; +- `env_ignore_empty=False` — пустая строка считается заданным значением (не игнорируется), поэтому пустое обязательное поле-строка проходит валидацию, а вот отсутствие обязательного поля приводит к ошибке старта. + +Отдельного конфиг-файла (yaml/toml) у приложения нет. Настройки Uvicorn читаются отдельным классом `UvicornSettings` (тот же префикс/делимитер). + +Источники переменных по способам запуска: + +| Способ запуска | Откуда берутся переменные | +| --- | --- | +| Локально (бинарник) | Переменные окружения процесса. `make config` копирует `.example.env` → `.env` как шаблон, но приложение **не загружает `.env` автоматически** (в коде нет `env_file`/`dotenv`) — файл нужно экспортировать самому, напр. `set -a && . ./.env && set +a` | +| Локально (контейнеры) | `makefile`: цели `container-run`, `container-run-database`, `container-run-rabbitmq` пробрасывают переменные хоста через `--env` | +| Kubernetes (Helm) | `.helm/values-.yaml`: блок `envs` (обычные значения) и `secrets` (значения из k8s-секретов); шаблоны `deployment.yaml`, `worker.yaml`, `crontab_periodic.yaml` | +| CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна (`workflow.rules`) и переменные job-а `test-unit` для запуска тестов | + +Способы запуска процессов (`[project.scripts]` в `pyproject.toml`): + +| Команда | Точка входа | Назначение | +| --- | --- | --- | +| `start_api` (`make run-api`) | `cmd/api.py` | HTTP API (uvicorn/gunicorn) | +| `taskiq worker …` (`make run-worker`) | `tasks.broker:broker` | Обработчик фоновых задач | +| `process_expired_transmittals` | `cmd/process_expired_transmittals.py` | Разовая задача обработки просроченных трансмитталов (в k8s — CronJob `0 3 * * *`) | +| `create_system_values` | `cmd/create_system_values.py` | Создание системных значений | +| `generate-act` | `cmd/generate_act.py` | Генерация акта | + +Порядок запуска в контейнере (`scripts/entrypoint.sh`): сначала выполняются миграции (`alembic upgrade heads`), затем стартует gunicorn с воркерами `ConfigurableWorker`. + +## Переменные приложения + +Все перечисленные ниже переменные имеют префикс `TRANSMITTAL_SERVICE_`. В столбце «Переменная» указано полное имя. Дефолт `—` означает, что значение обязательно (иначе ошибка старта). + +### App (`app.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_APP__NAME` | string | `Transmittal Service` | Имя приложения | +| `TRANSMITTAL_SERVICE_APP__LOG_LEVEL` | enum | `INFO` | Уровень логирования: `CRITICAL`/`FATAL`/`ERROR`/`WARNING`/`WARN`/`INFO`/`DEBUG`/`NOTSET` | +| `TRANSMITTAL_SERVICE_APP__ENVIRONMENT` | enum | — | Окружение развёртывания: `stage`/`preprod`/`prod` | +| `TRANSMITTAL_SERVICE_APP__HOST` | string | — | Внешний базовый URL сервиса (используется в письмах/ссылках) | + +### Auth (`auth.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY` | string | — | Публичный RSA-ключ для проверки JWT. Экранированные `\n` автоматически заменяются на реальные переводы строк | + +### CORS (`cors.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_CORS__ALLOW_ORIGINS` | list[str] (JSON) | — | Разрешённые Origin, напр. `["*"]` | +| `TRANSMITTAL_SERVICE_CORS__ALLOW_METHODS` | list[str] (JSON) | — | Разрешённые HTTP-методы | +| `TRANSMITTAL_SERVICE_CORS__ALLOW_HEADERS` | list[str] (JSON) | — | Разрешённые заголовки | +| `TRANSMITTAL_SERVICE_CORS__ALLOW_CREDENTIALS` | bool | — | Разрешить передачу учётных данных | + +### Uvicorn (`uvicorn.*`) + +Читаются отдельным классом `UvicornSettings`. + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_UVICORN__HOST` | string | `127.0.0.1` | Адрес прослушивания | +| `TRANSMITTAL_SERVICE_UVICORN__PORT` | int | `8001` | Порт | +| `TRANSMITTAL_SERVICE_UVICORN__ENABLE_AUTO_RELOAD` | bool | `False` | Live/hot-reload (для разработки) | +| `TRANSMITTAL_SERVICE_UVICORN__LOG_LEVEL` | enum | `info` | `critical`/`error`/`warning`/`info`/`debug`/`trace` | +| `TRANSMITTAL_SERVICE_UVICORN__NUM_WORKERS` | int | `1` | Число воркеров gunicorn | +| `TRANSMITTAL_SERVICE_UVICORN__ROOT_PATH` | string | `""` | Root path (префикс за реверс-прокси) | + +### Database (`database.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_DATABASE__HOST` | string | — | Хост PostgreSQL | +| `TRANSMITTAL_SERVICE_DATABASE__PORT` | int | — | Порт PostgreSQL | +| `TRANSMITTAL_SERVICE_DATABASE__USER` | string | — | Пользователь БД | +| `TRANSMITTAL_SERVICE_DATABASE__PASSWORD` | string | — | Пароль пользователя БД | +| `TRANSMITTAL_SERVICE_DATABASE__NAME` | string | — | Имя базы данных | +| `TRANSMITTAL_SERVICE_DATABASE__POOL_SIZE` | int | `5` | Размер пула соединений | +| `TRANSMITTAL_SERVICE_DATABASE__MAX_POOL_OVERFLOW` | int | `5` | Доп. соединения сверх пула | +| `TRANSMITTAL_SERVICE_DATABASE__ENABLE_SSL` | bool | — | Подключение к БД по TLS | +| `TRANSMITTAL_SERVICE_DATABASE__SSL_MODE` | enum | — | `verify-full`/`verify-ca`/`""`. Обязателен при `ENABLE_SSL=true` | +| `TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH` | string | — | Путь к CA-сертификату. Обязателен при `ENABLE_SSL=true` | + +> При `ENABLE_SSL=true` валидатор требует непустые `SSL_MODE` и `SSL_ROOT_CERT_PATH`, иначе — ошибка старта. Итоговый DSN собирается в `database.uri`. + +### RabbitMQ (`rabbitmq.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_RABBITMQ__USER` | string | — | Пользователь | +| `TRANSMITTAL_SERVICE_RABBITMQ__PASSWORD` | string | — | Пароль | +| `TRANSMITTAL_SERVICE_RABBITMQ__VHOST` | string | — | Виртуальный хост | +| `TRANSMITTAL_SERVICE_RABBITMQ__HOST` | string | — | Хост | +| `TRANSMITTAL_SERVICE_RABBITMQ__PORT` | int | — | Порт | + +### HTTP-клиенты внешних сервисов + +Все клиенты наследуют общий набор полей (`HttpClient`): `BASE_URL`, `MAX_CONNECTIONS`, `MAX_KEEPALIVE_CONNECTIONS`, `TIMEOUT`. Все четыре поля обязательны (дефолтов нет). + +| Секция / префикс | Назначение | Доп. поля | +| --- | --- | --- | +| `TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__*` | Основной backend Sarex | `BASIC_AUTH_ENCODED` — base64 от `login:password` (обязателен), декодируется в пару login/password | +| `TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__*` | Сервис ресурсов (IAM/resources) | — | +| `TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__*` | Сервис документаций | — | +| `TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__*` | Сервис flows | — | +| `TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__*` | Конвертер HTML→PDF (export-project) | — | +| `TRANSMITTAL_SERVICE_MARKINGS__*` | Сервис PDF-маркировок | — | + +Для каждого — четыре переменные, напр. для markings: + +| Переменная | Тип | Назначение | +| --- | --- | --- | +| `TRANSMITTAL_SERVICE_MARKINGS__BASE_URL` | string | Базовый URL сервиса | +| `TRANSMITTAL_SERVICE_MARKINGS__MAX_CONNECTIONS` | int | Макс. число соединений | +| `TRANSMITTAL_SERVICE_MARKINGS__MAX_KEEPALIVE_CONNECTIONS` | int | Макс. keep-alive соединений | +| `TRANSMITTAL_SERVICE_MARKINGS__TIMEOUT` | int | Таймаут запроса (сек) | + +Для `SAREX_BACKEND_REPOSITORY` дополнительно: + +| Переменная | Тип | Назначение | +| --- | --- | --- | +| `TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASIC_AUTH_ENCODED` | string (base64) | Basic-auth в виде base64(`login:password`) | + +### S3 (`s3_client.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_S3_CLIENT__ENDPOINT` | string | — | Эндпоинт S3. Если без `http(s)://` — префикс добавляется автоматически по `USE_SSL` | +| `TRANSMITTAL_SERVICE_S3_CLIENT__REGION_NAME` | string | — | Регион | +| `TRANSMITTAL_SERVICE_S3_CLIENT__DEFAULT_BUCKET` | string | — | Бакет по умолчанию | +| `TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY` | string | — | Access key | +| `TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY` | string | — | Secret key | +| `TRANSMITTAL_SERVICE_S3_CLIENT__USE_SSL` | bool | — | Использовать SSL | +| `TRANSMITTAL_SERVICE_S3_CLIENT__VERIFY` | bool | — | Проверять TLS-сертификат | +| `TRANSMITTAL_SERVICE_S3_CLIENT__MAX_POOL_CONNECTIONS` | int | `10` | Размер пула соединений | +| `TRANSMITTAL_SERVICE_S3_CLIENT__CONNECT_TIMEOUT` | int | `10` | Таймаут подключения (сек) | +| `TRANSMITTAL_SERVICE_S3_CLIENT__READ_TIMEOUT` | int | `30` | Таймаут чтения (сек) | +| `TRANSMITTAL_SERVICE_S3_CLIENT__USE_PATH_STYLE` | bool | `True` | Path-style адресация | +| `TRANSMITTAL_SERVICE_S3_CLIENT__REQUEST_CHECKSUM_CALCULATION` | enum | `when_required` | `when_supported`/`when_required` | +| `TRANSMITTAL_SERVICE_S3_CLIENT__RESPONSE_CHECKSUM_VALIDATION` | enum | `when_required` | `when_supported`/`when_required` | + +### Почта: Mailgun или SMTP + +Должен быть настроен **ровно один** из двух сервисов (валидатор `check_mailing_service`), иначе — ошибка старта. По умолчанию используется Mailgun. + +Mailgun (`mailgun.*`) — наследует поля `HttpClient` плюс: + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_MAILGUN__BASE_URL` | string | — | URL API, напр. `https://api.mailgun.net/v3/` | +| `TRANSMITTAL_SERVICE_MAILGUN__MAX_CONNECTIONS` | int | — | Макс. соединений | +| `TRANSMITTAL_SERVICE_MAILGUN__MAX_KEEPALIVE_CONNECTIONS` | int | — | Макс. keep-alive | +| `TRANSMITTAL_SERVICE_MAILGUN__TIMEOUT` | int | — | Таймаут (сек) | +| `TRANSMITTAL_SERVICE_MAILGUN__EMAIL` | string | — | Адрес отправителя | +| `TRANSMITTAL_SERVICE_MAILGUN__API_KEY` | string | — | API-ключ Mailgun | + +SMTP (`smtp.*`) — альтернатива Mailgun: + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_SMTP__HOST` | string | — | SMTP-хост | +| `TRANSMITTAL_SERVICE_SMTP__PORT` | int | — | SMTP-порт | +| `TRANSMITTAL_SERVICE_SMTP__EMAIL` | string | — | Адрес отправителя | +| `TRANSMITTAL_SERVICE_SMTP__ENABLE_TLS` | bool | `False` | Включить TLS | +| `TRANSMITTAL_SERVICE_SMTP__LOGIN` | string \| null | `None` | Логин | +| `TRANSMITTAL_SERVICE_SMTP__PASSWORD` | string \| null | `None` | Пароль | + +### OpenTelemetry (`otel.*`) + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `TRANSMITTAL_SERVICE_OTEL__ENABLE` | bool | `False` | Включить трейсинг | +| `TRANSMITTAL_SERVICE_OTEL__HOST` | string | — | Адрес OTLP-коллектора | +| `TRANSMITTAL_SERVICE_OTEL__SERVICE_NAME` | string | — | Имя сервиса в трейсах | +| `TRANSMITTAL_SERVICE_OTEL__INSECURE` | bool | `False` | Небезопасное (без TLS) подключение к коллектору | + +## Переменные инфраструктуры, сборки и вспомогательных утилит + +Не читаются кодом приложения, но участвуют в запуске/сборке/деплое. + +| Переменная | Где используется | Назначение | +| --- | --- | --- | +| `TRANSMITTAL_SERVICE_PGDATA` | `.example.env` (закомментировано) | Каталог данных локального PostgreSQL | +| `TRANSMITTAL_SERVICE_PGHOST` | `.example.env` (закомментировано) | Хост локального PostgreSQL | +| `TRANSMITTAL_SERVICE_PGPORT` | `makefile` (`container-run-database`) | Внутренний порт контейнера Postgres при пробросе | +| `OCI` | `makefile` | Инструмент контейнеризации (`docker`/`podman`), по умолчанию `docker` | +| `TRANSMITTAL_SERVICE_IMAGE_NAME` / `TRANSMITTAL_SERVICE_IMAGE_VERSION` | `makefile` | Имя/тег собираемого образа | +| `TRANSMITTAL_SERVICE_CONTAINER__NETWORK_NAME` | `makefile` | Имя docker-сети | +| `TRANSMITTAL_SERVICE_DATABASE_CONTAINER__*` | `makefile` | Параметры контейнера Postgres (образ, имя, volume) | +| `TRANSMITTAL_SERVICE_RABBITMQ_CONATINER__*` | `makefile` | Параметры контейнера RabbitMQ | +| `PIP_INDEX_URL`, `PIP_TRUSTED_HOST` | `Dockerfile` (build-arg) | Приватный индекс пакетов при сборке | +| `TRANSMITTAL_SERVICE_PYTHON_IMAGE_NAME`, `TRANSMITTAL_SERVICE_PYTHON_IMAGE_TAG` | `Dockerfile` (build-arg) | Базовый образ Python (по умолчанию `python:3.12-slim`) | +| `UID`, `GID`, `USERNAME` | `Dockerfile` (build-arg) | Пользователь внутри образа (по умолчанию `10000`/`10001`/`transmittal_service`) | + +## Переменные из Helm-чарта (`.helm/values-.yaml`) + +Обычные значения задаются в блоке `envs` для каждого окружения (`stage`/`preprod`/`production`) и содержат те же переменные приложения `TRANSMITTAL_SERVICE_*`, что описаны выше (различаются адресами БД/сервисов, портами, `LOG_LEVEL`, `ROOT_PATH`, бакетом, доменом Mailgun и т.п.). + +Значения из секретов (блок `secrets`, монтируются как env через `secretKeyRef`): + +| Переменная | Секрет (`secret_name`) | Ключ (`secret_key`) | +| --- | --- | --- | +| `TRANSMITTAL_SERVICE_DATABASE__USER` | `ya-pg-secret` | `username` | +| `TRANSMITTAL_SERVICE_DATABASE__PASSWORD` | `ya-pg-secret` | `password` | +| `YC-PG-CERTIFICATE` | `ya-pg-secret` | `certificate` | +| `TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY` | `public-key` | `key` | +| `TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASIC_AUTH_ENCODED` | `django-auth` | `key` | +| `TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY` | `s3-secret` | `access_key` | +| `TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY` | `s3-secret` | `secret_key` | +| `TRANSMITTAL_SERVICE_RABBITMQ__USER` | `rabbitmq-cred` | `username` | +| `TRANSMITTAL_SERVICE_RABBITMQ__PASSWORD` | `rabbitmq-cred` | `password` | +| `TRANSMITTAL_SERVICE_MAILGUN__API_KEY` | `mailgun-cred` | `api_key` | + +Помимо env, чарт монтирует CA-сертификат PostgreSQL из секрета `ya-pg-secret` (ключ `certificate`) как файл `/opt/.postgresql/root.crt` — именно на него указывает `TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH` в prod-конфигурации. + +Прочие значения чарта (не переменные приложения): `deployment.*` (имя, образ, порт, реплики, ресурсы), `api.*` (host/prefix/path ingress), `worker.*`, `job.name_periodic`, `imagePullSecrets`. + +## Переменные в CI (`.gitlab-ci.yml`) + +Пайплайн подключает общие шаблоны из `generic/common-ci` и переключает окружение по ветке/тегу через `workflow.rules`: + +| Условие | STAND | Namespace | +| --- | --- | --- | +| ветка `master` | `preprod` | `transmittal-api-preprod` | +| ветка `stage` | `stage` | `transmittal-api-stage` | +| тег (`CI_COMMIT_TAG`) | `prod` | `transmittal-api-prod` | + +Ключевые переменные пайплайна: `RELEASE_NAME`, `CHART_NAME`, `CHART_VERSION`, `DOCKERFILE_PATH`, `HELM_SET_ARGS` (`--set deployment.image=…`), флаги `ENABLE_LINTER`/`ENABLE_BUILD_CHART`/`ENABLE_BUILD_IMAGE`/`ENABLE_DEPLOY`. Job `test-unit` задаёт полный набор `TRANSMITTAL_SERVICE_*` переменных для прогона юнит-тестов. + +## Замечания и потенциальные проблемы + +- Переменные БД в `.example.env` должны иметь префикс `TRANSMITTAL_SERVICE_DATABASE__*` — код читает их именно так. Ранее в файле они были записаны без префикса (`DATABASE__USER` и т.д.) и не подхватывались; сейчас исправлено. В `makefile`, `.gitlab-ci.yml` и Helm имена с префиксом корректны. +- Приложение **не загружает `.env` автоматически** (в `settings.py` не задан `env_file`, зависимости `python-dotenv` нет). `make config` лишь создаёт файл-шаблон; переменные нужно экспортировать в окружение вручную либо задавать через `--env` (см. `make container-run`). +- `env_ignore_empty=False`: пустая строка воспринимается как заданное значение. Например `TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY=''` — валидное (пустой ключ), а вот полностью отсутствующая обязательная переменная вызовет ошибку старта. +- Переменная `YC-PG-CERTIFICATE` прокидывается из секрета в окружение, но **кодом приложения не читается** — сертификат используется как смонтированный файл (`root.crt`). Имя с дефисами не соответствует схеме `TRANSMITTAL_SERVICE_*`. +- Почтовый сервис: должен быть задан ровно один из `mailgun`/`smtp`. Если заданы оба или ни одного — сервис не стартует. +- В `.example.env` секция `FLOWS_REPOSITORY__BASE_URL` пустая, но поле обязательно — для реального запуска его нужно заполнить. + +## Минимальный набор для локального запуска + +Postgres и RabbitMQ поднимаются через `make container-deps`, приложение — через `make run-api` / `make run-worker`. Минимально необходимо задать (с префиксом `TRANSMITTAL_SERVICE_`): + +- `APP__ENVIRONMENT`, `APP__HOST` +- `AUTH__PUBLIC_KEY` (можно пустой для локальной разработки) +- `CORS__ALLOW_ORIGINS`, `CORS__ALLOW_METHODS`, `CORS__ALLOW_HEADERS`, `CORS__ALLOW_CREDENTIALS` +- `DATABASE__HOST`, `DATABASE__PORT`, `DATABASE__USER`, `DATABASE__PASSWORD`, `DATABASE__NAME`, `DATABASE__ENABLE_SSL` (`false` локально), `DATABASE__SSL_MODE`, `DATABASE__SSL_ROOT_CERT_PATH` +- `RABBITMQ__USER`, `RABBITMQ__PASSWORD`, `RABBITMQ__VHOST`, `RABBITMQ__HOST`, `RABBITMQ__PORT` +- `BASE_URL`/`MAX_CONNECTIONS`/`MAX_KEEPALIVE_CONNECTIONS`/`TIMEOUT` для всех шести HTTP-клиентов (`SAREX_BACKEND_REPOSITORY` + `BASIC_AUTH_ENCODED`, `RESOURCE_REPOSITORY`, `DOCUMENTATIONS_REPOSITORY`, `FLOWS_REPOSITORY`, `HTML_TO_PDF_CONVERTER`, `MARKINGS`) +- `S3_CLIENT__*` (эндпоинт, регион, бакет, ключи, `USE_SSL`, `VERIFY`) +- один из почтовых сервисов: `MAILGUN__*` **или** `SMTP__*` +- `OTEL__ENABLE` (`False` локально), при `True` — `OTEL__HOST`, `OTEL__SERVICE_NAME` + +Готовые значения-примеры для всех переменных приведены в `.example.env` (с учётом замечаний выше по префиксу БД). \ No newline at end of file diff --git a/apps/transmittal/ENDPOINTS.md b/apps/transmittal/ENDPOINTS.md new file mode 100644 index 0000000..d607615 --- /dev/null +++ b/apps/transmittal/ENDPOINTS.md @@ -0,0 +1,185 @@ +# Эндпоинты, с которыми взаимодействует transmittal-frontend + +Документ описывает все HTTP-эндпоинты внешних сервисов, к которым обращается модуль (микрофронтенд `transmittal-frontend`). + +## Как устроено взаимодействие + +Все запросы описаны декларативно в реестре `module/api/endpoints.ts` (объект `endpoints`). Каждый эндпоинт задаётся структурой `Endpoint`: + +- `service` — логическое имя сервиса (см. таблицу хостов ниже); +- `method` — HTTP-метод (`GET`/`POST`/`PUT`/`PATCH`/`DELETE`); +- `path(args)` — функция, возвращающая путь запроса (с подстановкой параметров/query); +- `body(args)` — опционально, формирование тела запроса; +- `cache`, `queryOptions`, `responseType`, `axiosConfig` — опции кеширования, повторов и типа ответа. + +Запрос выполняется единой функцией `fetch(endpoint, params, controller)`, которая через `httpService` (`module/api/http-service.ts`, поверх `@sarex-team/sdk-js` + `axios`) отправляет запрос на базовый хост сервиса. Базовый хост подставляется `resolveHost(service)` из `module/api/hosts.ts` в зависимости от `BUILD_ENV`. Ошибки маппируются в человекочитаемые сообщения в `module/api/errors.ts`. + +## Базовые хосты по сервисам и окружениям + +Значения из `module/api/hosts.ts`. Итоговый URL = `<базовый хост сервиса>` + `path` эндпоинта. + +| Сервис (`service`) | Назначение | `stage` | `prod` | +| --- | --- | --- | --- | +| `transmittals` | Сервис передачи документации (трансмитталы, шаблоны) | `https://stage-api.sarex.io/transmittals` | `https://api.sarex.io/transmittals` | +| `documentations` | Сервис документации (документы, бандлы, файлы) | `https://stage-api.sarex.io/documentations` | `https://api.sarex.io/documentations` | +| `sarexApi` | Gateway/API Sarex (`/gateway`, `/eav`, `/cde`) | `https://stage-api.sarex.io` | `https://api.sarex.io` | +| `sarex` | Локальный сервис данных (`/api/core`, `/api/client`) | `""` (относительные пути) | `""` | +| `processes` | Сервис рабочих процессов (flows, reviews) | `https://stage-api.sarex.io/flows` | `https://api.sarex.io/flows` | +| `workflows` | Сервис обработки документов | `https://stage-api.sarex.io/workflows` | `https://api.sarex.io/workflows` | +| `workspaces` | Сервис рабочих областей | `https://stage-api.sarex.io/workspaces` | `https://api.sarex.io/workspaces` | +| `remarks` | Сервис замечаний | `https://stage-api.sarex.io/remarks` | `https://api.sarex.io/remarks` | +| `files` | Сервис файлов | `https://stage-api.sarex.io/files` | `https://api.sarex.io/files` | +| `google` | Временное хранилище (GCS) | `https://storage.googleapis.com/srx-tmp` | `https://storage.googleapis.com/srx-tmp` | +| `bim` | BIM-API | `https://stage-bim-api.sarex.io` | `https://bim-api.sarex.io` | +| `zitadel` | IdP (аутентификация) | `https://idp.dev.stage.sarex.io` | `https://login.sarex.io` | + +> Также определены окружения `local`, `preprod` и `contour` (относительные пути для изолированного контура). В `local` сервис `sarex` проксируется на `/sarex-backend`. Подключаемый удалённый модуль documentations описан отдельно в `module/api/module-hosts.ts`. + +## Эндпоинты по сервисам + +### `transmittals` — Сервис передачи документации + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getTransmittals` | POST | `api/v1/transmittals` | Список трансмитталов (пагинация по `bookmark`, фильтр по `resource_id`) | +| `getTransmittalStatuses` | POST | `api/v1/transmittals/global_statuses` | Глобальные статусы по набору `resource_ids` | +| `getTransmittalById` | GET | `api/v1/transmittals/{transmittalId}` | Трансмиттал по id | +| `getAct` | GET | `api/v1/transmittals/{transmittalId}/act_available` | Доступность акта для трансмиттала | +| `downloadAct` | GET | `api/v1/transmittals/{transmittalId}/download_act` | Скачивание акта | +| `createTransmittal` | POST | `api/v1/transmittals/create` | Создание трансмиттала | +| `approveTransmittal` | PUT | `api/v1/transmittals/{transmittalId}/approve` | Принять трансмиттал (с комментарием) | +| `declineTransmittal` | PUT | `api/v1/transmittals/{transmittalId}/decline` | Отклонить трансмиттал (с комментарием) | +| `deleteTransmittal` | DELETE | `api/v1/transmittals/{transmittalId}` | Удалить трансмиттал | +| `linkReviewToTransmittal` | POST | `api/v1/transmittals/{transmittalId}/link_review` | Привязать review к трансмитталу | +| `getStatusTypes` | GET | `api/v1/transmittals/status` | Справочник типов статусов | +| `getSearchProject` | POST | `api/v1/transmittals/search` | Поиск/фильтрация трансмитталов в проекте | +| `getSearchProjects` | POST | `api/v1/transmittals/search/resources` | Поиск/фильтрация по нескольким ресурсам | +| `getSteps` | GET | `api/v1/steps` | Список шагов | +| `getStep` | GET | `api/v1/steps/{id}` | Шаг по id | +| `getSearchTemplates` | POST | `/api/v1/transmittal_templates` | Поиск шаблонов трансмитталов | +| `createTemplate` | POST | `/api/v1/transmittal_templates/create` | Создать шаблон | +| `updateTemplate` | PATCH | `/api/v1/transmittal_templates/{templateId}` | Обновить шаблон | +| `deleteTemplate` | DELETE | `/api/v1/transmittal_templates/{templateId}` | Удалить шаблон | +| `getTemplateListForSelect` | GET | `/api/v1/transmittal_templates/select?resource={resourceId}` | Список шаблонов для выбора | +| `getSingleTemplate` | GET | `/api/v1/transmittal_templates/{templateId}?resource={resourceId}` | Шаблон по id | + +### `documentations` — Сервис документации + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getDisks` | GET | `api/v1/disks` | Список дисков | +| `getAllPermmission` | GET | `api/v1/permissions` | Все права доступа | +| `getDocPermission` | GET | `api/v1/documents/{id}/permissions` | Права доступа документа | +| `postPermission` | POST | `api/v1/documents/{id}/permissions` | Выдать права сервисному аккаунту | +| `postBundle` | POST | `api/v1/bundles` | Создать бандл | +| `postFile` | POST | `api/v1/bundles/{bundleId}/{fileKey}?single_upload=1` | Загрузить файл (single upload) | +| `uploadFolderStart` | POST | `api/v1/bundles/{bundleId}/{key}/upload_multipart?upload_path={folderPath}` | Начать multipart-загрузку | +| `uploadPart` | PUT | `api/v1/bundles/{bundleId}/{bundleKey}?part_number={partNumber}` | Загрузить часть файла | +| `bundleComplite` | POST | `api/v1/bundles/{bundleId}/upload_finish` | Завершить загрузку бандла | +| `getFile` | GET | `api/v1/bundles/{bundleId}/{bundleKey}` | Получить файл бандла | +| `getBundles` | GET | `api/v1/documents/{id}/bundles` | Бандлы документа | +| `addBundle` | POST | `api/v1/documents/{documentId}/add_bundle` | Привязать бандл к документу | +| `moveBundles` | PATCH | `api/v1/documents/{documentId}/move_bundles` | Переместить бандлы | +| `removeBundle` | DELETE | `api/v1/bundles/{id}` | Удалить бандл | +| `postWorkspace` | POST | `api/v1/workspaces` | Создать рабочую область | +| `getDocumentById` | GET | `api/v1/documents/{id}` | Документ по id | +| `getDocumentWithBundles` | GET | `api/v1/documents/{id}?extend=bundles` | Документ с бандлами | +| `fetchBatchDocuments` | POST | `/api/v1/documents/batch` | Пакетное получение документов | +| `changeDocument` | PATCH | `api/v1/documents/{id}` | Переименовать документ | +| `updatePath` | PATCH | `api/v1/documents/{id}/update-path` | Сменить родителя документа | +| `updateDocumentsPaths` | PATCH | `api/v1/documents/update-path` | Массовая смена родителя | +| `deleteDocument` | DELETE | `api/v1/documents/{id}` | Удалить документ | +| `deleteDocuments` | DELETE | `api/v1/documents?document_ids={ids}` | Удалить несколько документов | +| `downloadFile` | GET | `api/v1/bundles/{lastBundleId}/{key}/download` | Скачать файл | +| `downloadAllFiles` | GET | `api/v1/bundles/{lastBundleId}/download` | Скачать все файлы бандла | +| `downloadFolder` | GET | `api/v1/documents/{docId}/download?depth={depth}` | Скачать папку | +| `getFolderChildrenWithActiveProcesses` | POST | `/api/v1/documents/flows` | Дети папки с активными процессами | +| `conversionFile` | POST | `api/v1/conversion` | Конвертация документа (в IFC) | +| `addMarks` | PUT | `api/v1/bundles/{bundleId}/marks` | Добавить штампы/QR/подписи | +| `sign` | POST | `api/v1/bundles/{bundleId}/sign` | Подписать бандл | +| `cancelQrCode` | PATCH | `api/v1/bundles/{bundleId}/cancel_qr` | Отменить QR-код | +| `restartWorkflow` | POST | `api/v1/bundles/{bundleId}/restart` | Перезапустить workflow бандла | +| `getPublicLink` | GET | `api/v1/public/documents/public_link/{public_link_id}` | Получить публичную ссылку | +| `deletePublicLink` | DELETE | `api/v1/documents/public_link/{public_link_id}` | Удалить публичную ссылку | +| `removeDoc` | DELETE | `api/v1/documents/bin?parent_id={id}` | Переместить в корзину | +| `recoveryDocument` | PATCH | `api/v1/documents/bin/restore?parent_id={id}` | Восстановить из корзины | +| `copyFolderStructure` | POST | `api/v1/documents/copy_structure` | Копировать структуру папок | + +### `sarexApi` — Gateway/API Sarex + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getUsersWithTransmittalProjectPermissions` | GET | `/gateway/api/v2/users/?...&resource_id={projectId}&permissions=...` | Пользователи с правами в проекте | +| `getDocuments` | GET | `/gateway/api/v1/disks/{id}/documents?...` | Документы диска (с фильтрами/поиском) | +| `filterByAttributes` | GET | `/gateway/api/v1/disks/{diskId}/documents?parent_id={rootDocumentId}&{params}` | Фильтрация документов по атрибутам | +| `getResources` | GET | `/gateway/api/v1/resources` | Список ресурсов | +| `createDocument` | POST | `/gateway/api/v1/documents` | Создать документ/папку/проект | +| `fetchDocumentAncestors` | POST | `/gateway/api/v1/documents/ancestors` | Предки документов | +| `fetchDocumentsBundleVersions` | POST | `/gateway/api/v1/documents/bundle_versions` | Версии бандлов документов | +| `getAttributesByDocumet` | GET | `/gateway/api/v1/documents/{id}/attributes` | Атрибуты документа | +| `updateAttributes` | PUT | `/gateway/api/v1/documents/{id}/attributes` | Обновить атрибуты документа | +| `addAttributes` | POST | `/gateway/eav/api/v0/entity/` | Создать сущность атрибутов (EAV) | +| `getDefaultAttributes` | GET | `/eav/api/v0/schema/?model=document&company_id=...&type_identifier=...` | Схема атрибутов по типу | +| `getAttributes` | GET | `/eav/api/v0/attribute/?company_id={params}` | Атрибуты компании | +| `getAttributesWithParams` | GET | `/eav/api/v0/schema/?model=document&{params}` | Схема атрибутов с параметрами | +| `updateSubscription` | POST | `/gateway/api/v1/subscription/` | Создать/обновить подписку | +| `deleteSubscription` | DELETE | `/gateway/api/v1/documents/{documentId}/subscription/` | Удалить подписку | +| `getActivityLog` | GET | `/gateway/api/v1/system_log/?...` | Журнал активности документа | +| `fetchDocumentByResourceId` | GET | `/gateway/api/v1/resources-rpc/parent-document-by-resource-id/{resourceId}/` | Родительский документ по resource id | +| `getRemovedDocuments` | GET | `/gateway/api/v1/documents/bin?parent_id={id}{params}` | Удалённые документы в папке | +| `getRemovedFilteredDocuments` | GET | `/gateway/api/v1/documents/bin{params}` | Удалённые документы (фильтр) | +| `getBindings` | GET | `/cde/app/v1/bundles/{bundleId}/bindings` | Привязки бандла | +| `completeUpload` | POST | `{uploadUrl}/complete` | Завершение загрузки (по переданному URL) | + +### `sarex` — Локальный сервис данных + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getSettings` | GET | `/api/client/settings/` | Клиентские настройки (кешируется) | +| `getUser` | GET | `/api/core/users/{userId}/` | Пользователь по id | +| `getUsersByCompanyIds` | GET | `/api/core/users/?company={ids}&limit=&offset=&show_inactive=true` | Пользователи компаний | +| `getTargets` | GET | `/api/core/targets/` | Список таргетов | +| `getCompanies` | GET | `/api/core/companies/` | Список компаний | +| `getDepartmentById` | GET | `/api/core/admin/departments?company={companyId}` | Отделы компании | +| `getUsersPositionById` | GET | `/api/core/admin/positions/?company={companyId}` | Должности компании | +| `getByFullUrl` | GET | `{url}` | Запрос по произвольному URL | + +### `processes` — Сервис рабочих процессов (flows) + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getProcesses` | GET | `api/v1/flows/?{query}` | Список процессов (flows) | +| `createReview` | POST | `api/v1/reviews/` | Создать review | +| `deleteReview` | DELETE | `api/v1/reviews/{id}/` | Удалить review | +| `activateReview` | PATCH | `api/v1/reviews/{id}/approve/` | Активировать/утвердить review | +| `createReviewDocuments` | POST | `api/v1/documents/` | Добавить документы в review | + +### `workflows` — Сервис обработки документов + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getWorkflow` | GET | `api/v1/workflows/{workflowId}` | Workflow по id | +| `getWorkflows` | POST | `api/v1/workflows/batch` | Пакетное получение workflow | + +### `workspaces` — Сервис рабочих областей + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getWorkspaces` | GET | `api/v1/workspaces/{uuid}` | Рабочая область по uuid | + +### `remarks` — Сервис замечаний + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `getRemarksTotalCount` | GET | `api/v1/total_count` | Общее число замечаний | + +### `files` — Сервис файлов + +| Ключ | Метод | Путь | Назначение | +| --- | --- | --- | --- | +| `downloadFiles` | GET | `/api/v1/documents/{documentIds}` | Скачать документы по id | +| `downloadFileBundles` | POST | `/api/v1/documents/` | Скачать бандлы (ответ `blob`) | + +## Обработка ошибок + +Коды ответов маппируются в сообщения (`module/api/errors.ts`): `400` — некорректный запрос, `404` — ресурс не найден, `500` (и прочие) — ошибка сервера. Для каждого сервиса задано человекочитаемое имя (напр. `transmittals` → «Сервис передачи документации»), которое подставляется в текст ошибки. По умолчанию у запросов включён показ уведомления об ошибке (`showErrorNotification: true`). diff --git a/apps/workspaces/.env.example b/apps/workspaces/.env.example new file mode 100644 index 0000000..fdb2bb7 --- /dev/null +++ b/apps/workspaces/.env.example @@ -0,0 +1,21 @@ +API_PORT=6666 + +API_ADDRESS=0.0.0.0:6666 + +POSTGRES_ADDRESS=127.0.0.1 +POSTGRES_USER=user +POSTGRES_PASSWORD=password +POSTGRES_DB=workspaces +POSTGRES_PORT=5432 +POSTGRES_EXTERNAL_PORT=5432 +POSTGRES_POLL_SIZE=10 + +ENABLE_SQL_QUERY=1 + +DOCUMENTATION_HOST=https://stage-api.sarex.io/documentation +DOCUMENTATION_LOGGER_FEATURE=1 +DOCUMENTATION_ORIGINATOR=local_ws + +SENTRY_DSN=https://62dbe0a9ee5745eead25f2a705cb35ce@o279218.ingest.sentry.io/6229949 +SENTRY_DEBUG=0 +ENVIRONMENT=local \ No newline at end of file diff --git a/apps/workspaces/CONFIGURATION.md b/apps/workspaces/CONFIGURATION.md new file mode 100644 index 0000000..6b54bcf --- /dev/null +++ b/apps/workspaces/CONFIGURATION.md @@ -0,0 +1,122 @@ +# Конфигурация проекта workspaces-api + +Документ описывает все переменные окружения и способы конфигурирования сервиса. + +## Способы конфигурирования + +Сервис настраивается **только через переменные окружения**. Разбор выполняется в `config/config.go` через библиотеку [`envconfig`](https://github.com/kelseyhightower/envconfig) (функция `config.FromEnv()`). Отдельного конфиг-файла (yaml/toml) у приложения нет. + +Источники переменных по способам запуска: + +| Способ запуска | Откуда берутся переменные | +| --- | --- | +| Локально (docker-compose) | Файл `.env` в корне (`env_file: .env`); поднимает только контейнер Postgres, сам API-сервис в compose закомментирован | +| Локально (бинарник) | Переменные окружения процесса; пример значений — в `.env`, приватные — в `.private.env` (см. `.private.env.example`) | +| Kubernetes (Helm) | `.helm/values.yaml`: блок `envs` (обычные значения) и `secretEnvs` (значения из k8s-секретов) | +| CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна и build-args для сборки образа | + +Порядок запуска в контейнере (`entrypoint.sh`): сначала выполняются миграции (`/migrations migrate`), затем стартует API (`/api`). + +## Переменные приложения (`config.Config`) + +Читаются напрямую по имени. Пустые обязательные значения не приводят к ошибке старта (envconfig не помечает их как required) — но без корректных значений БД/documentation сервис работать не будет. + +| Переменная | Тип | Значение по умолчанию | Назначение | +| --- | --- | --- | --- | +| `POSTGRES_ADDRESS` | string | — | Хост PostgreSQL | +| `POSTGRES_PORT` | string | — | Порт PostgreSQL | +| `POSTGRES_USER` | string | — | Пользователь БД | +| `POSTGRES_PASSWORD` | string | — | Пароль пользователя БД | +| `POSTGRES_DB` | string | — | Имя базы данных | +| `POSTGRES_POOL_SIZE` | int | `0` | Размер пула соединений к БД | +| `API_ADDRESS` | string | — | Адрес прослушивания HTTP-сервера (`host:port`), напр. `0.0.0.0:8000` | +| `DOCUMENTATION_HOST` | string | — | Базовый URL сервиса документации (documentation service) | +| `DOCUMENTATION_ORIGINATOR` | string | — | Идентификатор источника, передаваемый в сервис документации | +| `DOCUMENTATION_LOGGER_FEATURE` | bool | `false` | Включает фичу логирования обращений к сервису документации | +| `SENTRY_DSN` | string | — | DSN для отправки ошибок в Sentry | +| `SENTRY_DEBUG` | bool | `false` | Debug-режим Sentry | +| `ENVIRONMENT` | string | — | Имя окружения (передаётся в Sentry как environment) | +| `BUNDLES_RETRY_COUNT` | int | `3` | Кол-во ретраев клиента bundles (если задано `<= 0`, берётся `3`) | +| `BUNDLES_NJOBS` | int | `3` | Кол-во параллельных задач при работе с bundles (если `<= 0`, берётся `3`) | +| `ENABLE_SQL_QUERY` | bool | `false` | Логировать SQL-запросы (добавляет query-hook в go-pg) | +| `YC-PG-CERTIFICATE` | string | — | Содержимое (PEM) CA-сертификата PostgreSQL; используется при `ENABLE_SSL=1` | +| `ENABLE_SSL` | bool | `false` | Подключаться к PostgreSQL по TLS с проверкой по `YC-PG-CERTIFICATE` | +| `TRACER_USE` | bool | `false` | Включает OpenTelemetry-трейсинг и otel-логгер | +| `TRACER_HOST` | string | `localhost:4317` | Адрес OTLP-коллектора | +| `SERVICE_NAME` | string | `workspaces` | Имя сервиса в трейсах | +| `TRACER_USE_INSECURE` | bool | `true` | Небезопасное (без TLS) подключение к коллектору | +| `TRACER_LOGGER_NAME` | string | `tracer_logger` | Имя otel-логгера | + +> Тип `bool` в envconfig принимает `1`/`0`, `true`/`false`, `t`/`f` и т.п. + +## Переменные инфраструктуры, сборки и вспомогательных утилит + +Не читаются основным кодом приложения, но участвуют в запуске/сборке/деплое. + +| Переменная | Где используется | Назначение | +| --- | --- | --- | +| `POSTGRES_EXTERNAL_PORT` | `docker-compose.yml` | Внешний порт проброса контейнера Postgres | +| `API_PORT` | `.env`, `docker-compose.yml` (закомментированный сервис) | Порт API при локальном запуске в контейнере | +| `FAKE_API_ADDRESS` | `fake_bundle_api/main.go` | Адрес фейкового bundle-API (только для локальной разработки/тестов) | +| `GITLAB_CREDENTIALS` | `api.Dockerfile` (build-arg) | Креды `https://:@gitlab.sarex.io` для доступа к приватным Go-модулям при сборке | +| `CI_COMMIT_SHORT_SHA` | `api.Dockerfile` (build-arg) → `APP_VERSION` | Версия/хэш коммита, зашиваемая в бинарь при сборке (`make api`) | +| `APP_VERSION` | `Makefile` (`make api`) | Версия приложения при сборке | + +## Переменные из Helm-чарта (`.helm/values.yaml`) + +Обычные переменные (`envs`) — переопределяют дефолты по окружениям (`_default`/`stage`/`preprod`/`production`): + +| Переменная | Значение `_default` | Примечание | +| --- | --- | --- | +| `POSTGRES_POOL_SIZE` | `3` | | +| `BUNDLES_RETRY_COUNT` | `5` | | +| `BUNDLES_NJOBS` | `5` | | +| `API_ADDRESS` | `0.0.0.0:8000` | В preprod/production — порт `8080` | +| `NAMESPACE` | `workspaces` | Задаётся в чарте, но **кодом приложения не читается** | +| `ENABLE_SQL_QUERY` | `0` | | +| `ENABLE_SSL` | `1` | | +| `DOCUMENTATION_HOST` | `http://documentations-api-svc.documentations:8000` | Зависит от окружения | +| `DOCUMENTATION_LOGGER_FEATURE` | `0` | | +| `DOCUMENTATION_ORIGINATOR` | `stage_ws` | В prod — `prod_ws` | +| `SENTRY_DSN` | `https://…@o279218.ingest.sentry.io/6229949` | | +| `SENTRY_DEBUG` | `0` | | +| `ENVIRONMENT` | `stage` | В prod — `prod` | +| `TRACER_USE` | `1` | | +| `TRACER_HOST` | `signoz-otel-collector.signoz.svc.cluster.local:4317` | Зависит от окружения | +| `SERVICE_NAME` | `workspaces-api.platform` | Зависит от окружения | +| `TRACER_USE_INSECURE` | `1` | | +| `INTERNAL_PATH` | `/internal/` | Задаётся в чарте, но **кодом приложения не читается** | + +Переменные из секретов (`secretEnvs`, секрет `workspaces-postgresql-secret` / `ya-pg-secret`): + +| Переменная | Ключ секрета | +| --- | --- | +| `POSTGRES_USER` | `username` | +| `POSTGRES_PASSWORD` | `password` | +| `YC-PG-CERTIFICATE` | `ca.crt` | +| `POSTGRES_ADDRESS` | `host` | +| `POSTGRES_PORT` | `port` | +| `POSTGRES_DB` | `database` | + +## JWT-ключи + +RSA-ключи для JWT лежат в `.pub_keys/` и при сборке образа копируются в `/etc/sarex/keys` (см. `api.Dockerfile`). Пути к ключам передаются в функции работы с токенами (`pkg/gotools/auth/jwt.go`) как аргументы, отдельной переменной окружения для пути к ключам в текущем коде нет. + +## Замечания и потенциальные проблемы + +- В файле `.env` переменная названа `POSTGRES_POLL_SIZE` (опечатка), тогда как код читает `POSTGRES_POOL_SIZE`. При локальном запуске из `.env` размер пула не применится и останется `0`. +- Имя переменной `YC-PG-CERTIFICATE` содержит дефисы — envconfig сопоставляет её по точному совпадению тега. +- В `.helm/values.yaml` у `secretEnvs.POSTGRES_PORT` значение `_default.secretName` указано как `a-pg-secret` (похоже на опечатку, ожидается `ya-pg-secret`/`workspaces-postgresql-secret`). +- Переменные `NAMESPACE` и `INTERNAL_PATH` задаются в Helm-чарте, но не используются в коде приложения. + +## Минимальный набор для локального запуска + +Для запуска сервиса локально (Postgres — через docker-compose, API — бинарником) нужно задать: + +- `POSTGRES_ADDRESS`, `POSTGRES_PORT`, `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB` +- `API_ADDRESS` (напр. `0.0.0.0:6666`) +- `DOCUMENTATION_HOST`, `DOCUMENTATION_ORIGINATOR` +- `ENVIRONMENT` (напр. `local`) +- при необходимости — `SENTRY_DSN`, `ENABLE_SQL_QUERY` + +См. пример значений в `.env`.