# Конфигурация проекта workflows-engine

`workflows-engine` (внутреннее имя образа — `kubernetes-engine`) — это фоновый сервис-оркестратор (демон без REST API), который вычитывает workflow/задачи из PostgreSQL и запускает их либо как Job'ы в Kubernetes, либо публикует в RabbitMQ (AMQP-исполнитель). Конфигурируется исключительно через переменные окружения.

## Способы конфигурирования

- **Библиотека парсинга:** [`github.com/ilyakaznacheev/cleanenv`](https://github.com/ilyakaznacheev/cleanenv).
- **Точка входа конфигурации:** `config/config.go`, функция `config.New()` вызывает `cleanenv.ReadEnv(cfg)` и заполняет структуру `Config` из переменных окружения процесса.
- **Формат тегов:** каждое поле помечено тегом `env:"ИМЯ"`; значение по умолчанию задаётся тегом `env-default:"..."`. Префикса имён переменных нет.
- **Составная структура `Config`** собирается из встроенных (embedded) структур:
  - `App`, `Log`, `Executor`, `Kubernetes`, `Resources`, `Storages`, `Pooling`, `Workflows`, `Security` — объявлены в `config/config.go`;
  - `pgxconnection.Postgres` — объявлена в `pkg/pgxconnection/postgres.go` (переменные `POSTGRES_*`);
  - `rabbitmq.RabbitMQ` — объявлена в `pkg/rabbitmq/config.go` (переменные `RABBITMQ_*`).
- **Кастомный парсинг:** поле `WORKFLOW_PRIORITY` имеет тип `entity.WorkflowPriority` с методом `SetValue` (`internal/entity/workflow.go`); допустимые значения: `default`, `high`, `low` (регистр не важен).
- **Важно:** часть переменных из `config.env` и Helm-чарта **не читается** структурой конфигурации. Они либо читаются напрямую через `os.Getenv(...)` в `pkg/kube_services/services.go` и **пробрасываются в env запускаемых Job-подов** (а не потребляются самим engine), либо не используются кодом вовсе (см. раздел «Замечания и потенциальные проблемы»).

### Режимы запуска / исполнители

Бинарь один (`cmd/engine`), «режим» определяется набором включённых исполнителей и приоритетом.

| Режим | Как включается | Назначение |
| --- | --- | --- |
| Kubernetes-исполнитель | `ENABLE_KUBERNETES_EXECUTOR=1` (по умолчанию `true`) | Запуск задач как `batchv1.Job` в кластере Kubernetes |
| AMQP-исполнитель | `ENABLE_AMQP_EXECUTOR=1` (по умолчанию `false`) | Публикация задач в RabbitMQ и приём результатов |
| backend (обычный приоритет) | Helm-деплой `backend`, `WORKFLOW_PRIORITY=low` | Обработка обычных workflow |
| backend-high-priority | Helm-деплой `backend-high-priority`, `WORKFLOW_PRIORITY=high` | Обработка высокоприоритетных workflow |

Оба Helm-деплоя разворачивают один и тот же образ; отличаются только значением `WORKFLOW_PRIORITY` (и `MAX_WORKFLOWS_LIMIT`).

### Точки входа (entrypoints)

| Путь | Тип | Описание |
| --- | --- | --- |
| `cmd/engine/main.go` | main-пакет | Единственная точка входа. Поднимает pprof-сервер на `:8081`, читает конфиг, создаёт `engine.New(cfg, logger)` и вызывает `Run()` |
| `internal/apps/engine/engine.go` | приложение | Основная логика: подключение к Postgres, инициализация исполнителей (K8s/AMQP), pooling-контроллер и оркестратор, graceful shutdown по SIGINT |

### Запуск контейнера

- **Dockerfile:** multi-stage сборка на `golang:1.20-buster`, финальный образ `FROM scratch`.
- **CMD/ENTRYPOINT:** `ENTRYPOINT ["/engine"]` — запускается собранный бинарь напрямую, без shell-скрипта/entrypoint-обёртки.
- Внутри процесса дополнительно поднимается HTTP-сервер `net/http/pprof` на порту `:8081` (профилирование). Полноценного REST API нет (см. раздел про `API_ADDRESS`).

## Переменные приложения

### Приложение и логирование (`App`, `Log`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `APP_NAME` | string | `kubernetes-engine` | Имя приложения (в Helm переопределяется на `kubernetes-engine`/`kubernetes-engine-high-priority`) |
| `APP_VERSION` | string | `v1` | Версия приложения |
| `LOG_LEVEL` | string | `info` | Уровень логирования |

### PostgreSQL (`pkg/pgxconnection`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `POSTGRES_ADDRESS` | string | `localhost` | Хост БД |
| `POSTGRES_DB` | string | `processing_db` | Имя базы данных |
| `POSTGRES_USER` | string | `user` | Пользователь БД |
| `POSTGRES_PASSWORD` | string | `password` | Пароль БД |
| `POSTGRES_PORT` | string | `5432` | Порт БД |
| `POSTGRES_POOL_SIZE` | int | `20` | Размер пула соединений |
| `ENABLE_SQL_QUERY` | bool | `true` | Логирование SQL-запросов |
| `YC-PG-CERTIFICATE` | string | `""` | TLS-сертификат CA для подключения к БД (значение сертификата) |
| `POSTGRES_SSL_USE` | bool | `false` | Использовать SSL при подключении к БД |

### RabbitMQ (`pkg/rabbitmq`) — используется только при `ENABLE_AMQP_EXECUTOR=1`

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `RABBITMQ_HOST` | string | — | Хост брокера |
| `RABBITMQ_PORT` | string | — | Порт брокера |
| `RABBITMQ_USER` | string | — | Пользователь |
| `RABBITMQ_PASS` | string | — | Пароль |
| `RABBITMQ_VHOST` | string | — | Виртуальный хост |
| `RABBITMQ_USE_SSL` | bool | — | Использовать TLS |
| `RABBITMQ_CERTIFICATE` | string | — | TLS-сертификат |
| `RABBITMQ_CREATE_EXCHANGE` | string | — | Exchange для отправки задач на запуск |
| `RABBITMQ_CANCEL_EXCHANGE` | string | — | Exchange для отмены задач |
| `RABBITMQ_CREATE_ROUTING_KEY` | string | — | Routing key для запуска |
| `RABBITMQ_CANCEL_TOPIC` | string | — | Topic/ключ отмены |
| `RABBITMQ_COMPLETENESS_EXCHANGE` | string | — | Exchange для получения результатов выполнения |
| `RABBITMQ_COMPLETENESS_TOPIC` | string | — | Topic результатов выполнения |

> Примечание: в `config.env` присутствуют также `RABBITMQ_CREATE_TOPIC` — переменной `RABBITMQ_CREATE_TOPIC` в коде нет (в структуре есть только `CreateRoutingKey`).

### Исполнители и воркеры (`Executor`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `COUNT_RUNNING_WORKERS` | int | — (0) | Кол-во воркеров запуска задач |
| `COUNT_CANCELING_WORKERS` | int | — (0) | Кол-во воркеров отмены задач |
| `COUNT_HANDLE_JOB_WORKERS` | int | — (0) | Кол-во воркеров обработки Job'ов |
| `ENABLE_AMQP_EXECUTOR` | bool | `false` | Включить AMQP-исполнитель (RabbitMQ) |
| `ENABLE_KUBERNETES_EXECUTOR` | bool | `true` | Включить Kubernetes-исполнитель |

### Kubernetes (`Kubernetes`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `JOBS_NAMESPACE` | string | — | Namespace, в котором создаются Job'ы задач |
| `KUBE_CONFIG` | string | — | Путь к kubeconfig. Если **пусто** — используется in-cluster конфигурация; если задан — out-of-cluster |
| `KUBE_CONTEXT` | string | — | Контекст kubeconfig (для out-of-cluster) |
| `KUBE_ADDR` | string | — | Адрес API-сервера кластера (для out-of-cluster; используется с `InsecureSkipTLSVerify`) |

### Ресурсы и планирование подов (`Resources`)

Управляют NodeSelector/Tolerations/requests для запускаемых Job'ов в зависимости от `service_requests` задачи (см. `README.md`).

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `CPU_COUNT` | int | — | CPU requests для `high-resources`/`persistent` |
| `MEMORY_GI` | int | — | Memory (Gi) requests для `high-resources`/`persistent` |
| `CPU_COUNT_LOW_RESOURCES` | int | — | CPU для `low-resources` |
| `MEMORY_GI_LOW_RESOURCES` | int | — | Memory (Gi) для `low-resources` |
| `CPU_COUNT_HIGH_MEM` | int | — | CPU для `super-high-resources` |
| `MEMORY_GI_HIGH_MEM` | int | — | Memory (Gi) для `super-high-resources` |
| `ENABLE_TOLERATION` | bool | — | Включить набор сервисов ресурсов (toleration/nodeselector) |
| `TOLERATION_KEY` | string | — | Ключ toleration/nodeselector для high/low ресурсов |
| `TOLERATION_VALUE` | string | — | Значение toleration/nodeselector для high/low ресурсов |
| `TOLERATION_KEY_HIGH_MEM` | string | — | Ключ toleration для `super-high-resources` |
| `TOLERATION_VALUE_HIGH_MEM` | string | — | Значение toleration для `super-high-resources` |
| `TOLERATION_KEY_PERSISTENT` | string | — | Ключ toleration для `persistent` |
| `TOLERATION_VALUE_PERSISTENT` | string | — | Значение toleration для `persistent` |
| `DJANGO_BASIC_AUTH` | string | — | Базовая авторизация Django (поле присутствует в конфиге, но не используется в бизнес-логике; в под задачи прокидывается хардкод-путь `DJANGO_BASIC_AUTH_PATH`) |
| `DEFAULT_TOLERATION_KEY` | string | — | Ключ toleration по умолчанию для всех подов |
| `DEFAULT_TOLERATION_VALUE` | string | — | Значение toleration по умолчанию |
| `DEFAULT_NODE_SELECTOR_KEY` | string | — | Ключ NodeSelector по умолчанию |
| `DEFAULT_NODE_SELECTOR_VALUE` | string | — | Значение NodeSelector по умолчанию |
| `DEFAULT_IMAGE_PULL_POLICY` | string | `always` | ImagePullPolicy для подов задач |
| `DEFAULT_CPU_REQUESTS` | string | `100m` | CPU requests по умолчанию |
| `DEFAULT_MEMORY_REQUESTS` | string | `64Mi` | Memory requests по умолчанию |

### Хранилища и внешние сервисы (`Storages`)

Флаги `ENABLE_*` включают соответствующий «сервис» (набор env/секретов/volume), который добавляется в под задачи в зависимости от `service_requests`. URL'ы прокидываются в поды mesh/pdm-сервисов.

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `S3_SERVICE_ACCOUNT` | string | — | Путь к service account JSON для S3 (в коде для подов путь по факту хардкодится) |
| `ENABLE_S3_STORAGE` | bool | — | Включить сервис `s3` |
| `ENABLE_S3V2_STORAGE` | bool | — | Включить сервис `s3v2` |
| `ENABLE_PDM_STORAGE` | bool | — | Включить сервис `pdm` |
| `ENABLE_URL_STORAGE` | bool | — | Включить сервис `url` |
| `ENABLE_LOCAL` | bool | — | Включить локальное хранилище |
| `ENABLE_BIM_API_DB` | bool | — | Включить сервис `bim_api_db` |
| `ENABLE_BIM_API_CH` | bool | — | Включить сервис `bim_api_ch` (ClickHouse) |
| `ENABLE_BIM_API_V2_DB` | bool | — | Включить сервисы `bim_api_v2_db` (+ db_2/3/4) |
| `ENABLE_PDM_API_DB` | bool | — | Включить сервис `pdm_api_db` |
| `ENABLE_COMPARISONS_API_DB` | bool | — | Включить сервис `comparison-api-db` |
| `ENABLE_ISSUE_API_DB` | bool | — | Включить сервис `issues-api-db` |
| `ENABLE_RESOURCES_API` | bool | — | Включить сервис `resources-api` |
| `ENABLE_MAIL_GUN` | bool | — | Включить сервис `mailgun` |
| `ENABLE_SMTP` | bool | — | Включить сервис `smtp` |
| `ENABLE_WORKSPACE_API_DB` | bool | — | Включить сервис `workspace_api_db` |
| `ENABLE_CROSS_SECTION_API_DB` | bool | — | Включить сервис `cross-section-api-db` |
| `BIM_API_DEBUG` | bool | — | Флаг debug для BIM API (также пробрасывается в под, см. ниже) |
| `COMPARISONS_API_DEBUG` | string | — | Флаг debug для Comparisons API (также пробрасывается в под) |
| `INTERNAL_PDM_URL` | string | — | Внутренний URL PDM |
| `EXTERNAL_PDM_URL` | string | — | Внешний URL PDM |
| `INTERNAL_FILESTREAM_URL` | string | — | Внутренний URL filestream |
| `EXTERNAL_FILESTREAM_URL` | string | — | Внешний URL filestream |
| `INTERNAL_REMARK_URL` | string | — | Внутренний URL remarks |
| `EXTERNAL_REMARK_URL` | string | — | Внешний URL remarks |
| `DJANGO_HOST` | string | — | URL Django-хоста (ЛК) |
| `INTERNAL_WORKSPACE_URL` | string | — | Внутренний URL workspaces |
| `EXTERNAL_WORKSPACE_URL` | string | — | Внешний URL workspaces |

### Пулинг (`Pooling`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `MAX_WORKFLOWS_LIMIT` | uint64 | — (0) | Лимит одновременно обрабатываемых workflow при выборке |
| `MAX_RUNNING_JOBS` | int64 | `200` | Максимум одновременно выполняющихся Job'ов |

### Workflow (`Workflows`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `DEFAULT_GET_SINCE_LAST_HOURS` | uint64 | `168` | Глубина выборки задач в часах (нужно для FIFO; 168 ч = 7 дней) |
| `WORKFLOW_PRIORITY` | enum (`default`/`high`/`low`) | `default` | Приоритет обрабатываемых workflow (задаёт «роль» инстанса) |

### Безопасность (`Security`)

| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `ENABLE_RUNASUSER` | bool | `false` | Запускать контейнеры задач под фиксированным UID |
| `USER_RUNASUSER` | int64 | `1000` | UID для `runAsUser` |

### Переменные, читаемые через `os.Getenv` и пробрасываемые в под'ы задач

Эти переменные **не входят** в структуру `Config` и **не потребляются** самим engine. Они читаются напрямую в `pkg/kube_services/services.go` и добавляются как env в контейнер запускаемой задачи (Job), когда включён соответствующий `ENABLE_*`-флаг. Тип — всегда строка (передаётся «как есть»).

| Переменная | Куда прокидывается (условие) | Назначение |
| --- | --- | --- |
| `BIM_API_DB` | сервис `bim_api_db` (при `ENABLE_BIM_API_DB`) | Путь к JSON-конфигу БД BIM API |
| `BIM_API_DEBUG` | сервис `bim_api_db` | Флаг debug |
| `BIM_API_CH` | сервис `bim_api_ch` (при `ENABLE_BIM_API_CH`) | Путь к JSON-конфигу ClickHouse |
| `BIM_API_CH_DEBUG` | сервис `bim_api_ch` | Флаг debug |
| `BIM_API_V2_DB` | сервис `bim_api_v2_db` (при `ENABLE_BIM_API_V2_DB`) — в под прокидывается под именем `BIM_API_DB` | Путь к JSON-конфигу БД BIM API v2 |
| `BIM_API_V2_DEBUG` | сервис `bim_api_v2_db` | Флаг debug |
| `BIM_API_V2_DB_2` | сервис `bim_api_v2_db_2` — в под как `BIM_API_DB_2` | Путь к JSON-конфигу 2-й БД BIM v2 |
| `BIM_API_V2_DB_3` | сервис `bim_api_v2_db_3` — в под как `BIM_API_DB_3` | Путь к JSON-конфигу 3-й БД BIM v2 |
| `BIM_API_V2_DB_4` | сервис `bim_api_v2_db_4` — в под как `BIM_API_DB_4` | Путь к JSON-конфигу 4-й БД BIM v2 |
| `COMPARISONS_API_DB` | сервис `comparison-api-db` (при `ENABLE_COMPARISONS_API_DB`) | Путь к JSON-конфигу БД Comparisons |
| `COMPARISONS_API_DEBUG` | сервис `comparison-api-db` | Флаг debug |
| `ISSUE_API_DB` | сервис `issues-api-db` (при `ENABLE_ISSUE_API_DB`) | Путь к JSON-конфигу БД Issues |
| `ISSUE_API_DEBUG` | сервис `issues-api-db` | Флаг debug |
| `RESOURCES_API_INTERNAL_HOST` | сервис `resources-api` (при `ENABLE_RESOURCES_API`) | Внутренний хост Resources API |
| `SMTP` | сервис `smtp` (при `ENABLE_SMTP`) — в под как `SMTP_CONFIG_PATH` | Путь к JSON-конфигу SMTP |
| `PDM_API_DB` | сервис `pdm_api_db` (при `ENABLE_PDM_API_DB`) | Путь к JSON-конфигу БД PDM |
| `PDM_API_DEBUG` | сервис `pdm_api_db` | Флаг debug |
| `WORKSPACE_API_DB` | сервис `workspace_api_db` (при `ENABLE_WORKSPACE_API_DB`) | Путь к JSON-конфигу БД Workspace |
| `WORKSPACE_API_DEBUG` | сервис `workspace_api_db` | Флаг debug |
| `CROSS_SECTION_API_DB` | сервис `cross-section-api-db` (при `ENABLE_CROSS_SECTION_API_DB`) | Путь к JSON-конфигу БД Cross-section |
| `CROSS_SECTION_API_DEBUG` | сервис `cross-section-api-db` | Флаг debug |
| `WORKFLOWS_SENTRY_DSN` | сервис `Default` (всегда) | Sentry DSN для подов задач |
| `WORKFLOWS_SENTRY_DEBUG` | сервис `Default` (всегда) | Флаг debug Sentry |
| `ENVIRONMENT` | сервис `Default` (всегда) | Имя окружения для подов задач |

> Пути `BIM_API_V2_DB_2/3/4`, `MAILGUN`, `SMTP` и т.п. задаются в Helm-чарте (`.helm/values.yaml`) — в `config.env` присутствуют не все из них.

## Переменные инфраструктуры/сборки

| Переменная | Где | Назначение |
| --- | --- | --- |
| `CGO_ENABLED=0`, `GOOS=linux`, `GOARCH=amd64` | Dockerfile (build stage) | Статическая сборка бинаря под Linux/amd64 |
| `CI_COMMIT_SHORT_SHA` | `.gitlab-ci.yml` → build-arg | Прокидывается в сборку образа |
| `SERVICE_NAME=workflows-engine` | `.gitlab-ci.yml` | Имя сервиса/чарта в CI |
| `DOCKERFILE_PATH=Dockerfile` | `.gitlab-ci.yml` | Путь к Dockerfile |
| `BUILD_ARGS` | `.gitlab-ci.yml` | Аргументы сборки образа |
| `CI_TRIGGER_SOURCE=app` | `.gitlab-ci.yml` | Источник триггера пайплайна |
| `IMAGE_NAME`, `CI_COMMIT_SHA`, `CI_PROJECT_URL`, `CI_JOB_URL`, `CI_PROJECT_NAMESPACE` | `.gitlab-ci.yml` → `HELM_SET_ARGS` | Метаданные деплоя, пробрасываются в universal-chart |

Сборка/деплой наследуются из внешних CI-шаблонов проекта `generic/common-ci` (`universal-pipeline.yaml`, `common-security-scan.yaml`). Юнит-тесты: стадия `test`, образ `golang:1.20`, команда `make unit-tests`.

## Переменные из Helm-чарта

Чарт (`.helm/values.yaml`) построен на `universal-chart`; секреты монтируются как env (`secretEnvs`) и как volume'ы. Ниже — маппинг секретных env (общий для `backend` и `backend-high-priority`). Имя секрета зависит от окружения (`_default` / `stage` / `preprod` / `production`).

| Переменная | Секрет (secret_name) | Ключ (secret_key) |
| --- | --- | --- |
| `POSTGRES_ADDRESS` | `ya-pg-secret` (stage: `processing-postgresql-secret`) | `host` |
| `POSTGRES_PORT` | `ya-pg-secret` (stage: `processing-postgresql-secret`) | `port` |
| `POSTGRES_DB` | `ya-pg-secret` (stage: `processing-postgresql-secret`) | `database` |
| `POSTGRES_USER` | `ya-pg-secret` (stage: `processing-postgresql-secret`) | `username` |
| `POSTGRES_PASSWORD` | `ya-pg-secret` (stage: `processing-postgresql-secret`) | `password` |
| `RABBITMQ_USER` | `rabbitmq-secret` | `username` |
| `RABBITMQ_PASS` | `rabbitmq-secret` | `password` |
| `YC-PG-CERTIFICATE` | `yc-pg-certificate` (stage: `processing-postgresql-secret`) | `certificate` (stage: `ca.crt`, preprod/prod: `certificate`) |

Секреты, монтируемые как volume'ы (файлы JSON-конфигов внешних БД и т.п.):

| Volume / секрет | mountPath |
| --- | --- |
| `yc-s3` | `/etc/sarex/yc-s3` |
| `bim-api-db` | `/etc/sarex` |
| `bim-api-v2-db-2` | `/etc/sarex/second-bim-bd` |
| `bim-api-v2-db-3` | `/etc/sarex/third-bim-bd` |
| `bim-api-v2-db-4` | `/etc/sarex/fourth-bim-bd` |
| `comparison-api-db` | `/etc/comparisons` |
| `pdm-api-db` | `/etc/pdm` |
| `ws-api-db` | `/etc/ws` |
| `mailgun-secret` | `/etc/mailgun-secret` |
| `smtp-secret` | `/etc/smtp-secret` |
| `issues-api-db` | `/etc/issues` |
| `cross-section-api-db` | `/etc/cross_section` |
| `tmp-volume` (emptyDir) | `/tmp` |

Прочие значимые переменные окружения задаются в `.helm/values.yaml` секцией `envs` для каждого сервиса (значения зависят от окружения `_default/stage/preprod/production`) — в т.ч. пути к JSON-конфигам (`BIM_API_DB`, `PDM_API_DB`, …), URL'ы сервисов, `POD_NAME=$(K8S_POD_NAME)`, `WORKFLOW_PRIORITY` (`low` для `backend`, `high` для `backend-high-priority`). Также в чарте описан `meshConfig` (Istio) — включён только для production.

## Переменные в CI

Определяются в `workflow.rules` файла `.gitlab-ci.yml` по ветке/тегу:

| Триггер | STAND | NAMESPACE | universal-chart env | CHART_VERSION | K8S_HUSTLER_BRANCH |
| --- | --- | --- | --- | --- | --- |
| ветка `stage` | `stage` | `platform` | `stage` | `0.0.1-stage` | `universal-chart-stage` |
| ветка `master` | `preprod` | `processing-preprod` | `preprod` | `0.0.1-preprod` | `universal-chart-preprod` |
| тег (`CI_COMMIT_TAG`) | `production` | `processing-prod` | `production` | `0.0.1-prod` | `universal-chart-production` |
| Merge Request | — (сборка образа выключена: `ENABLE_BUILD_IMAGE=false`) | — | — | — | — |

`RELEASE_NAME` во всех случаях — `workflows-engine`. Для каждого стенда деплоятся оба сервиса: `backend` и `backend-high-priority`.

## Замечания и потенциальные проблемы

1. **Нет HTTP REST API, но `API_ADDRESS` присутствует.** Переменная `API_ADDRESS=0.0.0.0:8080` есть в `config.env` и в Helm (`envs`), но **не читается ни одной строкой Go-кода**. Реальный HTTP-сервер — только `net/http/pprof` на `:8081` (`cmd/engine/main.go`). В Helm у сервисов `service.enabled: false`, liveness/readiness-пробы выключены. Переменную стоит либо удалить, либо реализовать сервер. По этой причине `openapi.yaml` для сервиса не создаётся.
2. **Дубликаты в `config.env`:**
   - `ENABLE_BIM_API_V2_DB=1` указана дважды (строки 18 и 19);
   - `JOBS_NAMESPACE` задаётся дважды с разными значениями: `processing-stage` и `processing-testing` — побеждает последнее;
   - `POD_NAME` задаётся дважды: `fieldRef(v1:metadata.name)` и `workflows-backend-869584d795-b7p2b` — второе значение это «замороженное» имя конкретного пода, что явно ошибочно для шаблона.
3. **Хардкод локальных путей разработчика в `config.env`:**
   - `S3_SERVICE_ACCOUNT=/Users/khannanov/sarex/yc-s3-service-account.json`;
   - `KUBE_CONFIG=/Users/khannanov/.kube/config`.
   Эти пути специфичны для машины конкретного разработчика и не должны попадать в общий конфиг (в Helm `S3_SERVICE_ACCOUNT` корректно указывает на `/etc/sarex/yc-s3/...`).
4. **Переменные из `config.env`/Helm, которые не читаются кодом `engine` вообще** (кандидаты на удаление либо потребляются исключительно другими компонентами): `API_ADDRESS`, `CONTROL_PLANE_PERIOD`, `ENABLE_GOOGLE_STORAGE`, `GOOGLE_STORAGE_BUCKET`, `GOOGLE_STORAGE_PROJECT`, `ENABLE_SRX_TMP`, `MAX_TASKS_IN_PERIOD`, `ENABLE_PDM_DB`, `POD_NAME`. Ни `Getenv`, ни struct-тега для них нет.
5. **`config.env` частично устарел относительно `config/config.go` и Helm.** Ряд переменных, реально используемых кодом/чартом, в `config.env` отсутствует (`WORKFLOW_PRIORITY`, `DEFAULT_TOLERATION_*`, `DEFAULT_NODE_SELECTOR_*`, `ENABLE_ISSUE_API_DB`, `ENABLE_RESOURCES_API`, `ENABLE_WORKSPACE_API_DB`, `ENABLE_CROSS_SECTION_API_DB`, `RESOURCES_API_INTERNAL_HOST`, `WORKFLOWS_SENTRY_DSN`, пути `*_API_DB` для issues/ws/cross_section и т.д.). Источником истины следует считать `config/config.go` + `.helm/values.yaml`, а не `config.env`.
6. **Расхождение `env-default` и реальных значений.** У ряда флагов (`ENABLE_S3_STORAGE`, `ENABLE_TOLERATION`, `CPU_COUNT`, воркеры и др.) в коде нет `env-default`, поэтому при отсутствии переменной поле останется нулевым (`0`/`false`/`""`) — сервис молча стартует с «пустой» конфигурацией планирования. Значения обязательно должны задаваться через окружение (Helm).
7. **`DJANGO_BASIC_AUTH` / `COMPARISONS_API_DEBUG` / `BIM_API_DEBUG`** объявлены в структуре конфига, но фактически в бизнес-логике engine не задействованы (debug-флаги повторно читаются через `os.Getenv` и прокидываются в поды; `DJANGO_BASIC_AUTH` не используется — в под задачи попадает хардкод-путь `DJANGO_BASIC_AUTH_PATH=/etc/sarex/django-auth.json`).
8. **`RABBITMQ_CREATE_TOPIC`** присутствует в `config.env`, но в конфиге RabbitMQ такого поля нет (используется `RABBITMQ_CREATE_ROUTING_KEY`) — переменная не читается.

## Минимальный набор для локального запуска

Для локального старта достаточно поднять PostgreSQL и указать доступ к нему; исполнители и внешние интеграции можно выключить.

```env
# Логирование
LOG_LEVEL=debug

# PostgreSQL (обязательно — engine сразу подключается к БД)
POSTGRES_ADDRESS=localhost
POSTGRES_PORT=5432
POSTGRES_DB=processing_db
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_POOL_SIZE=5
POSTGRES_SSL_USE=false
ENABLE_SQL_QUERY=true

# Исполнители: выключаем AMQP; для Kubernetes нужен доступ к кластеру
ENABLE_AMQP_EXECUTOR=0
ENABLE_KUBERNETES_EXECUTOR=1
KUBE_CONFIG=/path/to/your/.kube/config   # если пусто — используется in-cluster
KUBE_CONTEXT=your-context
JOBS_NAMESPACE=processing-testing

# Воркеры
COUNT_RUNNING_WORKERS=1
COUNT_CANCELING_WORKERS=1
COUNT_HANDLE_JOB_WORKERS=1

# Пулинг / выборка
MAX_WORKFLOWS_LIMIT=10
MAX_RUNNING_JOBS=10
DEFAULT_GET_SINCE_LAST_HOURS=168
WORKFLOW_PRIORITY=default

# Дефолты планирования подов (иначе будут пустыми)
DEFAULT_IMAGE_PULL_POLICY=IfNotPresent
DEFAULT_CPU_REQUESTS=100m
DEFAULT_MEMORY_REQUESTS=64Mi

# Хранилища/внешние БД можно отключить для минимального запуска
ENABLE_S3_STORAGE=0
ENABLE_S3V2_STORAGE=0
ENABLE_PDM_STORAGE=0
ENABLE_URL_STORAGE=0
ENABLE_LOCAL=0
ENABLE_BIM_API_DB=0
ENABLE_BIM_API_CH=0
ENABLE_BIM_API_V2_DB=0
ENABLE_PDM_API_DB=0
ENABLE_COMPARISONS_API_DB=0
ENABLE_ISSUE_API_DB=0
ENABLE_RESOURCES_API=0
ENABLE_MAIL_GUN=0
ENABLE_SMTP=0
ENABLE_WORKSPACE_API_DB=0
ENABLE_CROSS_SECTION_API_DB=0
ENABLE_TOLERATION=0
```

Запуск: `go run ./cmd/engine`. Если Kubernetes-исполнитель не нужен вовсе — установите `ENABLE_KUBERNETES_EXECUTOR=0` (тогда `KUBE_*`/`JOBS_NAMESPACE` не требуются), но учтите, что без единого включённого исполнителя сервис не будет запускать задачи. Профилирование доступно на `http://localhost:8081/debug/pprof/`.
