7.0 KiB
ADDED Requirements
Requirement: Приём журнала изменений
Хаб SHALL принимать от агента журнал изменений задач маршрутом POST /agent/history (агентский токен) с телом
{command_id, changes: [...]}, элемент — {history_id, seq, key, created, author, field_id, field_name, from, from_string, to, to_string}. До записи хаб SHALL проверить форму всей пачки: changes — список объектов;
history_id, key, created, field_name — непустые строки; seq — целое ≥ 0; author, field_id, from,
from_string, to, to_string — строка или null. Нарушение — 422 bad_history с номером элемента и именем поля,
пачка не применяется. Принятая пачка записывается в issue_change в одной транзакции (см. data-model, «Журнал
изменений задач»); ответ — {accepted, duplicates} (записано новых строк, отброшено повторов). Задача элемента может
отсутствовать в зеркале — элемент всё равно записывается.
Scenario: Пачка журнала
- WHEN
POST /agent/historyс тремя элементами, один из них уже есть вissue_change - THEN 200
{accepted: 2, duplicates: 1}
Scenario: Неверный элемент
- WHEN
POST /agent/historyс двумя элементами, у второгоseq = "0" - THEN 422
bad_historyс номером элемента 1 и полемseq; ни один элемент не записан
Scenario: Клиентский токен
- WHEN
POST /agent/historyклиентским токеном - THEN 401
Requirement: Лента изменений
Хаб SHALL отдавать интерфейсам (клиентский токен) ленту событий за период маршрутом GET /changes с параметрами:
since,until— ISO-8601 со смещением илиZ(время без смещения — 422); безuntil— текущее время; безsince—untilминус 24 часа;project— только свои задачи проекта (метка проекта; соседи не входят); неизвестный проект — 404;key— события одной задачи (без ограничения проектом);kinds— через запятую изstatus,description,dates,comment,other, илиall; по умолчанию —status,description,dates,comment;limit— по умолчанию 500, не больше 2000.
События: строки issue_change с at в [since, until] — вид status (поле status), description (поле
description), dates (поля duedate, planned_start, planned_end), other (прочие поля); и комментарии
issue_comment с created_at в [since, until] — вид comment. Ответ — {since, until, truncated, changes: [...]},
элемент — {at, key, summary, status, kind, field, author, from, to, from_value, to_value}: summary и status —
текущие из зеркала (null, если задачи в зеркале нет); from/to — from_string/to_string строки журнала, а если
строка null — from_value/to_value; from_value/to_value — сырые значения строки журнала; у комментария
field = "comment", from = null, to — текст комментария, from_value = to_value = null. Порядок — по at
по убыванию, затем key, history_id, seq (комментарии — comment_id). Событий больше limit — отдаются первые
limit по этому порядку и truncated = true. Неверное время, since позже until, неизвестный вид, limit вне
1..2000 — 422 bad_request с именем параметра.
Scenario: Что закрылось за два часа
- WHEN в 12:00 UTC
GET /changes?project=AWPCA&since=2026-10-22T10:00:00Z&kinds=status; в журнале — X (меткаAWPCA) «В работе» → «Готово» в 11:15 UTC и Y (меткаSTOCKS_DRRK) в 11:20 UTC - THEN одно событие: X,
kind = status,from = "В работе",to = "Готово", автор иatиз журнала
Scenario: Комментарий в ленте
- WHEN у X комментарий с
created = "2026-10-22T13:30:00.000+0300"(10:30 UTC), запрос сsince10:00 UTC - THEN в ленте событие
kind = comment,at = "2026-10-22T10:30:00+00:00",to— текст комментария
Scenario: Прочие поля по запросу
- WHEN в журнале X сменился исполнитель; запрос без
kinds, затем сkinds=all - THEN в первом ответе события нет; во втором —
kind = other,field = "assignee"
Scenario: Сосед проекта не в ленте
- WHEN Z без метки
AWPCAсвязана с задачейAWPCA; в журнале Z сменился статус;GET /changes?project=AWPCA - THEN события Z нет;
GET /changes?key=Zего отдаёт
Scenario: Неверный период
- WHEN
GET /changes?since=вчера - THEN 422
bad_requestс параметромsince
Requirement: Журнал в журнале синхронизаций
GET /sync-runs SHALL отдавать у каждого прогона также history_at (null — журнал по прогону не принят).
Scenario: Прогон с журналом
- WHEN полный прогон завершился
doneс принятым журналом;GET /sync-runs - THEN у прогона
history_at— время приёма; у хвостовогоrefresh {keys}—null
Requirement: История задачи в карточке
GET /issues/{key} SHALL отдавать также changes — все строки issue_change задачи (все виды, включая other) в
формате элемента ленты без summary и status, по at по убыванию (строки с at = NULL — в конце); журнала нет —
changes = [].
Scenario: Задача с историей
- WHEN у X в журнале смена статуса вчера и правка описания сегодня;
GET /issues/X - THEN
changesиз двух элементов: первым — правка описания (kind = description), вторым — смена статуса