# Конфигурация проекта auth-flow-frontend Документ описывает способы конфигурирования микрофронтенда аутентификации `auth-flow-frontend` (React + webpack), а также все переменные сборки, деплоя и рантайма. ## Способы конфигурирования В отличие от бэкенд-сервисов, приложение **не читает `.env` и не использует dotenv**. Это статический фронтенд, собираемый webpack, поэтому конфигурация распределена по трём уровням: 1. **Сборка (build-time).** Переменная `ENDPOINT` определяет окружение. Её значение подставляется в код на этапе сборки через `webpack.DefinePlugin` (`webpack.config.ts`) — заменяет обращения `process.env.ENDPOINT` и `process.env.IS_DEV` на строковые литералы. Выбор режима (`development`/`production`) и флага `isDev` выполняется в `webpack/build.config.ts`. 2. **Установка зависимостей.** Пакеты `@sarex-team/*` тянутся из приватного npm-реестра (`.npmrc` → `nexus.infra.sarex.io`). Для доступа нужен токен `NPM_NEXUS_TOKEN`. 3. **Рантайм (runtime).** Параметры OIDC-провайдера — `authority` и `client_id` — читаются из `localStorage` (`src/config/zitadel.ts`) по ключам `STORAGE.AUTHORITY` и `STORAGE.CLIENT_ID` из `@sarex-team/sdk-js`. Их задаёт хостовое приложение, а не сборка. Источники переменных по способам запуска: | Способ запуска | Откуда берутся переменные | | --- | --- | | Локально (dev) | `npm run dev` → `ENDPOINT=local webpack serve`. Dev-сервер на `https://localhost:9000` | | Локально (build) | `npm run build` → `webpack --config webpack.config.ts` (по умолчанию `ENDPOINT=prod`, см. `build.config.ts`) | | Docker | `Dockerfile`: build-args `ENDPOINT` и `NPM_NEXUS_TOKEN`; сборка dist → отдача через nginx | | Kubernetes (Helm) | `.helm/values.yaml` (чарт `universal-chart`): блок `services.frontend`, `global.env` | | CI/CD (GitLab) | `.gitlab-ci.yml`: `workflow.rules` (ветка/тег → `STAND`, `ENDPOINT`, `CHART_VERSION`), `BUILD_ARGS`, `HELM_SET_ARGS` | ## Переменные сборки (build-time) Подставляются в код на этапе сборки; в рантайме это уже константы. | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `ENDPOINT` | enum | `prod` (в `build.config.ts`, если не задана) | Окружение сборки: `local`/`stage`/`prod`/`preprod`/`contour`. Определяет `mode` (`development` для `local`, иначе `production`) и `isDev` | | `IS_DEV` | bool | — (вычисляется) | `true`, если `ENDPOINT === 'local'`. Включает dev-роуты (`/login`, `/logout`, `/`). Задаётся автоматически через `DefinePlugin`, вручную указывать не нужно | | `NPM_NEXUS_TOKEN` | string | — | Токен авторизации в приватном npm-реестре `@sarex-team` (`.npmrc`). Обязателен для `npm i` | > `mode` по окружениям (`webpack/build.config.ts`): `local` → `development`, `stage`/`prod`/`preprod`/`contour` → `production`. Неизвестное значение `ENDPOINT` приводит к ошибке сборки. ## Переменные рантайма (localStorage) Читаются в браузере во время работы приложения; задаются хостовым приложением, не сборкой. | Ключ | Источник | Назначение | | --- | --- | --- | | `STORAGE.AUTHORITY` | `@sarex-team/sdk-js` | URL issuer'а Zitadel (`authority` OIDC). Обязателен — при отсутствии `src/config/zitadel.ts` бросает `Error("Authority or client ID is not set")` | | `STORAGE.CLIENT_ID` | `@sarex-team/sdk-js` | `client_id` OIDC-клиента. Обязателен (та же проверка) | | `sarex_logout` (`LOGOUT_STORAGE_KEY`) | `src/config/logout.ts` | Состояние логаута между вкладками (`{ logoutAt, owner, reason }`). Снимается только валидным токеном в `setTokensInfo` | | access / refresh / id токены | `storage` из `@sarex-team/sdk-js` | Устанавливаются в `setTokensInfo` (`storage.setAccessToken`/`setRefreshToken`/`setIdentityToken`) после успешного колбэка | ## Конфигурация OIDC (Zitadel) Задаётся в `src/config/zitadel.ts` (`configZitadel: ZitadelConfig`), клиент создаётся через `createZitadelAuth`. | Параметр | Значение | Назначение | | --- | --- | --- | | `authority` | из `localStorage` (`STORAGE.AUTHORITY`) | Issuer Zitadel | | `client_id` | из `localStorage` (`STORAGE.CLIENT_ID`) | Идентификатор клиента | | `response_type` | `code` | Authorization Code Flow | | `scope` | `openid profile email offline_access urn:zitadel:iam:user:metadata` | Запрашиваемые области | | `redirect_uri` | `${window.location.origin}/auth/callback` | URL возврата после логина | | `post_logout_redirect_uri` | `${window.location.origin}/login` | URL после логаута | | `redirectMethod` | `replace` | Замена записи в истории браузера | | `revokeTokensOnSignout` | `false` | Не отзывать токены при выходе | | `automaticSilentRenew` | `false` | Фоновое обновление токенов выключено | | `validateSubOnSilentRenew` | `false` | — | | `silentRequestTimeoutInSeconds` | `100` | Таймаут silent-запроса | ## Роуты приложения Определены в `src/config/urls.ts`, диспетчеризация в `src/App.tsx`. | Роут | Константа | Доступность | Назначение | | --- | --- | --- | --- | | `/auth/callback` | `CALLBACK` | всегда | Обработка OIDC-колбэка (по умолчанию для неизвестных путей) | | `/auth/error` | `ERROR` | всегда | Страница ошибки аутентификации | | `/login` | `LOGIN` | только dev | Dev-страница входа | | `/logout` | `LOGOUT` | только dev | Dev-страница выхода | | `/` | `HOME` | только dev | Dev-навигация | > В production разрешены только `/auth/callback` и `/auth/error` (`ALLOWED_PATHS`); в dev дополнительно `/login`, `/logout`, `/` (`ALLOWED_PATHS_DEV`). Неразрешённый путь заменяется на `/auth/callback` (`history.replaceState`). ## Сборка (webpack) `webpack.config.ts` + `webpack/build.config.ts`. | Параметр | Значение | Примечание | | --- | --- | --- | | `entry` | `src/index.tsx` | Точка входа | | `output.path` | `dist/` | | | `output.filename` | `index.js` | | | `output.publicPath` | `/` (dev) или `/auth/callback/` (prod) | Зависит от `isDev` | | loader | `esbuild-loader`, target `es2015` | Для `.tsx?/.jsx?` | | `devServer` | `https`, `port: 9000`, `hot`, `historyApiFallback`, `open` | Только dev | | plugins | `HtmlWebpackPlugin` (`public/index.html`), `DefinePlugin` (`ENDPOINT`, `IS_DEV`) | | Node-версия для разработки: `v20.0.0` (`.nvmrc`; в `package.json` заявлено `v20.0.0`, реальная база образа — `node:20`). ## Docker `Dockerfile` — двухстадийная сборка. | Стадия | База | Действия | | --- | --- | --- | | build | `cr.yandex/crp3ccidau046kdj8g9q/node:20` | `npm i` (с `NPM_NEXUS_TOKEN`), `npm run build` (с `ENDPOINT`) | | runtime | `cr.yandex/crp3ccidau046kdj8g9q/nginx:latest` | Копирует `/app/dist/` → `/dist/`, `nginx/nginx.conf` → `/etc/nginx/nginx.conf` | Build-args: `ENDPOINT`, `NPM_NEXUS_TOKEN`. ## Nginx `nginx/nginx.conf` — отдача статики и healthcheck. | Локация | Поведение | | --- | --- | | `= /auth/callback/index.js` | `alias /dist/index.js` | | `^~ /auth/callback` | `try_files $uri $uri/ /index.html`; заголовки `Cache-Control: no-store,...`, кеш отключён | | `= /ping` | `200 {"result": "ok"}` (healthcheck) | `listen 80`, `root /dist`, логи в stdout/stderr, `gzip on`. ## Helm-чарт (`.helm/values.yaml`) Деплой через зонтичный чарт `universal-chart` (`oci://cr.yandex/crp3ccidau046kdj8g9q/charts`, версия `0.1.7`; `Chart.yaml` приложения — `auth-flow-frontend` `1.0.0`). Значения задаются с ключами по окружениям (`_default`/`stage`/`preprod`/`production`). | Параметр | Значение | Назначение | | --- | --- | --- | | `global.env` | `stage` (`_default` в файле) | Активное окружение чарта | | `services.frontend.enabled` | `true` | Включение сервиса | | `deployment.name._default` | `auth-flow-frontend` | Имя деплоймента | | `deployment.replicaCount` | `_default: 1`, `production: 2` | Число реплик | | `deployment.port._default` | `80` | Порт контейнера | | `deployment.revisionHistoryLimit._default` | `5` | Хранимые ревизии | | `deployment.resources.requests` | `memory: 128Mi`, `cpu: 100m` | Реквесты ресурсов | | `deployment.probes.liveness/readiness` | `httpGet` `/` : `80` | Пробы | | `image.name._default` | `cr.yandex/crp3ccidau046kdj8g9q/auth-flow-frontend` | Образ | | `image.pullPolicy._default` | `IfNotPresent` | | | `imagePullSecrets.name._default` | `dockerhub` (enabled `false`) | Секрет реестра | | `service` | `ClusterIP`, port/targetPort `80`, portName `http`, имя `auth-flow-frontend-service` | Service | | `envs` | `[]` | Переменные окружения контейнера (пусто) | | `volumes._default` | `[]` | Тома | | `commitSha`/`gitlabUri`/`gitlabJobUrl`/`owner` | заполняются из CI (`owner` по умолчанию `team-abc`) | Метаданные | ## CI (`.gitlab-ci.yml`) Подключает общие шаблоны `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml` ref `apps-business`). Базовые переменные: `SERVICE_NAME=auth-flow-frontend`, `DOCKERFILE_PATH=./Dockerfile`, `CI_TRIGGER_SOURCE=app`. Переключение окружения по `workflow.rules`: | Условие | STAND | ENDPOINT | CHART_VERSION | K8S_HUSTLER_BRANCH | | --- | --- | --- | --- | --- | | `merge_request_event` | — | — | — (`ENABLE_BUILD_IMAGE=false`) | — | | ветка `stage` | `stage` | `stage` | `0.0.1-stage` | `universal-chart-stage` | | тег (`CI_COMMIT_TAG`) | `production` | `prod` | `0.0.1-prod` | `universal-chart-production` | > Правило для ветки `master` → `preprod` присутствует, но **закомментировано**. `NAMESPACE` для всех окружений — `platform`, `RELEASE_NAME`/`CHART_NAME` — `${SERVICE_NAME}`. `BUILD_ARGS` прокидывают `--build-arg ENDPOINT=` и `--build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN}`. `HELM_SET_ARGS` устанавливают `universal-chart.services.frontend.image.name.`, `global.env`, а также `commitSha`, `gitlabUri`, `gitlabJobUrl`, `owner`. ## Замечания и потенциальные проблемы - **Обязательные runtime-параметры.** Если в `localStorage` нет `AUTHORITY` или `CLIENT_ID`, `src/config/zitadel.ts` бросает ошибку при инициализации — приложение не стартует. Эти значения должен положить хостовый сервис до загрузки микрофронтенда. - **Нет `.env`.** Приложение не читает dotenv; `process.env.ENDPOINT`/`IS_DEV` существуют только на этапе сборки (замена через `DefinePlugin`). Значение `ENDPOINT` задаётся только через CLI/`--build-arg`/CI. - **publicPath в prod** — `/auth/callback/`: приложение обслуживается nginx под префиксом `/auth/callback`, что согласовано с `redirect_uri` OIDC. - **`silentRenew` отключён** намеренно (`automaticSilentRenew: false`) — обновление токенов не выполняется в фоне.