chore(specs): move clean-repo-enterprise spec from 020 to 023

This commit is contained in:
2026-03-03 19:50:53 +03:00
parent da24fb9253
commit 19898b1570
10 changed files with 1549 additions and 0 deletions

View File

@@ -0,0 +1,206 @@
openapi: 3.1.0
info:
title: Clean Release Compliance API
version: "1.0.0"
description: >
API contract for enterprise clean release validation in isolated corporate networks.
servers:
- url: https://internal-api.company.local
paths:
/api/clean-release/checks:
post:
summary: Start enterprise clean compliance check
operationId: startCleanComplianceCheck
tags: [clean-release]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StartCheckRequest'
examples:
enterpriseClean:
value:
candidate_id: "2026.03.03-rc1"
profile: "enterprise-clean"
execution_mode: "tui"
responses:
"202":
description: Check run accepted
content:
application/json:
schema:
$ref: '#/components/schemas/StartCheckResponse'
"400":
description: Invalid request
"403":
description: Forbidden
"409":
description: Candidate is not eligible for check
/api/clean-release/checks/{check_run_id}:
get:
summary: Get compliance check status
operationId: getCleanComplianceStatus
tags: [clean-release]
parameters:
- name: check_run_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Current check status
content:
application/json:
schema:
$ref: '#/components/schemas/CheckStatusResponse'
"404":
description: Check run not found
/api/clean-release/reports/{report_id}:
get:
summary: Get compliance report
operationId: getCleanComplianceReport
tags: [clean-release]
parameters:
- name: report_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Compliance report
content:
application/json:
schema:
$ref: '#/components/schemas/ComplianceReportResponse'
"404":
description: Report not found
components:
schemas:
StartCheckRequest:
type: object
required: [candidate_id, profile, execution_mode]
properties:
candidate_id:
type: string
profile:
type: string
enum: [enterprise-clean, development]
execution_mode:
type: string
enum: [tui, ci]
StartCheckResponse:
type: object
required: [check_run_id, candidate_id, status, started_at]
properties:
check_run_id:
type: string
candidate_id:
type: string
status:
type: string
enum: [running]
started_at:
type: string
format: date-time
CheckStageResult:
type: object
required: [stage, status]
properties:
stage:
type: string
enum: [data_purity, internal_sources_only, no_external_endpoints, manifest_consistency]
status:
type: string
enum: [pass, fail, skipped]
details:
type: string
duration_ms:
type: integer
minimum: 0
Violation:
type: object
required: [violation_id, category, severity, location, remediation, blocked_release]
properties:
violation_id:
type: string
category:
type: string
enum: [data-purity, external-source, manifest-integrity, policy-conflict, operational-risk]
severity:
type: string
enum: [critical, high, medium, low]
location:
type: string
evidence:
type: string
remediation:
type: string
blocked_release:
type: boolean
detected_at:
type: string
format: date-time
CheckStatusResponse:
type: object
required: [check_run_id, candidate_id, final_status, checks]
properties:
check_run_id:
type: string
candidate_id:
type: string
final_status:
type: string
enum: [running, compliant, blocked, failed]
started_at:
type: string
format: date-time
finished_at:
type: string
format: date-time
checks:
type: array
items:
$ref: '#/components/schemas/CheckStageResult'
violations:
type: array
items:
$ref: '#/components/schemas/Violation'
ComplianceReportResponse:
type: object
required:
[report_id, check_run_id, candidate_id, generated_at, final_status, operator_summary, violations_count, blocking_violations_count]
properties:
report_id:
type: string
check_run_id:
type: string
candidate_id:
type: string
generated_at:
type: string
format: date-time
final_status:
type: string
enum: [compliant, blocked, failed]
operator_summary:
type: string
structured_payload_ref:
type: string
violations_count:
type: integer
minimum: 0
blocking_violations_count:
type: integer
minimum: 0
violations:
type: array
items:
$ref: '#/components/schemas/Violation'

View File

@@ -0,0 +1,190 @@
# Module Contracts: Clean Repository Enterprise Preparation
## Contract Scope
Этот документ фиксирует семантические контракты новых модулей для enterprise clean-подготовки.
Контракты синхронизированы с UX состояниями из [`ux_reference.md`](../ux_reference.md) и моделью данных из [`data-model.md`](../data-model.md).
---
# [DEF:backend.src.services.clean_release.policy_engine:Module]
# @TIER: CRITICAL
# @SEMANTICS: clean-release, policy, classification, compliance, enterprise
# @PURPOSE: Evaluate artifact and source policies for enterprise clean profile with deterministic outcomes.
# @LAYER: Domain
# @RELATION: DEPENDS_ON -> backend.src.models.clean_release.CleanProfilePolicy
# @RELATION: DEPENDS_ON -> backend.src.models.clean_release.ResourceSourceRegistry
# @INVARIANT: For enterprise-clean profile, external resource sources are always forbidden.
# @TEST_CONTRACT: CleanPolicyEvaluation -> PolicyDecision
# @TEST_FIXTURE: policy_enterprise_clean -> {"external_source_forbidden": true, "prohibited_artifact_categories": ["test-data","demo-data"]}
# @TEST_EDGE: conflicting_rules -> same artifact matches allowed and prohibited patterns, must resolve to prohibited
# @TEST_EDGE: missing_registry -> enterprise-clean policy without internal_source_registry_ref must fail validation
# @TEST_EDGE: empty_prohibited_categories -> must fail policy activation for enterprise-clean
# @TEST_INVARIANT: deterministic_policy_result -> VERIFIED_BY: [policy_enterprise_clean, conflicting_rules]
class CleanPolicyEngine:
# @PURPOSE: Initialize policy engine with active policy and internal source registry.
# @PRE: Active policy exists and is internally consistent.
# @POST: Engine is ready for deterministic classification.
def __init__(self): ...
# @PURPOSE: Validate policy consistency before any release operation.
# @PRE: Policy payload is provided.
# @POST: Returns validation result with blocking reasons if inconsistent.
def validate_policy(self): ...
# @PURPOSE: Classify one artifact against policy categories.
# @PRE: Artifact metadata is provided.
# @POST: Returns one of [required-system, allowed, excluded-prohibited].
def classify_artifact(self): ...
# @PURPOSE: Validate that resource source belongs to internal registry.
# @PRE: Source endpoint is provided.
# @POST: Returns pass/fail and violation payload for non-internal sources.
def validate_resource_source(self): ...
# @PURPOSE: Evaluate full candidate policy compliance input.
# @PRE: Candidate artifacts and sources are provided.
# @POST: Returns deterministic policy decision and violations list.
def evaluate_candidate(self): ...
# [/DEF:backend.src.services.clean_release.policy_engine:Module]
---
# [DEF:backend.src.services.clean_release.compliance_orchestrator:Module]
# @TIER: CRITICAL
# @SEMANTICS: clean-release, compliance, orchestrator, release-gate, audit
# @PURPOSE: Orchestrate multi-stage compliance checks and produce final COMPLIANT/BLOCKED decision.
# @LAYER: Domain
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.policy_engine
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.report_builder
# @RELATION: DEPENDS_ON -> backend.src.models.clean_release.ComplianceCheckRun
# @INVARIANT: A check run cannot end with COMPLIANT if any mandatory stage fails.
# @TEST_CONTRACT: ComplianceRunInput -> ComplianceRunResult
# @TEST_FIXTURE: compliant_candidate -> {"stages":{"data_purity":"pass","internal_sources_only":"pass","no_external_endpoints":"pass","manifest_consistency":"pass"}}
# @TEST_EDGE: stage_failure_blocks_release -> one mandatory stage fail must force BLOCKED
# @TEST_EDGE: missing_stage_result -> incomplete stage set must fail run as invalid
# @TEST_EDGE: report_generation_error -> run must be marked failed, never falsely compliant
# @TEST_INVARIANT: blocking_gate_integrity -> VERIFIED_BY: [compliant_candidate, stage_failure_blocks_release]
class CleanComplianceOrchestrator:
# @PURPOSE: Start new compliance check run for a release candidate.
# @PRE: Candidate exists and policy is active.
# @POST: Check run created with status RUNNING.
def start_check_run(self): ...
# @PURPOSE: Execute mandatory stage sequence deterministically.
# @PRE: Check run is in RUNNING state.
# @POST: Stage statuses recorded for all mandatory checks.
def execute_stages(self): ...
# @PURPOSE: Finalize run status and trigger report build.
# @PRE: Stage execution completed or failed.
# @POST: Final status set to COMPLIANT/BLOCKED/FAILED with immutable result summary.
def finalize_run(self): ...
# [/DEF:backend.src.services.clean_release.compliance_orchestrator:Module]
---
# [DEF:backend.src.services.clean_release.report_builder:Module]
# @TIER: CRITICAL
# @SEMANTICS: compliance-report, audit, release, violations, summary
# @PURPOSE: Build operator-readable and machine-readable compliance reports for release audit.
# @LAYER: Domain
# @RELATION: DEPENDS_ON -> backend.src.models.clean_release.ComplianceReport
# @RELATION: DEPENDS_ON -> backend.src.models.clean_release.ComplianceViolation
# @INVARIANT: Report counters must match underlying violations set.
# @TEST_CONTRACT: ComplianceRunResult -> ComplianceReport
# @TEST_FIXTURE: blocked_with_two_violations -> {"violations":[{"category":"data-purity","blocked_release":true},{"category":"external-source","blocked_release":true}]}
# @TEST_EDGE: empty_violations_for_blocked -> blocked run without violations must fail report validation
# @TEST_EDGE: counter_mismatch -> blocking_violations_count cannot exceed violations_count
# @TEST_EDGE: missing_operator_summary -> report invalid without human-readable summary
# @TEST_INVARIANT: report_counter_consistency -> VERIFIED_BY: [blocked_with_two_violations, counter_mismatch]
class ComplianceReportBuilder:
# @PURPOSE: Build normalized report payload from run result.
# @PRE: Run has terminal status.
# @POST: Report payload includes required machine and operator fields.
def build_report_payload(self): ...
# @PURPOSE: Persist report and return report reference.
# @PRE: Report payload validated.
# @POST: Report saved with stable report_id.
def persist_report(self): ...
# [/DEF:backend.src.services.clean_release.report_builder:Module]
---
# [DEF:backend.src.scripts.clean_release_tui:Module]
# @TIER: CRITICAL
# @SEMANTICS: tui, ncurses, enterprise-clean, compliance, operator-flow
# @PURPOSE: Provide interactive ncurses-compatible TUI flow for clean release validation and report export.
# @LAYER: UI
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.compliance_orchestrator
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.report_builder
# @INVARIANT: TUI must always expose explicit terminal state READY/RUNNING/COMPLIANT/BLOCKED.
# @UX_STATE: READY -> Candidate and profile are visible; operator can trigger check via hotkey.
# @UX_STATE: RUNNING -> Stage progress is visible with current active check.
# @UX_STATE: COMPLIANT -> Final pass state with report id and export action.
# @UX_STATE: BLOCKED -> Final blocked state with violation table and remediation hints.
# @UX_FEEDBACK: On violation, blocked status is rendered with category/location/remediation.
# @UX_RECOVERY: Operator can fix inputs/config and rerun check from same screen without restarting tool.
# @TEST_CONTRACT: TuiOperatorAction -> TuiStateTransition
# @TEST_FIXTURE: ready_to_running -> {"initial":"READY","action":"F5","expected":"RUNNING"}
# @TEST_EDGE: blocked_due_to_external_source -> {"initial":"RUNNING","result":"external-source violation","expected":"BLOCKED"}
# @TEST_EDGE: internal_registry_unavailable -> {"initial":"RUNNING","error":"internal source unavailable","expected":"BLOCKED"}
# @TEST_EDGE: report_export_without_terminal_state -> export denied before COMPLIANT/BLOCKED
# @TEST_INVARIANT: state_machine_integrity -> VERIFIED_BY: [ready_to_running, blocked_due_to_external_source]
module CleanReleaseTui:
# @PURPOSE: Render main screen and initialize state machine.
# @PRE: Terminal supports ncurses-compatible mode.
# @POST: UI enters READY state with loaded candidate/profile context.
def run(self): ...
# @PURPOSE: Handle key actions (run check, view details, export, exit).
# @PRE: Current UI state exists.
# @POST: Deterministic transition to next valid state.
def handle_input(self): ...
# @PURPOSE: Render progress and status updates from orchestrator.
# @PRE: Check run started.
# @POST: UI reflects latest stage statuses and final result.
def render_status(self): ...
# [/DEF:backend.src.scripts.clean_release_tui:Module]
---
# [DEF:backend.src.api.routes.clean_release:Module]
# @TIER: STANDARD
# @SEMANTICS: api, clean-release, compliance, report, release-gate
# @PURPOSE: Expose release compliance endpoints for CI and controlled integrations.
# @LAYER: API
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.compliance_orchestrator
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.report_builder
# @INVARIANT: API never returns release-approved state when orchestration result is blocked/failed.
module CleanReleaseRouter:
# @PURPOSE: Start compliance check for a candidate.
# @PRE: Candidate exists and caller is authorized.
# @POST: Returns check_run_id and initial RUNNING status.
def start_check(self): ...
# @PURPOSE: Read compliance check status and stage details.
# @PRE: check_run_id exists.
# @POST: Returns deterministic status payload with stage matrix.
def get_check_status(self): ...
# @PURPOSE: Retrieve final compliance report.
# @PRE: check run reached terminal state.
# @POST: Returns report metadata and violations summary.
def get_report(self): ...
# [/DEF:backend.src.api.routes.clean_release:Module]
---
## Contract Trace (Key User Scenario)
Сценарий: оператор запускает TUI-проверку и получает BLOCKED из-за внешнего источника.
1. [`clean_release_tui`](#defbackendsrcscriptsclean_release_tuimodule) принимает `F5` и переводит состояние READY -> RUNNING.
2. [`compliance_orchestrator`](#defbackendsrcservicesclean_releasecompliance_orchestratormodule) запускает stage pipeline.
3. [`policy_engine`](#defbackendsrcservicesclean_releasepolicy_enginemodule) обнаруживает `external-source` нарушение и возвращает fail stage + violation.
4. [`compliance_orchestrator`](#defbackendsrcservicesclean_releasecompliance_orchestratormodule) завершает run статусом BLOCKED.
5. [`report_builder`](#defbackendsrcservicesclean_releasereport_buildermodule) формирует отчёт с remediation.
6. [`clean_release_tui`](#defbackendsrcscriptsclean_release_tuimodule) отображает BLOCKED + таблицу нарушений + путь восстановления.