14 KiB
ADDED Requirements
Requirement: Корень вики проекта
Модуль wiki SHALL давать проекту поле wiki_root — код корневого документа Eva вида DOC-<цифры> (регистр
приводится к верхнему; ссылка на документ Eva с таким кодом принимается и сводится к коду) или null. Поле
необязательно при создании и изменяемо после (PATCH /projects/{label}). Задание или смена корня SHALL ставить пакет
синхронизации проекта; смена корня SHALL оставлять прежнюю копию до успешной синхронизации нового. Сброс в null
SHALL удалять копию проекта, его страницы, индекс и строки вложений. Модуль SHALL хранить для проекта root_title,
synced_at, pages_count, sync_error.
Scenario: Ссылка вместо кода
- WHEN
PATCH /projects/AWPCA {wiki_root: "https://eva.example.ru/project/Document/doc-001234"} - THEN 200,
wiki_root = DOC-001234, поставленwiki_sync {label: AWPCA, root: DOC-001234}
Scenario: Неверный код
- WHEN
PATCH /projects/AWPCA {wiki_root: "страница про статусы"} - THEN 422 с указанием поля
wiki_root, корень прежний, пакета нет
Scenario: Сброс корня
- WHEN у
AWPCAсинхронизировано 120 страниц,PATCH /projects/AWPCA {wiki_root: null} - THEN каталога
wiki/AWPCA/нет, страниц и вложений проекта в базе нет;GET /projects—wiki_root = null
Requirement: Синхронизация вики
Команда wiki_sync {label, root} SHALL быть командой чтения модуля wiki (без копии базы) в пакете с project = label. Её SHALL ставить: POST /wiki/sync {project}, задание или смена корня, фоновая работа хаба — по каждому
проекту с корнем, если с последней успешной или неудачной синхронизации прошло больше wiki_auto_sync_hours
(настройка модуля, по умолчанию 24; 0 — выключено). Пока у проекта есть пакет wiki_sync не в терминальном статусе,
новый не ставится: POST /wiki/sync отвечает 409 sync_in_progress с batch_id текущего. Смена или сброс корня
SHALL отменять невыданные (queued) пакеты wiki_sync проекта и при новом корне ставить новый; отчёт done по
команде, чей root не равен текущему корню проекта, SHALL отбрасываться без изменения копии и данных
(result.discarded = "корень сменился").
Агент wiki SHALL прислать все страницы поддерева корня (включая корень) пачками POST /agent/wiki/pages {command_id, pages} — каждая страница {code, eva_id, title, parent_code, orderno, url, html, attachments: [{ref, url, name}], links: [{ref, code}]}, где attachments — ссылки и картинки на файлы Eva, links — ссылки на документы Eva, ref —
значение атрибута src/href ровно как в html, url — абсолютный адрес, name — alt/title, текст ссылки или
имя файла; в пачке не больше 50 страниц, — и отчитаться done с result = {root_title, codes, eva_calls}, где
codes — коды всех страниц дерева в порядке обхода. Хаб SHALL при приёме пачки переводить HTML в Markdown вне
транзакции записи и складывать результат во временную стадию команды, не трогая копию. Пачка по
команде не в claimed или не wiki_sync — 409; неверная форма страницы — 422 bad_pages с кодом страницы и полем.
По отчёту done хаб SHALL одной операцией заменить копию проекта (см. «Markdown-копия вики»), страницы, индекс поиска и
вложения и записать synced_at, pages_count, root_title, очистив sync_error. Код из codes без присланной
страницы — команда failed «нет страницы <код>». Отчёт failed или перевод в failed по пределу выдач SHALL записать
sync_error; копия, страницы и вложения остаются прежними. Повторная выдача команды SHALL очищать её стадию. Стадия
очищается при любом терминальном статусе команды.
Scenario: Первая синхронизация
- WHEN у
AWPCAкорень DOC-1 с детьми DOC-2, DOC-3; агент прислал три страницы одной пачкой иdone {root_title: "АРМ КА", codes: [DOC-1, DOC-2, DOC-3]} - THEN в
wiki/AWPCA/триindex.md;GET /projects—wiki_pages = 3,wiki_root_title = АРМ КА,wiki_synced_atзаполнен
Scenario: Неудачная синхронизация не портит копию
- WHEN копия
AWPCAиз 3 страниц, следующая синхронизация завершиласьfailed«Eva: HTTP 503» - THEN копия и поиск прежние;
wiki_sync_error = "Eva: HTTP 503"
Scenario: Потерянная пачка
- WHEN отчёт
doneсcodes: [DOC-1, DOC-2], пачки пришли только для DOC-1 - THEN команда
failed«нет страницы DOC-2», копия прежняя
Scenario: Страница удалена в Eva
- WHEN в прошлой копии были DOC-1, DOC-2, DOC-3, новая синхронизация вернула DOC-1, DOC-3
- THEN каталога DOC-2 нет, поиск его не находит, его вложения удалены
Scenario: Корень исправлен, пока агент не установлен
- WHEN у
AWPCAкорень DOC-12 и пакетwiki_syncвqueued;PATCH /projects/AWPCA {wiki_root: "DOC-21"} - THEN прежний пакет
cancelled, поставленwiki_sync {root: DOC-21}
Scenario: Поздний отчёт по старому корню
- WHEN
wiki_sync {root: DOC-12}выдан агенту, корень сменён на DOC-21, агент отчиталсяdone - THEN копия и страницы
AWPCAне изменились, командаdoneсresult.discarded
Scenario: Повторный запрос синхронизации
- WHEN пакет
wiki_syncпроектаAWPCAвыполняется, вызванPOST /wiki/sync {project: AWPCA} - THEN 409
sync_in_progressсbatch_idтекущего пакета, нового пакета нет
Requirement: Markdown-копия вики
Копия проекта SHALL лежать в <JIRA_HUB_HOME>/wiki/<метка>/ (каталоги 0700): у каждой страницы — каталог
NN_<название> внутри каталога родителя (NN — двузначная позиция среди соседей по orderno, затем по коду; у корня
номера нет; название без символов <>:"/\|?* и управляющих, обрезано до 80 символов; совпадение у соседей —
суффикс _2, _3), в нём index.md: frontmatter code, title, url, synced_at, строка # <title> и текст. В
корне копии — _tree.json, список {code, title, depth, path} в порядке обхода. Копия SHALL собираться рядом
(wiki/.<метка>.new/) и подменять прежнюю переименованием; незавершённую подмену хаб SHALL доводить при старте.
HTML страницы SHALL переводиться в Markdown (заголовки #); ссылка или картинка на файл Eva (по списку attachments агента: тот же хост, путь с
files, file, attachments, attachment, download, media или upload) SHALL заменяться на
[📎 <имя>](attachment:<id>), где id — строка вложения; ссылка на документ Eva с кодом DOC-<цифры> — на
[<текст>](page:<код>); прочие ссылки остаются. Сырой HTML в копию не попадает.
Scenario: Раскладка
- WHEN корень DOC-1 «АРМ КА», дети DOC-3 «Статусы» (
orderno1) и DOC-2 «Роли/права» (orderno2) - THEN
wiki/AWPCA/АРМ КА/index.md,…/01_Статусы/index.md,…/02_Роли_права/index.md;_tree.jsonв порядке DOC-1, DOC-3, DOC-2
Scenario: Картинка на странице
- WHEN в HTML DOC-3
<img src="/files/abc/scheme.png">того же хоста - THEN в
index.md—[📎 scheme.png](attachment:<id>), у вложения<id>state = none, файл не скачан
Requirement: Вложения вики по запросу
POST /wiki/attachments/{id}/fetch SHALL ставить пакет из одной команды чтения wiki_fetch {attachment_id, url} и
переводить вложение в fetching; для fetching — ответ текущим состоянием без нового пакета, для ready — сразу
ready. Агент wiki SHALL скачать файл с токеном Eva, отказаться от файла больше предела хранилища ядра (10 МБ) с
ошибкой «файл больше 10 МБ — откройте в Eva», загрузить файл POST /agent/files и отчитаться done {file, size}. Хаб
SHALL проверить, что файл есть в files/ и размер совпадает, и перевести вложение в ready; иначе команда и вложение
failed. Адрес не на хосте Eva из конфига агента агент SHALL отвергать без запроса (failed «чужой хост»).
Файлы вложений в ready SHALL считаться ссылками для уборки files/. GET /wiki/attachments/{id} отдаёт
{id, name, page_code, url, state, size, error}, GET /wiki/attachments/{id}/content — содержимое (ready) или 409
not_ready.
Scenario: Скачивание картинки
- WHEN вложение 7 в
none,POST /wiki/attachments/7/fetch, агент прислал файл 300 КБ - THEN вложение 7
ready,size = 307200,GET /wiki/attachments/7/content— файл
Scenario: Слишком большой файл
- WHEN агент отчитался
failed«файл больше 10 МБ — откройте в Eva» - THEN вложение
failedс этим текстом;GET …/content— 409not_ready
Scenario: Вложение переживает синхронизацию
- WHEN вложение 7
ready, синхронизация вернула ту же страницу с той же ссылкой - THEN у вложения тот же
id7 иstate = ready, файл вfiles/не убран
Requirement: Маршруты вики
Хаб SHALL предоставлять под клиентским токеном (проект — project=<метка>, неизвестный — 404, без корня — 409
no_root):
GET /wiki/status?project=—{root, root_title, synced_at, pages, error, batch: {id, status} | null};GET /wiki/tree?project=— список{code, title, depth, parent_code, size}в порядке обхода;GET /wiki/pages/{code}?project=—{code, title, path, url, synced_at, markdown, attachments: [{id, name, state, size}]}; страницы нет в копии — 404;GET /wiki/search?project=&q=&limit=(limit1–50, по умолчанию 10) —[{code, title, path, snippet}]по убыванию релевантности; слова запроса ищутся по префиксу, пустой запрос — 422;POST /wiki/sync {project, author?}→ 201{batch_id}(409 — см. «Синхронизация вики»);- маршруты вложений — см. «Вложения вики по запросу».
Под токеном агента wiki — POST /agent/wiki/pages (см. «Синхронизация вики»).
Scenario: Поиск
- WHEN в копии
AWPCAстраница DOC-3 «Статусы» содержит «статус «На согласовании» ставит аналитик»;GET /wiki/search?project=AWPCA&q=согласов - THEN первым — DOC-3 с фрагментом, содержащим «На согласовании»
Scenario: Проект без корня
- WHEN у
sfm_kedrнет корня,GET /wiki/tree?project=sfm_kedr - THEN 409
no_root