iac/apps/stamp-verification/CONFIGURATION.md

133 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Конфигурация проекта stamp-verification-frontend
Документ описывает, как конфигурируется и разворачивается модуль **stamp-verification-frontend** — публичная статическая страница проверки штампа (QR) на документе.
## Что это за сервис
`stamp-verification-frontend` — это статический фронтенд (обычный HTML + ванильный JavaScript + `moment.js`), который раздаётся через **nginx**. По QR-коду со штампа на PDF пользователь попадает на страницу с параметрами `?id=<qrId>&page_number=<n>`, страница запрашивает данные документа у backend-сервиса `documentations` и отображает информацию о версии, авторе, дате загрузки, статусе согласования и ссылке на документ в Sarex.
Ключевое отличие от backend-сервисов: **у приложения нет разбора переменных окружения**. Здесь нет `pydantic-settings`, нет `.env`, нет секций конфигурации. Всё «runtime»-поведение либо статично, либо определяется по хосту в браузере (`window.location.host`). Конфигурируется только **сборка и деплой** (Docker, Helm/`universal-chart`, GitLab CI).
## Способы конфигурирования
| Слой | Где задаётся | Что настраивает |
| --- | --- | --- |
| Runtime (браузер) | `static/js/index.js` | Выбор базового URL API по `window.location.host`; параметры запроса берутся из query-строки (`id`, `page_number`, `v`) |
| Веб-сервер | `nginx.conf` | Порт прослушивания `8080`, корень `/dist`, health-check `GET /ping``200 {"result": "ok"}`, gzip, логи в stdout/stderr |
| Образ | `Dockerfile` | Базовый образ `nginx:mainline-alpine-otel`, копирование `static/` и `index.html` в `/dist`, `EXPOSE 8080` |
| Helm | `.helm/values.yaml`, `.helm/Chart.yaml` | Значения чарта-зависимости `universal-chart` (deployment, image, service, imagePullSecrets) |
| CI/CD | `.gitlab-ci.yml` | Выбор окружения по ветке/тегу, имя релиза/чарта, `HELM_SET_ARGS` |
| IaC (kustomize) | `iac/apps/stamp-verification/**` | Namespace, Deployment, Service и оверлеи кластеров (этот репозиторий) |
Отдельного конфиг-файла (yaml/toml/env) приложение не читает.
## Runtime-поведение (`static/js/index.js`)
Скрипт выполняется на `DOMContentLoaded`. Логика:
- читает query-параметры: `id` (идентификатор QR), `page_number`, `v` (пока не используется);
- запрос выполняется только если заданы одновременно `id` и `page_number`;
- выбирает базовый URL API:
| `window.location.host` | Базовый URL API | Окружение |
| --- | --- | --- |
| `stamp-verification.sarex.io` | `api.sarex.io` | prod |
| любой другой (напр. `stamp-verification.stage.sarex.io`) | `stage-api.sarex.io` | stage |
- делает `fetch` `GET https://<apiBaseUrl>/documentations/api/v1/public/qr/{id}/document_info?number_page={page_number}` с `mode: cors`, `credentials: include`, `cache: no-cache`;
- по ответу заполняет поля страницы (название, версия, номер страницы, автор, дата загрузки), блок изменений (changelog), индикаторы актуальности/аннулирования версии, статус согласования и ссылку на документ.
Локаль дат — `ru` (`moment.locale("ru")`), формат отображения даты — `DD.MM.YYYY / HH:mm`.
Полный перечень внешних вызовов см. в `ENDPOINTS.md`, контракт эндпоинта — в `openapi.yaml`.
## nginx (`nginx.conf`)
| Параметр | Значение | Назначение |
| --- | --- | --- |
| `listen` | `8080` | Порт HTTP |
| `root` | `/dist` | Корень статики (туда Dockerfile кладёт `static/` и `index.html`) |
| `location = /ping` | `return 200 '{"result": "ok"}'` | Health-check для k8s-проб/балансировщика |
| `access_log` | `/dev/stdout` | Логи доступа в stdout |
| `error_log` | `stderr warn` | Логи ошибок в stderr |
| `gzip` | `on` | Сжатие ответов |
| `expires` | `off` | Без заголовков кеширования |
## Docker (`Dockerfile`, `docker-compose.yml`)
Образ на базе `nginx:mainline-alpine-otel`. Сборка копирует `nginx.conf` в `/etc/nginx/nginx.conf`, каталог `static` и `index.html` в `/dist`, выставляет права на `/var` и `/run`, объявляет `EXPOSE 8080` и запускает `nginx -g "daemon off;"`. Build-time аргументов нет (`BUILD_ARGS=""`).
`docker-compose.yml` — только для локального прогона (`image: sarex/landing:latest`, публикует порт `8000:8000`; обратите внимание, что nginx внутри слушает `8080` — маппинг в compose оставлен историческим).
## Helm / universal-chart (`.helm/`)
`Chart.yaml` подключает зависимость `universal-chart` (`oci://cr.yandex/crp3ccidau046kdj8g9q/charts`, версия `0.1.7`). Значения задаются в `values.yaml` под ключом `universal-chart` и разбиты по окружениям через суффиксы (`_default`, `stage`, `preprod`, `production`).
| Ключ (`universal-chart.services.frontend.*`) | Значение (`_default`) | Назначение |
| --- | --- | --- |
| `deployment.enabled` | `true` | Создавать Deployment |
| `deployment.name` | `stamp-verification-frontend` | Имя Deployment |
| `deployment.port` | `8080` | Порт контейнера |
| `deployment.replicaCount` | `1` | Число реплик |
| `image.name` | `cr.yandex/crp3ccidau046kdj8g9q/stamp-verification-frontend:latest` | Образ |
| `image.pullPolicy` | `IfNotPresent` | Политика загрузки образа |
| `service.enabled` | `true` | Создавать Service |
| `service.name` | `frontend-service` | Имя Service |
| `service.port` | `8080``production``80`) | Порт сервиса |
| `service.targetPort` | `8080` | Целевой порт |
| `service.type` | `ClusterIP` | Тип сервиса |
| `imagePullSecrets.name` | `dockerhub` | Секрет для доступа к реестру |
`global.env` (`_default`) выбирает активный набор значений по окружению.
## CI/CD (`.gitlab-ci.yml`)
Пайплайн подключает общие шаблоны `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`, ref `apps-business`). Общие переменные: `SERVICE_NAME=stamp-verification-frontend`, `DOCKERFILE_PATH=Dockerfile`, `BUILD_ARGS=""`, `CI_TRIGGER_SOURCE=app`.
Окружение переключается правилами `workflow.rules`:
| Условие | STAND | NAMESPACE | CHART_VERSION | K8S_HUSTLER_BRANCH |
| --- | --- | --- | --- | --- |
| `merge_request_event` | — | — | — | `ENABLE_BUILD_IMAGE="false"` (только проверки, без сборки образа) |
| ветка `stage` | `stage` | `documentations` | `0.0.1-stage` | `universal-chart-stage` |
| ветка `master` | `preprod` | `stamp-verification-preprod` | `0.0.1-preprod` | `universal-chart-preprod` |
| тег (`CI_COMMIT_TAG`) | `production` | `stamp-verification-prod` | `0.0.1-prod` | `universal-chart-production` |
| иначе | `when: never` | | | |
Для каждого деплой-окружения `HELM_SET_ARGS` передаёт: образ (`universal-chart.services.frontend.image.name.<env>=${IMAGE_NAME}`), `universal-chart.global.env=<env>` и метаданные коммита (`commitSha`, `gitlabUri`, `gitlabJobUrl`, `owner`).
## Инфраструктура (kustomize, этот репозиторий)
Каталог `iac/apps/stamp-verification/` содержит kustomize-манифесты (альтернатива/дополнение к Helm-деплою из CI):
- `base/namespace.yaml` — namespace `stamp-verification` с `istio-injection: enabled`;
- `base/deployment.yaml` — Deployment `frontend` (образ `cr.yandex/crp3ccidau046kdj8g9q/stamp-verification-frontend:<sha>`, `imagePullPolicy: IfNotPresent`, `containerPort: 80`, requests `cpu: 25m`/`memory: 100Mi`, `imagePullSecrets: regcred`);
- `base/service.yaml` — Service `frontend-service` (`ClusterIP`, `port: 80``targetPort: 80`);
- `base/kustomization.yaml` — сборка base (namespace + deployment + service);
- `yc-k8s-test/kustomization.yaml` — оверлей кластера (`resources: ../base`, патчи закомментированы);
- `yc-k8s-test/replicas.yaml` — заготовка патча реплик (`replicas: 1`).
## Замечания и потенциальные проблемы
- **Захардкоженный JWT.** В `static/js/index.js` в заголовок `Authorization: Bearer …` вшит истёкший (2023 г.) токен. Публичный эндпоинт `/public/qr/...` не должен требовать пользовательский токен — строку следует удалить. Держать секреты в статике недопустимо.
- **Рассогласование портов.** nginx и Helm/`universal-chart` используют порт **8080**, а kustomize-манифесты в этом репозитории (`base/deployment.yaml`, `base/service.yaml`) — порт **80**. Нужно привести к одному значению (образ слушает 8080), иначе проброс/пробы могут не сходиться.
- **Дублирование деплоя.** Приложение может разворачиваться и через Helm (CI, чарт `universal-chart`), и через kustomize (этот репозиторий). Следует зафиксировать единый источник истины, чтобы образ/порт/namespace не расходились.
- **NAMESPACE для stage.** На ветке `stage` деплой идёт в namespace `documentations` (общий), тогда как preprod/prod — в выделенные `stamp-verification-*`. Это осознанное решение или наследие — стоит проверить.
- **Конфиг только по хосту.** Выбор prod/stage жёстко завязан на строку `stamp-verification.sarex.io`. Любой новый прод-домен потребует правки кода, а не конфигурации.
- **Mock-данные в бандле.** В `index.js` присутствуют объекты `mockData`/`mockChangeLog` — тестовые данные, оставшиеся в продовом бандле. На поведение не влияют (не используются), но их стоит убрать.
## Минимальный набор для локального запуска
Отдельная конфигурация не требуется — приложение статично:
```
# сборка и запуск образа
docker build -t stamp-verification-frontend .
docker run --rm -p 8080:8080 stamp-verification-frontend
# проверка
curl http://localhost:8080/ping # {"result": "ok"}
# страница: http://localhost:8080/?id=<qrId>&page_number=1
```
Для реальных данных нужен доступный backend `documentations` (по умолчанию для не-prod хоста используется `https://stage-api.sarex.io`).