## ADDED Requirements ### Requirement: Реле через общую папку `jira-hub serve` SHALL запускать поток реле вместе с HTTP-сервером. Пока настройка `relay_dir` пуста (`null`), реле бездействует; настройку оно SHALL перечитывать не реже раза в 5 с, включение и выключение не требуют перезапуска. Если каталог `relay_dir` существует, реле SHALL создать в нём подкаталоги `req/`, `resp/`, `work/`; если не существует — записать одно предупреждение в лог и проверять снова. Обмен: - запрос агента — файл `req/.json`: `{id, method, path, body, authorization, deadline}`, где `deadline` — момент UTC (ISO 8601), после которого ответ не нужен; файлы, имя которых начинается с точки, реле MUST NOT читать; - реле SHALL брать запрос переименованием в `work/.json` и обрабатывать каждый взятый запрос в отдельном потоке; - запрос с истёкшим `deadline` SHALL выбрасываться без ответа; `POST /agent/claim` SHALL пересылаться, только если до `deadline` осталось не меньше 35 с, иначе выбрасываться без ответа; - остальные запросы реле SHALL пересылать в свой HTTP на `127.0.0.1:` тем же методом, путём и телом, с заголовком `Authorization` из файла, и записывать ответ `resp/.json` = `{id, status, body}` (тело — строка ответа HTTP) через временный файл с именем на точку и переименование; затем удалять `work/.json`; - если соединение с `127.0.0.1:` не удалось, ответ SHALL иметь `status = 502` и текст ошибки в `body`; - нечитаемый JSON запроса SHALL перечитываться до 2 с, затем запрос выбрасывается с записью в лог. При старте реле SHALL удалить файлы из `work/` с записью в лог. Раз в минуту реле SHALL удалять ответы в `resp/` старше 10 мин, запросы в `req/` с `deadline` старше 60 с и файлы с именем на точку старше 10 мин. На каждый обработанный запрос реле SHALL писать в лог хаба строку `relay <секунды>`. HTTP API, обработчики и проверка токенов при этом не меняются. #### Scenario: Запрос через папку - **WHEN** в `req/` появился `a1.json` с `GET /agent/settings`, агентским токеном и `deadline` через 60 с - **THEN** в `resp/` появляется `a1.json` со `status = 200` и телом настроек; `work/a1.json` удалён #### Scenario: Чужой токен через папку - **WHEN** в файле запроса `GET /issues` с агентским токеном - **THEN** ответ со `status = 401`, как по HTTP #### Scenario: Просроченный claim - **WHEN** реле взяло `POST /agent/claim`, до `deadline` которого осталось 20 с - **THEN** запрос выброшен без ответа и без обращения к хабу; команда в очереди осталась `queued` #### Scenario: Долгий claim не задерживает другие запросы - **WHEN** реле пересылает `claim`, который ждёт команду 30 с, и в это время в `req/` появляется `GET /agent/settings` - **THEN** ответ на `settings` пишется, не дожидаясь `claim` #### Scenario: Папка не подключена - **WHEN** `relay_dir` задан, но каталога нет; через минуту каталог появился - **THEN** в логе одно предупреждение; после появления каталога реле создаёт подкаталоги и обрабатывает запросы