Change web-modules по аудиту веба 24.10.2026 (#98). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.7 KiB
8.7 KiB
MODIFIED Requirements
Requirement: Раздача веб-приложения
Хаб SHALL отдавать собранное веб-приложение (спека web-app) из каталога пакета src/sdlc_hub/web/app/, читая файлы
с диска на каждый запрос:
GET /app/assets/<путь>— файл изassets/сборки; путь, который после разрешения выходит заassets/, не существует или содержит нулевой байт, — 404;Content-Typeпо расширению (.js—text/javascript; charset=utf-8,.css—text/css; charset=utf-8,.svg—image/svg+xml,.png—image/png,.ico—image/x-icon,.woff2—font/woff2,.map—application/json, прочее —application/octet-stream);Cache-Control: public, max-age=31536000, immutable;- любой другой
GET /appилиGET /app/…—index.htmlсборки,text/html; charset=utf-8,Cache-Control: no-cache; - если
index.htmlсборки нет — на любойGET /app…503text/html; charset=utf-8с текстом, что приложение не собрано и нужно выполнитьmake webв каталоге sdlc-hub; GET /иGET /links— 302 сLocation: /app/(главная страница приложения — «Обзор»). Сборка приложения не хранится в git; её создаётmake web.
Scenario: Файл сборки
- WHEN в сборке есть
assets/index-abc123.js, запрошенGET /app/assets/index-abc123.js - THEN 200,
Content-Type: text/javascript; charset=utf-8,Cache-Controlсimmutable, тело — содержимое файла
Scenario: Путь приложения
- WHEN запрошен
GET /app/issues/AURORA-1620 - THEN 200, тело —
index.htmlсборки,Cache-Control: no-cache
Scenario: Выход за каталог сборки
- WHEN запрошен
GET /app/assets/../../api.py(в том числе в виде%2e%2e) - THEN 404, содержимое файлов вне
assets/не отдаётся
Scenario: Приложение не собрано
- WHEN каталога сборки нет, запрошен
GET /app/board - THEN 503, тело — HTML с подсказкой
make web
Scenario: Старый адрес доски
- WHEN запрошен
GET /linksилиGET / - THEN 302,
Location: /app/
Scenario: Нулевой байт в пути
- WHEN запрошен
GET /app/assets/%00илиGET /app/assets/a%00.js - THEN 404
not_found, а не 500
Requirement: Маршруты проектов
Хаб SHALL предоставлять под клиентским токеном:
GET /projects→ список проектов поcreated_at, затемlabel; каждый — плоский объект из полей ядра (label,name,created_at) и полей всех модулей (modules, «Поля проекта от модулей»). Модуль jira даётboard_id,board_type,issues_count(задачи зеркала с меткой проекта),jira_synced_at(время завершения последнего полного обновления зеркала, общее для всех проектов;null, если его не было), модуль wiki —wiki_root,wiki_root_title,wiki_pages,wiki_synced_at,wiki_sync_error.POST /projects{label, name, author?, <поля модулей>}→ 201{project, batch_id, batches}: в одной транзакции проект записывается, модули записывают свои поля и ставят свои пакеты;batches— список{module, id}всех поставленных пакетов в порядке модулей;batch_id— пакет первого модуля, вернувшего пакет (у jira — «Новый проект <метка>» из одногоrefreshпо базовой JQL, уже включающей новую метку). Автор пакетов —author(по умолчаниюapi). Неизвестное поле, неверные поля ядра (см.data-model, «Проекты») или модуля — 422 с указанием поля; метка, совпадающая с существующей без учёта регистра, — 409. При ошибке ни проекта, ни пакетов нет.PATCH /projects/{label}{<изменяемые поля модулей>, author?}→ 200{project, batch_ids, batches}: модули правят свои поля и ставят пакеты в одной транзакции;batches— список{module, id}. Неизменяемое поле (метка, название,board_id) — 422 «<поле> после создания не меняется»; неизвестное поле или неверное значение — 422 с указанием поля; проекта нет — 404.
Scenario: Новый проект
- WHEN
POST /projects {label: "STOCKS_DRRK", name: "Запасы ДРРК", board_id: 5120, author: "viewer"}, есть проектAWPCA - THEN 201;
GET /projectsотдаёт два проекта, уSTOCKS_DRRKboard_type = null,wiki_root = null; в очереди пакет автораviewerсrefresh {jql: 'project = AURORA AND labels in ("AWPCA", "STOCKS_DRRK")'}
Scenario: Проект без доски
- WHEN
POST /projects {label: "STOCKS_DRRK", name: "Запасы ДРРК"} - THEN 201,
board_id = null
Scenario: Проект с корнем вики
- WHEN
POST /projects {label: "STOCKS_DRRK", name: "Запасы ДРРК", wiki_root: "DOC-001234"} - THEN 201; в очереди пакет
refreshи пакетwiki_sync {label: "STOCKS_DRRK", root: "DOC-001234"};batch_id— пакетrefresh;batches—[{module: "jira", id: <refresh>}, {module: "wiki", id: <wiki_sync>}]
Scenario: Повтор метки
- WHEN
POST /projects {label: "AWPCA", name: "…"}, проектAWPCAесть - THEN 409, пакет не поставлен
Scenario: Без названия
- WHEN
POST /projects {label: "STOCKS_DRRK", name: " "} - THEN 422 с указанием поля
name
Scenario: Неизвестное поле
- WHEN
POST /projects {label: "X", name: "X", board: 5} - THEN 422 с указанием поля
board, проекта нет
Scenario: Корень вики у существующего проекта
- WHEN
PATCH /projects/AWPCA {wiki_root: "DOC-000777"} - THEN 200,
batch_ids— один пакетwiki_sync,batches—[{module: "wiki", id: <он же>}];GET /projectsотдаётAWPCAсwiki_root = DOC-000777
Scenario: Доску не меняют
- WHEN
PATCH /projects/AWPCA {board_id: 1} - THEN 422 «board_id после создания не меняется», доска прежняя
Scenario: Свежесть Jira в проекте
- WHEN последний полный пакет
refreshзавершён в 11:07,GET /projects - THEN у каждого проекта
jira_synced_at— это время; до первого полного обновления —null
ADDED Requirements
Requirement: Модуль пакета
GET /batches и GET /batches/{id} SHALL отдавать у пакета поле module — имя модуля, которому принадлежит тип первой
команды пакета (по описаниям модулей в реестре); пакет без команд или с типом, которого не знает ни один модуль, —
module = null. Фильтр GET /batches?module=<имя> SHALL отдавать только пакеты модуля; неизвестный модуль — 404.
Scenario: Модуль у пакетов
- WHEN в очереди пакет «Автообновление» (
refresh, авторhub) и пакетwiki_syncпроектаAWPCA;GET /batches - THEN у первого
module = "jira", у второгоmodule = "wiki"
Scenario: Фильтр по модулю
- WHEN
GET /batches?module=wiki&project=AWPCA - THEN только пакеты модуля wiki проекта
AWPCA
Scenario: Неизвестный модуль
- WHEN
GET /batches?module=nope - THEN 404