## MODIFIED Requirements ### Requirement: Настройки Таблица `setting` SHALL хранить парами ключ–JSON: `base_jql`, `field_ids`, `issue_types`, `priority_map`, `link_types`, `transitions_map`, `pacing`, `board_id`, `tokens` (агентский и клиентский), `settings_version` (увеличивается при любой правке), `backup_keep`, `auto_refresh_minutes`, `relay_dir` (абсолютный путь папки реле или `null`, по умолчанию `null`; относительный путь и не-строка при записи — 422; агенту не передаётся), `closed_statuses` (список имён статусов Jira, считающихся закрытыми, по умолчанию `["Готово", "Снято"]`; не-список при записи — 422; агенту не передаётся; на существующей базе появляется со значением по умолчанию при открытии хаба). Спринты агент читает с доски `board_id`, отдельной настройки имён спринтов нет. Начальные значения SHALL импортироваться из `admin/jira-sync/config.example.json` командой `jira-hub init`; пароль и логин Jira в настройках MUST NOT присутствовать. `issue_types` — объект `{task, epic, bug}`, у каждого `{name, id}` (`id` может быть `null`); `init` берёт их из ключей конфига `issue_type_<тип>` и `issue_type_<тип>_id`; `bug` попадает в `issue_types`, только если в конфиге есть хотя бы один из ключей `issue_type_bug`, `issue_type_bug_id` (`task` и `epic` — как раньше, всегда). #### Scenario: Правка настроек поднимает версию - **WHEN** через API изменён `pacing` - **THEN** `settings_version` увеличен, следующий `claim` отдаёт агенту новую версию #### Scenario: Конфиг без ключей ошибки - **WHEN** `jira-hub init --config` с `issue_type_task`, `issue_type_epic`, без `issue_type_bug` - **THEN** `issue_types` содержит `task` и `epic`, `bug` нет; постановка `ensure_issue` с `issue_type = bug` — 422 #### Scenario: Неверный relay_dir - **WHEN** `PUT /settings` с `relay_dir = "rshb/jira-bridge"` - **THEN** 422, значение не записано, `settings_version` не изменился #### Scenario: Закрытые статусы по умолчанию - **WHEN** хаб открыл базу, в которой нет ключа `closed_statuses` - **THEN** `GET /settings` отдаёт `closed_statuses = ["Готово", "Снято"]`; `claim` агенту этого ключа не передаёт