openspec: change nats-env-config — subject'ы и JWT NATS по окружению из OpenBao
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d49fa63e55
commit
1579295961
2
openspec/changes/nats-env-config/.openspec.yaml
Normal file
2
openspec/changes/nats-env-config/.openspec.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-10-12
|
||||
20
openspec/changes/nats-env-config/design.md
Normal file
20
openspec/changes/nats-env-config/design.md
Normal file
@ -0,0 +1,20 @@
|
||||
## Context
|
||||
|
||||
Дизайн сквозной: `../docs/openspec/changes/nats-env-config/design.md` (решения 1–7, R-1…R-6). Здесь — только то, что
|
||||
специфично для `scan-gateway`.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. Сервис подписан на `image_request` (queue group `scan-gateway`), публикует ack и результат в `result`; в `/healthcheck.subjects` — `image_request`, `result`.
|
||||
2. Проверяются все три subject'а, включая неиспользуемые сервисом (docs design, решение 1 и R-3).
|
||||
3. Выбор subject'а и подписки получают имена из `settings.OPENBAO.NATS`; константы `contract/subjects.py` остаются
|
||||
умолчаниями полей настроек. Форма передачи (аргумент, объект subject'ов) — в плане.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
См. docs design: разъехавшиеся настройки — тишина на шине; JWT без прав на заданные subject'ы — ошибка прав NATS в логе.
|
||||
|
||||
## Decisions made without discussion
|
||||
|
||||
Решения без обсуждения ведутся в сквозном `../docs/openspec/changes/nats-env-config/design.md` (R-1…R-6); решения,
|
||||
принятые при исполнении в этом репозитории, дописываются сюда с маркером `R-n` сквозной нумерации.
|
||||
40
openspec/changes/nats-env-config/proposal.md
Normal file
40
openspec/changes/nats-env-config/proposal.md
Normal file
@ -0,0 +1,40 @@
|
||||
## Why
|
||||
|
||||
Прод и тест будут работать с разными наборами subject'ов NATS и разными JWT; платформа передаёт в под только
|
||||
`OPENBAO__*`. Сейчас subject'ы — константы `api/src/contract/subjects.py`. Решение владельца 12.10.2026: subject'ы и
|
||||
JWT задаются по окружению секретами группы `OPENBAO__NATS__`, как в `RSHB/armka_file_worker`. Сквозной change —
|
||||
`../docs/openspec/changes/nats-env-config` (RSHB/arm-ka-docs#80); здесь — его часть для `scan-gateway` (RSHB/arm-scan-gateway#32).
|
||||
|
||||
Срез: вне плана срезов `09-delivery-plan.md` — подготовка к контуру. Таблицы DBML v5.17 не затрагиваются
|
||||
(`recognition_job.request_subject` по-прежнему хранит фактический subject публикации).
|
||||
|
||||
## What Changes
|
||||
|
||||
- `NATSSettings`: `NATS_TABULAR_REQUEST_SUBJECT` (`files.tabular_uploaded`), `NATS_IMAGE_REQUEST_SUBJECT`
|
||||
(`files.img_uploaded`), `NATS_RESULT_SUBJECT` (`files.tabular_parsed`); проверка всех трёх при старте (непустые, без
|
||||
пробелов, `*`, `>` и пустых токенов, попарно различны).
|
||||
- `NATS_JWT`, `NATS_SEED` — `SecretStr`; `Settings(hide_input_in_errors=True)`.
|
||||
- Сервис подписан на `image_request` (queue group `scan-gateway`), публикует ack и результат в `result` — по настройкам; константы `contract/subjects.py` — только умолчания.
|
||||
- Лог при старте и `/healthcheck.subjects` (`image_request`, `result`), независимо от состояния NATS.
|
||||
- Тесты интеграционные (`tests/integration/`) задают собственные subject'ы через настройки (OQ-83).
|
||||
- `.env.example`, README.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- `schema_version` контракта и копии схем не меняются (кроме побайтной синхронизации `description` из docs, если она
|
||||
изменится).
|
||||
- Queue group'ы — константы; механизм nkeys/JWT не меняется.
|
||||
- Пароли MinIO/SMB в `SecretStr` не переводятся.
|
||||
- Настройка через `OPENBAO__APP__*` не вводится.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
### Modified Capabilities
|
||||
- `image-recognition-gateway`: subject'ы обмена и учётные данные NATS — настройки окружения; `/healthcheck.subjects`.
|
||||
|
||||
## Impact
|
||||
|
||||
Файлы: `api/src/core/config.py`, `api/src/contract/subjects.py`, `api/src/core/nats.py`, `api/src/gateway/`, `api/src/core/health.py`, `api/src/app.py` (лог старта), тесты (`tests/unit/test_config*.py`, `tests/unit/test_nats.py`, `tests/unit/test_app.py`, `tests/integration/`), `api/.env.example`, README. Выкат обратно совместим (умолчания — текущие имена); набор окружения задаётся одинаково всем трём
|
||||
сервисам.
|
||||
@ -0,0 +1,42 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Subject'ы и учётные данные NATS из настроек окружения
|
||||
Сервис SHALL брать subject'ы обмена из `OPENBAO__NATS__NATS_TABULAR_REQUEST_SUBJECT`, `NATS_IMAGE_REQUEST_SUBJECT`,
|
||||
`NATS_RESULT_SUBJECT` (умолчания `files.tabular_uploaded`, `files.img_uploaded`, `files.tabular_parsed`): подписан на `image_request` (queue group `scan-gateway`), публикует ack и результат в `result`.
|
||||
При старте SHALL проверяться все три имени (непустое, без пробельных символов, без `*` и `>`, без пустых токенов,
|
||||
попарно различны); при нарушении приложение MUST NOT стартовать. Значения `NATS_JWT` и `NATS_SEED` MUST NOT попадать в
|
||||
логи, `repr` настроек и тексты ошибок валидации. Используемые subject'ы SHALL писаться в лог при старте и отдаваться в
|
||||
`/healthcheck` объектом `subjects` с ключами `image_request`, `result` при любом значении `nats` (`ok | down | off`).
|
||||
|
||||
#### Scenario: Умолчания
|
||||
- **WHEN** приложение стартует без ключей `OPENBAO__NATS__NATS_*_SUBJECT`
|
||||
- **THEN** `/healthcheck.subjects` содержит имена `files.*` по умолчанию, обмен идёт по ним
|
||||
|
||||
#### Scenario: Subject'ы окружения
|
||||
- **WHEN** заданы `OPENBAO__NATS__NATS_TABULAR_REQUEST_SUBJECT=test.files.tabular_uploaded`,
|
||||
`OPENBAO__NATS__NATS_IMAGE_REQUEST_SUBJECT=test.files.img_uploaded`,
|
||||
`OPENBAO__NATS__NATS_RESULT_SUBJECT=test.files.tabular_parsed`
|
||||
- **THEN** подписки и публикации идут только по этим subject'ам, `/healthcheck.subjects` их показывает
|
||||
|
||||
#### Scenario: Недопустимый subject
|
||||
- **WHEN** `OPENBAO__NATS__NATS_RESULT_SUBJECT` совпадает с subject'ом запроса или содержит `>`
|
||||
- **THEN** приложение не стартует, ошибка называет ключ
|
||||
|
||||
#### Scenario: JWT не раскрывается
|
||||
- **WHEN** заданы `NATS_JWT` и `NATS_SEED`, а валидация настроек падает на другом поле
|
||||
- **THEN** текст ошибки и лог не содержат значений JWT и seed; `repr` настроек показывает их скрытыми
|
||||
|
||||
#### Scenario: Тесты на своих subject'ах
|
||||
- **WHEN** тесты интеграционные (`tests/integration/`) запускаются при работающих контейнерах стенда на том же NATS
|
||||
- **THEN** тесты используют уникальные subject'ы из настроек и не получают и не забирают сообщения стенда
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Соединение с NATS без JetStream
|
||||
При пустых `NATS_SEED`/`NATS_JWT` сервис SHALL подключаться без учётных данных, иначе — с nkeys/JWT из `OPENBAO__NATS__NATS_SEED`/`NATS_JWT` (значения — секреты); MUST NOT требовать
|
||||
stream'ов и consumer'ов JetStream; при разрыве SHALL переподключаться и восстанавливать подписку; `/healthcheck.nats`
|
||||
SHALL отражать состояние.
|
||||
|
||||
#### Scenario: NATS перезапущен
|
||||
- **WHEN** контейнер NATS перезапущен во время работы сервиса
|
||||
- **THEN** в течение 20 с после старта NATS подписка восстановлена, `nats = ok`
|
||||
18
openspec/changes/nats-env-config/tasks.md
Normal file
18
openspec/changes/nats-env-config/tasks.md
Normal file
@ -0,0 +1,18 @@
|
||||
## 1. Тесты
|
||||
|
||||
- [ ] 1.1 Unit: умолчания subject'ов, чтение `OPENBAO__NATS__NATS_*_SUBJECT`, отказ на `*`/`>`/пробеле/пустом токене и
|
||||
совпадающих именах; `SecretStr` для `NATS_JWT`/`NATS_SEED`, отсутствие значений в ошибке валидации и `repr`
|
||||
- [ ] 1.2 Unit: `/healthcheck.subjects` (`image_request`, `result`) при `nats = ok | down | off`; лог старта с subject'ами
|
||||
- [ ] 1.3 Тесты интеграционные (`tests/integration/`) — уникальные subject'ы через настройки
|
||||
|
||||
## 2. Реализация
|
||||
|
||||
- [ ] 2.1 `core/config.py`: поля и валидация `NATSSettings`, `SecretStr`, `hide_input_in_errors=True`
|
||||
- [ ] 2.2 Колбэки nkeys — `get_secret_value()`
|
||||
- [ ] 2.3 Подписка и публикация по настройкам; константы `contract/subjects.py` — умолчания
|
||||
- [ ] 2.4 `/healthcheck.subjects`, лог при старте
|
||||
|
||||
## 3. Документы
|
||||
|
||||
- [ ] 3.1 `api/.env.example`, README (переменные NATS, `/healthcheck`)
|
||||
- [ ] 3.2 `make check-full` зелёный
|
||||
Loading…
x
Reference in New Issue
Block a user