154 lines
21 KiB
Markdown
154 lines
21 KiB
Markdown
# Feature Specification: Clean Release Compliance Subsystem Redesign
|
||
|
||
**Feature Branch**: `025-clean-release-compliance`
|
||
**Created**: 2026-03-09
|
||
**Status**: Draft
|
||
**Input**: User description: "Редизайн текущего clean release TUI-checker в нормальную API/CLI-first release/compliance subsystem с разделением domain/application/infrastructure/interfaces, immutable snapshots, append-only compliance evidence, approval/publication flow, thin TUI client, REST API и интеграцией с TaskManager."
|
||
|
||
## User Scenarios & Testing *(mandatory)*
|
||
|
||
### User Story 1 - Headless candidate and manifest lifecycle (Priority: P1)
|
||
|
||
Как release-менеджер или CI pipeline, я хочу регистрировать релиз-кандидат, импортировать артефакты и строить manifest без TUI, чтобы вход в release workflow был воспроизводимым в автоматизированном или headless сценарии.
|
||
|
||
**Why this priority**: Это базовая ценность редизайна. Пока жизненный цикл кандидата зависит от TUI, release flow не годится для автоматизации и надёжного enterprise use.
|
||
|
||
**Independent Test**: Можно создать кандидата, импортировать набор артефактов, построить manifest и запросить overview только через CLI или HTTP API, не используя интерактивный интерфейс.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** у оператора есть описание релиз-кандидата и набор артефактов, **When** он выполняет headless workflow регистрации, импорта и построения manifest, **Then** система сохраняет кандидата и immutable snapshot manifest без участия TUI.
|
||
2. **Given** manifest успешно построен, **When** оператор запрашивает candidate overview через CLI или API, **Then** он получает актуальный lifecycle state и идентификатор latest manifest.
|
||
3. **Given** pipeline подготавливает следующий этап release workflow, **When** он использует headless candidate and manifest operations, **Then** ему не требуется интерактивный интерфейс для продолжения release process.
|
||
|
||
---
|
||
|
||
### User Story 2 - Trusted and immutable compliance evidence (Priority: P1)
|
||
|
||
Как сотрудник комплаенса или аудита, я хочу, чтобы policy, registry, manifest, run, violations и report были отделены друг от друга и сохранялись как доверенные или append-only сущности, чтобы итог выпуска был доказуемым и не зависел от UI-состояния или случайных env/json подмен.
|
||
|
||
**Why this priority**: Главная архитектурная проблема текущего решения - смешение trust boundaries и UI logic с бизнес-решениями. Без исправления этого нельзя считать результат compliance надёжным.
|
||
|
||
**Independent Test**: Можно зафиксировать policy snapshot и registry snapshot, выполнить run, затем проверить, что manifest/report/violations не переписывались и что итоговый статус выводится только из сохранённого evidence.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** активная policy получена из доверенного policy store, **When** запускается compliance, **Then** run использует snapshot policy и snapshot registry, а не значения из UI или временных env-переменных.
|
||
2. **Given** для кандидата уже создан manifest, **When** входные данные кандидата меняются, **Then** система создаёт новый version manifest вместо изменения существующего snapshot.
|
||
3. **Given** run завершён, **When** оператор запрашивает историю проверки, **Then** старые run, violations и reports остаются доступными и не удаляются в real mode.
|
||
|
||
---
|
||
|
||
### User Story 3 - Controlled approval and publication gate (Priority: P2)
|
||
|
||
Как владелец релиза, я хочу выполнять approve, publish и revoke только после валидного compliance результата, чтобы состояние выпуска было формально управляемым и не зависело от ручных договорённостей.
|
||
|
||
**Why this priority**: Проверка compliance имеет смысл только тогда, когда она реально управляет дальнейшими переходами release lifecycle.
|
||
|
||
**Independent Test**: Можно попытаться утвердить или опубликовать кандидата в запрещённом состоянии и убедиться, что система блокирует переход; затем пройти валидный путь `CHECK_PASSED -> APPROVED -> PUBLISHED`.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** кандидат имеет последний report со статусом `PASSED`, **When** уполномоченный оператор выполняет approve, **Then** система фиксирует approval decision и переводит кандидата в состояние `APPROVED`.
|
||
2. **Given** кандидат не имеет успешного compliance report или latest approval decision имеет значение `REJECTED`, **When** оператор пытается выполнить approve или publish вне допустимого правила, **Then** система отклоняет действие и сообщает причину блокировки.
|
||
3. **Given** кандидат опубликован в целевой канал, **When** требуется отзыв выпуска, **Then** система создаёт publication revocation record без удаления исходной истории публикации.
|
||
|
||
---
|
||
|
||
### User Story 4 - Thin operational interfaces (Priority: P3)
|
||
|
||
Как инженер сопровождения, я хочу использовать TUI и другие интерфейсы только как клиенты чтения и запуска операций, чтобы интерфейсы не содержали скрытой бизнес-логики, не подменяли policy и не создавали визуальные fake-runs.
|
||
|
||
**Why this priority**: Тонкие интерфейсы упрощают сопровождение, делают поведение одинаковым между CLI, API, TUI и будущим Web UI, а также уменьшают риск расхождения логики.
|
||
|
||
**Independent Test**: Можно открыть TUI, выполнить build manifest, run compliance, approve и publish, а затем проверить, что все операции и их последствия совпадают с CLI/API сценариями и не зависят от внутреннего UI state.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** оператор открывает TUI, **When** он запускает build manifest или compliance, **Then** TUI вызывает application services и только отображает актуальные DTO/статусы.
|
||
2. **Given** система работает в demo mode, **When** оператор запускает demo workflow, **Then** demo данные и demo history остаются полностью изолированными от real mode.
|
||
3. **Given** оператор работает в headless окружении без TTY, **When** он пытается использовать функциональность release lifecycle, **Then** система направляет его в CLI/API путь, а не переводит TUI в скрытый псевдо-headless режим.
|
||
|
||
### Edge Cases
|
||
|
||
- Что происходит, если артефакт имеет расхождение между `declared_category` и `detected_category`?
|
||
- Что происходит, если кандидат изменился после построения manifest, но до запуска compliance?
|
||
- Как система различает business blocked, invalid input и system error при возврате статуса и exit code?
|
||
- Что происходит, если policy store недоступен в момент запроса compliance?
|
||
- Как обрабатывается повторный approve или повторный publish для уже терминально обработанного кандидата?
|
||
- Что происходит, если run был отменён или task crashed после старта, но до генерации report?
|
||
- Как система предотвращает пересечение demo namespace и real namespace в storage и audit history?
|
||
|
||
## Requirements *(mandatory)*
|
||
|
||
### Functional Requirements
|
||
|
||
- **FR-001**: Система MUST предоставлять программно управляемый release lifecycle, доступный без TUI через CLI и HTTP API.
|
||
- **FR-002**: Система MUST поддерживать отдельную сущность release candidate с идентификатором, версией, ссылкой на source snapshot, provenance и статусом lifecycle.
|
||
- **FR-003**: Система MUST поддерживать импорт и хранение candidate artifacts с checksum, размером, declared category и detected category.
|
||
- **FR-004**: Система MUST различать declared category и detected category и фиксировать факт их расхождения как часть compliance evidence.
|
||
- **FR-005**: Система MUST строить distribution manifest как отдельный immutable snapshot с собственным идентификатором, version, digest и полным содержимым.
|
||
- **FR-006**: Если состав кандидата изменился после построения manifest, система MUST создавать новый manifest version вместо изменения существующего snapshot.
|
||
- **FR-007**: Система MUST получать policy только из доверенного policy store и сохранять используемую policy как immutable policy snapshot.
|
||
- **FR-008**: Система MUST получать source registry только из доверенного registry source и сохранять используемый registry как immutable snapshot.
|
||
- **FR-009**: Ни один интерфейс, пользовательский ввод или env-переменная MUST NOT определять содержимое policy snapshot, registry snapshot, итоговый report status или audit history.
|
||
- **FR-010**: Система MUST создавать отдельную сущность compliance run, связанную с candidate, manifest, policy snapshot и registry snapshot.
|
||
- **FR-011**: Compliance run MUST сохранять append-only stage execution records, violations и итоговый report.
|
||
- **FR-012**: Система MUST поддерживать статусы выполнения run не менее чем `PENDING`, `RUNNING`, `SUCCEEDED`, `FAILED`, `CANCELLED`.
|
||
- **FR-013**: Система MUST поддерживать итоговые статусы compliance не менее чем `PASSED`, `BLOCKED`, `ERROR`.
|
||
- **FR-014**: Система MUST различать outcome types `PASSED`, `BLOCKED`, `ERROR_INVALID_INPUT`, `ERROR_SYSTEM` и делать их однозначно наблюдаемыми через CLI/API.
|
||
- **FR-015**: Compliance pipeline MUST состоять из независимых стадий с отдельным stage result, decision, details и violations.
|
||
- **FR-016**: Система MUST позволять расширять compliance pipeline новыми стадиями без переписывания интерфейсов запуска и чтения run.
|
||
- **FR-017**: Release candidate lifecycle MUST поддерживать разрешённые переходы `DRAFT -> PREPARED -> MANIFEST_BUILT -> CHECK_PENDING -> CHECK_RUNNING -> CHECK_PASSED|CHECK_BLOCKED|CHECK_ERROR -> APPROVED -> PUBLISHED -> REVOKED`.
|
||
- **FR-018**: Система MUST блокировать `APPROVED` без успешного compliance result и MUST блокировать `PUBLISHED` без approval.
|
||
- **FR-019**: Система MUST сохранять отдельный approval decision с actor, временем, комментарием и ссылкой на report.
|
||
- **FR-020**: Система MUST трактовать approval и reject как immutable decisions, где latest decision governs publication gate; `REJECTED` блокирует публикацию, но не меняет compliance evidence и не переписывает lifecycle state кандидата.
|
||
- **FR-021**: Система MUST сохранять отдельный publication record с channel, actor, временем, ref и статусом, а revoke MUST оформляться как отдельное действие без удаления исходной публикации.
|
||
- **FR-022**: Каждое long-running compliance execution MUST выполняться как асинхронная task execution единица с наблюдаемым lifecycle, логами stage events и итоговой summary.
|
||
- **FR-023**: API запуск compliance MUST быть non-blocking и возвращать идентификаторы run и связанной task execution для последующего наблюдения.
|
||
- **FR-024**: Система MUST вести append-only audit log для создания кандидата, импорта артефактов, построения manifest, запуска compliance, завершения стадий, фиксации violations, генерации report, approval, publication и revoke.
|
||
- **FR-025**: В real mode система MUST NOT удалять historical runs, reports, violations или audit events.
|
||
- **FR-026**: Demo mode MUST использовать отдельный storage namespace, отдельные policy snapshots и отдельную историю, полностью изолированную от real mode.
|
||
- **FR-027**: TUI MUST быть thin client интерфейсом чтения и запуска операций и MUST NOT скрыто строить manifest, подмешивать policy, подменять registry, очищать history реального режима или создавать fake run только ради UI.
|
||
- **FR-028**: Для headless сценариев система MUST предоставлять CLI команды для candidate lifecycle, compliance, approval, publication и revoke.
|
||
- **FR-029**: Система MUST предоставлять HTTP endpoints для candidate lifecycle, manifest operations, compliance runs, report retrieval, approval и publication.
|
||
- **FR-030**: Система MUST предоставлять сводное представление candidate overview с данными о последнем manifest, последнем run, последнем report, latest policy snapshot, latest approval/publication state и текущем lifecycle state.
|
||
- **FR-031**: Compliance report MUST быть отдельной immutable сущностью с финальным статусом, summary и связью с конкретным run.
|
||
- **FR-032**: Система MUST позволять оператору получать список violations и stage details отдельно от итогового report.
|
||
- **FR-033**: Business actions для candidate, manifest, compliance, approval и publication MUST использовать единый application facade, одинаковый для CLI, TUI, API и будущего Web UI.
|
||
|
||
### Key Entities *(include if feature involves data)*
|
||
|
||
- **Release Candidate**: Объект управления выпуском, описывающий, что именно собираются выпустить и в каком lifecycle состоянии это находится.
|
||
- **Candidate Artifact**: Артефакт релиз-кандидата с доказуемыми признаками происхождения, контрольной суммой и двумя категориями классификации.
|
||
- **Distribution Manifest**: Immutable snapshot состава поставки, зафиксированный для конкретного кандидата и конкретной версии manifest.
|
||
- **Clean Policy Snapshot**: Доверенный immutable snapshot policy, использованный во время проверки.
|
||
- **Source Registry Snapshot**: Доверенный immutable snapshot реестра разрешённых источников.
|
||
- **Compliance Run**: Операционная сущность, представляющая отдельный запуск проверки для кандидата и manifest.
|
||
- **Compliance Stage Run**: Результат выполнения отдельной стадии pipeline внутри конкретного run.
|
||
- **Compliance Violation**: Зафиксированное нарушение с severity, evidence и ссылкой на stage/run.
|
||
- **Compliance Report**: Отдельный immutable итоговый отчёт по завершённому run.
|
||
- **Approval Decision**: Формальный акт approve/reject с actor, comment и ссылкой на report.
|
||
- **Publication Record**: Формальная запись публикации или отзыва с channel и статусом.
|
||
- **Candidate Overview**: Производное представление для интерфейсов, объединяющее состояние кандидата, latest manifest, latest run и latest report.
|
||
|
||
## Success Criteria *(mandatory)*
|
||
|
||
### Measurable Outcomes
|
||
|
||
- **SC-001**: 100% обязательных действий release lifecycle для стандартного сценария (`register -> import-artifacts -> build-manifest -> run-compliance -> approve -> publish`) выполняются без TUI через CLI или API.
|
||
- **SC-002**: 100% завершённых compliance runs оставляют неизменяемый report и связанный audit trail, доступный для чтения после завершения.
|
||
- **SC-003**: 100% попыток approve без успешного compliance result и publish без approval отклоняются системой.
|
||
- **SC-004**: Не менее 95% стандартных запусков compliance получают machine-readable outcome без ручного исправления состояния системы.
|
||
- **SC-005**: Не менее 90% операторов могут пройти базовый release workflow по quickstart без обращения к скрытым TUI-сценариям или ручным DB-операциям.
|
||
- **SC-006**: Время получения идентификатора run/task после запроса запуска compliance не превышает 2 секунд для типового кандидата.
|
||
- **SC-007**: В 100% real-mode сценариев historical runs, violations, reports и audit events не удаляются командами пользовательского интерфейса.
|
||
|
||
## Assumptions
|
||
|
||
- В проекте уже доступен общий TaskManager, пригодный для оркестрации long-running compliance tasks.
|
||
- Для policy и registry может быть предоставлен доверенный read-only источник, отдельный от пользовательского UI input.
|
||
- Существующий clean-release модуль допускает поэтапную миграцию без одномоментного удаления старых API/TUI entrypoints.
|
||
- Операторы релиза, approval actors и publication actors аутентифицированы существующими механизмами приложения.
|
||
- Demo mode нужен для демонстрации и тестовых сценариев, но не должен влиять на real mode evidence.
|