253 lines
9.7 KiB
Markdown
253 lines
9.7 KiB
Markdown
# Data Model: Clean Repository Enterprise Preparation
|
||
|
||
## Overview
|
||
|
||
Модель данных описывает сущности, необходимые для подготовки и контроля enterprise clean-поставки в изолированном контуре без внешнего интернета.
|
||
|
||
---
|
||
|
||
## 1) ReleaseCandidate
|
||
|
||
**Purpose**: Представляет конкретный релиз-кандидат, проходящий clean-подготовку и compliance-проверку.
|
||
|
||
### Fields
|
||
|
||
- `candidate_id` (string, required, unique)
|
||
Уникальный идентификатор релиз-кандидата.
|
||
- `version` (string, required)
|
||
Версия/метка релиза.
|
||
- `profile` (enum, required)
|
||
Допустимые значения: `enterprise-clean`, `development`.
|
||
- `created_at` (datetime, required)
|
||
- `created_by` (string, required)
|
||
Идентификатор оператора/сервиса, создавшего candidate.
|
||
- `source_snapshot_ref` (string, required)
|
||
Ссылка на исходный снимок/состояние для воспроизводимости.
|
||
- `status` (enum, required)
|
||
`draft`, `prepared`, `compliant`, `blocked`, `released`.
|
||
|
||
### Validation Rules
|
||
|
||
- `candidate_id` и `source_snapshot_ref` не могут быть пустыми.
|
||
- Для `profile=enterprise-clean` переход в `released` разрешён только после `compliant`.
|
||
- Переходы статусов должны быть монотонными по lifecycle (без недетерминированных откатов).
|
||
|
||
---
|
||
|
||
## 2) CleanProfilePolicy
|
||
|
||
**Purpose**: Формальная политика классификации артефактов и источников ресурсов для enterprise clean-профиля.
|
||
|
||
### Fields
|
||
|
||
- `policy_id` (string, required, unique)
|
||
- `policy_version` (string, required)
|
||
- `active` (boolean, required)
|
||
- `prohibited_artifact_categories` (array[string], required)
|
||
Примеры: `test-data`, `demo-data`, `load-test`, `sample-repository`.
|
||
- `required_system_categories` (array[string], required)
|
||
Примеры: `system-init`, `security-bootstrap`, `schema-migrations`.
|
||
- `external_source_forbidden` (boolean, required; для enterprise-clean = true)
|
||
- `internal_source_registry_ref` (string, required)
|
||
Ссылка на реестр внутренних серверов.
|
||
- `effective_from` (datetime, required)
|
||
- `effective_to` (datetime, optional)
|
||
|
||
### Validation Rules
|
||
|
||
- Политика не может быть активирована без `internal_source_registry_ref`.
|
||
- Одновременная активность двух политик для одного профиля и периода запрещена.
|
||
- Для `enterprise-clean` поле `external_source_forbidden` всегда `true`.
|
||
|
||
---
|
||
|
||
## 3) ResourceSourceRegistry
|
||
|
||
**Purpose**: Реестр разрешённых внутренних серверов компании, используемых для загрузки всех ресурсов.
|
||
|
||
### Fields
|
||
|
||
- `registry_id` (string, required, unique)
|
||
- `name` (string, required)
|
||
- `entries` (array[ResourceSourceEntry], required, min=1)
|
||
- `updated_at` (datetime, required)
|
||
- `updated_by` (string, required)
|
||
- `status` (enum, required)
|
||
`active`, `inactive`.
|
||
|
||
### ResourceSourceEntry (nested)
|
||
|
||
- `source_id` (string, required, unique within registry)
|
||
- `host` (string, required)
|
||
- `protocol` (enum, required)
|
||
`http`, `https`, `ssh`, `file`.
|
||
- `purpose` (string, required)
|
||
Например: `artifact-repo`, `package-mirror`, `git-mirror`.
|
||
- `allowed_paths` (array[string], optional)
|
||
- `enabled` (boolean, required)
|
||
|
||
### Validation Rules
|
||
|
||
- В `entries` запрещены дубликаты `host + purpose`.
|
||
- При `status=active` должен существовать хотя бы один `enabled=true` entry.
|
||
- Внешние публичные хосты не допускаются в активном реестре enterprise clean-профиля.
|
||
|
||
---
|
||
|
||
## 4) DistributionManifest
|
||
|
||
**Purpose**: Зафиксированный состав итогового дистрибутива для аудита и воспроизводимости.
|
||
|
||
### Fields
|
||
|
||
- `manifest_id` (string, required, unique)
|
||
- `candidate_id` (string, required, FK -> ReleaseCandidate)
|
||
- `policy_id` (string, required, FK -> CleanProfilePolicy)
|
||
- `generated_at` (datetime, required)
|
||
- `generated_by` (string, required)
|
||
- `items` (array[ManifestItem], required)
|
||
- `summary` (ManifestSummary, required)
|
||
- `deterministic_hash` (string, required)
|
||
|
||
### ManifestItem (nested)
|
||
|
||
- `path` (string, required)
|
||
- `category` (string, required)
|
||
- `classification` (enum, required)
|
||
`required-system`, `allowed`, `excluded-prohibited`.
|
||
- `reason` (string, required)
|
||
- `checksum` (string, optional for included items)
|
||
|
||
### ManifestSummary (nested)
|
||
|
||
- `included_count` (integer, required, >=0)
|
||
- `excluded_count` (integer, required, >=0)
|
||
- `prohibited_detected_count` (integer, required, >=0)
|
||
|
||
### Validation Rules
|
||
|
||
- `candidate_id` и `policy_id` должны ссылаться на существующие записи.
|
||
- `deterministic_hash` должен быть одинаковым для идентичного входного состояния.
|
||
- `included_count + excluded_count` должно совпадать с размером `items`.
|
||
|
||
---
|
||
|
||
## 5) ComplianceCheckRun
|
||
|
||
**Purpose**: Один запуск проверки соответствия clean/compliance для релиз-кандидата.
|
||
|
||
### Fields
|
||
|
||
- `check_run_id` (string, required, unique)
|
||
- `candidate_id` (string, required, FK -> ReleaseCandidate)
|
||
- `policy_id` (string, required, FK -> CleanProfilePolicy)
|
||
- `started_at` (datetime, required)
|
||
- `finished_at` (datetime, optional)
|
||
- `final_status` (enum, required)
|
||
`running`, `compliant`, `blocked`, `failed`.
|
||
- `triggered_by` (string, required)
|
||
- `execution_mode` (enum, required)
|
||
`tui`, `ci`.
|
||
- `checks` (array[CheckStageResult], required)
|
||
|
||
### CheckStageResult (nested)
|
||
|
||
- `stage` (enum, required)
|
||
`data_purity`, `internal_sources_only`, `no_external_endpoints`, `manifest_consistency`.
|
||
- `status` (enum, required)
|
||
`pass`, `fail`, `skipped`.
|
||
- `details` (string, optional)
|
||
- `duration_ms` (integer, optional, >=0)
|
||
|
||
### Validation Rules
|
||
|
||
- `final_status=compliant` допускается только при `pass` для всех обязательных стадий.
|
||
- `final_status=blocked` обязателен при `fail` хотя бы одной обязательной стадии.
|
||
- `execution_mode=ci` и `execution_mode=tui` должны быть сопоставимы по policy/version.
|
||
|
||
---
|
||
|
||
## 6) ComplianceViolation
|
||
|
||
**Purpose**: Нормализованная запись конкретного нарушения, найденного в ходе проверки.
|
||
|
||
### Fields
|
||
|
||
- `violation_id` (string, required, unique)
|
||
- `check_run_id` (string, required, FK -> ComplianceCheckRun)
|
||
- `category` (enum, required)
|
||
`data-purity`, `external-source`, `manifest-integrity`, `policy-conflict`, `operational-risk`.
|
||
- `severity` (enum, required)
|
||
`critical`, `high`, `medium`, `low`.
|
||
- `location` (string, required)
|
||
Путь/endpoint/конфигурационный ключ.
|
||
- `evidence` (string, optional)
|
||
- `remediation` (string, required)
|
||
- `blocked_release` (boolean, required)
|
||
- `detected_at` (datetime, required)
|
||
|
||
### Validation Rules
|
||
|
||
- Для `category=external-source` поле `blocked_release` всегда `true` в enterprise clean-профиле.
|
||
- Для `severity=critical` поле `remediation` обязательно и непустое.
|
||
- `check_run_id` должен ссылаться на существующий запуск проверки.
|
||
|
||
---
|
||
|
||
## 7) ComplianceReport
|
||
|
||
**Purpose**: Финальный отчёт проверки для оператора и аудита.
|
||
|
||
### Fields
|
||
|
||
- `report_id` (string, required, unique)
|
||
- `check_run_id` (string, required, FK -> ComplianceCheckRun)
|
||
- `candidate_id` (string, required)
|
||
- `generated_at` (datetime, required)
|
||
- `operator_summary` (string, required)
|
||
- `structured_payload_ref` (string, required)
|
||
Ссылка на машинно-читаемое представление.
|
||
- `violations_count` (integer, required, >=0)
|
||
- `blocking_violations_count` (integer, required, >=0)
|
||
|
||
### Validation Rules
|
||
|
||
- `blocking_violations_count` ≤ `violations_count`.
|
||
- При `final_status=blocked` в связанном check run `blocking_violations_count` > 0.
|
||
- Отчёт должен быть доступен для экспортирования из TUI сценария.
|
||
|
||
---
|
||
|
||
## Relationships
|
||
|
||
1. `ReleaseCandidate` 1—N `DistributionManifest`
|
||
2. `CleanProfilePolicy` 1—N `DistributionManifest`
|
||
3. `ReleaseCandidate` 1—N `ComplianceCheckRun`
|
||
4. `CleanProfilePolicy` 1—N `ComplianceCheckRun`
|
||
5. `ComplianceCheckRun` 1—N `ComplianceViolation`
|
||
6. `ComplianceCheckRun` 1—1 `ComplianceReport`
|
||
7. `ResourceSourceRegistry` 1—N `CleanProfilePolicy` (по ссылке active policy)
|
||
|
||
---
|
||
|
||
## State Model Highlights
|
||
|
||
### ReleaseCandidate lifecycle
|
||
|
||
`draft -> prepared -> compliant -> released`
|
||
`draft|prepared -> blocked` (при нарушениях)
|
||
|
||
### ComplianceCheckRun lifecycle
|
||
|
||
`running -> compliant|blocked|failed`
|
||
|
||
---
|
||
|
||
## TUI Mapping Notes (from UX reference)
|
||
|
||
Состояния TUI из [`ux_reference.md`](./ux_reference.md) напрямую маппятся на сущности:
|
||
|
||
- `READY` -> `ReleaseCandidate.status in {draft, prepared}`
|
||
- `RUNNING` -> `ComplianceCheckRun.final_status = running`
|
||
- `COMPLIANT` -> `ComplianceCheckRun.final_status = compliant` + `ComplianceReport`
|
||
- `BLOCKED` -> `ComplianceCheckRun.final_status = blocked` + `ComplianceViolation[*].blocked_release=true` |