feat(clean-release): complete and verify backend test suite (33 passing tests)

- Relocated and standardized tests for clean_release subsystem into __tests__ sub-packages.
- Implemented missing unit tests for preparation_service, audit_service, and stages.
- Enhanced API contract tests for candidate preparation and compliance reporting.
- Updated 023-clean-repo-enterprise coverage matrix with final verification results.
- Fixed relative import issues and model validation mismatches during test migration.
This commit is contained in:
2026-03-04 13:53:43 +03:00
parent 7194f6a4c4
commit 0894254b98
20 changed files with 2729 additions and 1209 deletions

View File

@@ -2,12 +2,12 @@
> High-level module structure for AI Context. Generated automatically. > High-level module structure for AI Context. Generated automatically.
**Generated:** 2026-03-04T11:13:41.118516 **Generated:** 2026-03-04T13:18:11.370535
## Summary ## Summary
- **Total Modules:** 84 - **Total Modules:** 83
- **Total Entities:** 2288 - **Total Entities:** 2349
## Module Hierarchy ## Module Hierarchy
@@ -91,10 +91,10 @@
### 📁 `__tests__/` ### 📁 `__tests__/`
- 🏗️ **Layers:** API, Domain (Tests), UI (API Tests) - 🏗️ **Layers:** API, Domain, Domain (Tests), UI (API Tests), Unknown
- 📊 **Tiers:** STANDARD: 61, TRIVIAL: 121 - 📊 **Tiers:** STANDARD: 63, TRIVIAL: 134
- 📄 **Files:** 9 - 📄 **Files:** 12
- 📦 **Entities:** 182 - 📦 **Entities:** 197
**Key Entities:** **Key Entities:**
@@ -285,6 +285,18 @@
- 🔗 DEPENDS_ON -> TaskLogger, USED_BY -> plugins - 🔗 DEPENDS_ON -> TaskLogger, USED_BY -> plugins
- 🔗 DEPENDS_ON -> TaskManager, CALLS -> TaskManager._add_log - 🔗 DEPENDS_ON -> TaskManager, CALLS -> TaskManager._add_log
### 📁 `__tests__/`
- 🏗️ **Layers:** Unknown
- 📊 **Tiers:** TRIVIAL: 9
- 📄 **Files:** 1
- 📦 **Entities:** 9
**Key Entities:**
- 📦 **test_task_logger** (Module) `[TRIVIAL]`
- Auto-generated module for backend/src/core/task_manager/__te...
### 📁 `utils/` ### 📁 `utils/`
- 🏗️ **Layers:** Core, Domain, Infra - 🏗️ **Layers:** Core, Domain, Infra
@@ -363,13 +375,15 @@
### 📁 `__tests__/` ### 📁 `__tests__/`
- 🏗️ **Layers:** Domain - 🏗️ **Layers:** Domain, Unknown
- 📊 **Tiers:** STANDARD: 2, TRIVIAL: 27 - 📊 **Tiers:** STANDARD: 2, TRIVIAL: 38
- 📄 **Files:** 2 - 📄 **Files:** 3
- 📦 **Entities:** 29 - 📦 **Entities:** 40
**Key Entities:** **Key Entities:**
- 📦 **test_clean_release** (Module) `[TRIVIAL]`
- Auto-generated module for backend/src/models/__tests__/test_...
- 📦 **test_models** (Module) `[TRIVIAL]` - 📦 **test_models** (Module) `[TRIVIAL]`
- Unit tests for data models - Unit tests for data models
- 📦 **test_report_models** (Module) - 📦 **test_report_models** (Module)
@@ -539,9 +553,9 @@
### 📁 `services/` ### 📁 `services/`
- 🏗️ **Layers:** Core, Domain, Service - 🏗️ **Layers:** Core, Domain, Service
- 📊 **Tiers:** CRITICAL: 7, STANDARD: 75, TRIVIAL: 6 - 📊 **Tiers:** CRITICAL: 7, STANDARD: 76, TRIVIAL: 6
- 📄 **Files:** 7 - 📄 **Files:** 7
- 📦 **Entities:** 88 - 📦 **Entities:** 89
**Key Entities:** **Key Entities:**
@@ -576,10 +590,10 @@
### 📁 `__tests__/` ### 📁 `__tests__/`
- 🏗️ **Layers:** Domain, Domain Tests, Service - 🏗️ **Layers:** Domain, Domain Tests, Service, Unknown
- 📊 **Tiers:** STANDARD: 24, TRIVIAL: 7 - 📊 **Tiers:** STANDARD: 24, TRIVIAL: 17
- 📄 **Files:** 3 - 📄 **Files:** 4
- 📦 **Entities:** 31 - 📦 **Entities:** 41
**Key Entities:** **Key Entities:**
@@ -591,6 +605,8 @@
- Unit tests for ResourceService - Unit tests for ResourceService
- 📦 **test_encryption_manager** (Module) - 📦 **test_encryption_manager** (Module)
- Unit tests for EncryptionManager encrypt/decrypt functionali... - Unit tests for EncryptionManager encrypt/decrypt functionali...
- 📦 **test_llm_provider** (Module) `[TRIVIAL]`
- Auto-generated module for backend/src/services/__tests__/tes...
**Dependencies:** **Dependencies:**
@@ -635,17 +651,29 @@
### 📁 `__tests__/` ### 📁 `__tests__/`
- 🏗️ **Layers:** Domain - 🏗️ **Layers:** Domain, Infra, Unknown
- 📊 **Tiers:** STANDARD: 12 - 📊 **Tiers:** STANDARD: 18, TRIVIAL: 25
- 📄 **Files:** 2 - 📄 **Files:** 8
- 📦 **Entities:** 12 - 📦 **Entities:** 43
**Key Entities:** **Key Entities:**
- 📦 **backend.tests.services.clean_release.test_audit_service** (Module)
- Validate audit hooks emit expected log patterns for clean re...
- 📦 **backend.tests.services.clean_release.test_compliance_orchestrator** (Module) - 📦 **backend.tests.services.clean_release.test_compliance_orchestrator** (Module)
- Validate compliance orchestrator stage transitions and final... - Validate compliance orchestrator stage transitions and final...
- 📦 **backend.tests.services.clean_release.test_manifest_builder** (Module)
- Validate deterministic manifest generation behavior for US1.
- 📦 **backend.tests.services.clean_release.test_preparation_service** (Module)
- Validate release candidate preparation flow, including polic...
- 📦 **backend.tests.services.clean_release.test_report_builder** (Module) - 📦 **backend.tests.services.clean_release.test_report_builder** (Module)
- Validate compliance report builder counter integrity and blo... - Validate compliance report builder counter integrity and blo...
- 📦 **backend.tests.services.clean_release.test_source_isolation** (Module)
- Verify internal source registry validation behavior.
- 📦 **backend.tests.services.clean_release.test_stages** (Module)
- Validate final status derivation logic from stage results.
- 📦 **test_policy_engine** (Module) `[TRIVIAL]`
- Auto-generated module for backend/src/services/clean_release...
### 📁 `reports/` ### 📁 `reports/`
@@ -675,10 +703,10 @@
### 📁 `__tests__/` ### 📁 `__tests__/`
- 🏗️ **Layers:** Domain, Domain (Tests) - 🏗️ **Layers:** Domain, Domain (Tests), Unknown
- 📊 **Tiers:** STANDARD: 2, TRIVIAL: 19 - 📊 **Tiers:** STANDARD: 2, TRIVIAL: 24
- 📄 **Files:** 2 - 📄 **Files:** 3
- 📦 **Entities:** 21 - 📦 **Entities:** 26
**Key Entities:** **Key Entities:**
@@ -686,6 +714,8 @@
- Validate unknown task type fallback and partial payload norm... - Validate unknown task type fallback and partial payload norm...
- 📦 **test_report_service** (Module) - 📦 **test_report_service** (Module)
- Unit tests for ReportsService list/detail operations - Unit tests for ReportsService list/detail operations
- 📦 **test_type_profiles** (Module) `[TRIVIAL]`
- Auto-generated module for backend/src/services/reports/__tes...
### 📁 `tests/` ### 📁 `tests/`
@@ -717,26 +747,12 @@
- 📦 **test_smoke_plugins** (Module) `[TRIVIAL]` - 📦 **test_smoke_plugins** (Module) `[TRIVIAL]`
- Auto-generated module for backend/tests/test_smoke_plugins.p... - Auto-generated module for backend/tests/test_smoke_plugins.p...
### 📁 `routes/`
- 🏗️ **Layers:** Domain
- 📊 **Tiers:** STANDARD: 2, TRIVIAL: 5
- 📄 **Files:** 2
- 📦 **Entities:** 7
**Key Entities:**
- 📦 **backend.tests.api.routes.test_clean_release_api** (Module)
- Contract tests for clean release checks and reports endpoint...
- 📦 **backend.tests.api.routes.test_clean_release_source_policy** (Module)
- Validate API behavior for source isolation violations in cle...
### 📁 `core/` ### 📁 `core/`
- 🏗️ **Layers:** Domain, Unknown - 🏗️ **Layers:** Domain, Unknown
- 📊 **Tiers:** STANDARD: 5, TRIVIAL: 32 - 📊 **Tiers:** STANDARD: 5, TRIVIAL: 33
- 📄 **Files:** 4 - 📄 **Files:** 4
- 📦 **Entities:** 37 - 📦 **Entities:** 38
**Key Entities:** **Key Entities:**
@@ -763,22 +779,6 @@
- 📦 **backend.tests.core.migration.test_dry_run_orchestrator** (Module) - 📦 **backend.tests.core.migration.test_dry_run_orchestrator** (Module)
- Unit tests for MigrationDryRunService diff and risk computat... - Unit tests for MigrationDryRunService diff and risk computat...
### 📁 `clean_release/`
- 🏗️ **Layers:** Domain
- 📊 **Tiers:** STANDARD: 11, TRIVIAL: 5
- 📄 **Files:** 3
- 📦 **Entities:** 16
**Key Entities:**
- 📦 **backend.tests.services.clean_release.test_manifest_builder** (Module)
- Validate deterministic manifest generation behavior for US1.
- 📦 **backend.tests.services.clean_release.test_policy_engine** (Module)
- Validate policy model contracts and deterministic classifica...
- 📦 **backend.tests.services.clean_release.test_source_isolation** (Module)
- Verify internal source registry validation behavior.
### 📁 `components/` ### 📁 `components/`
- 🏗️ **Layers:** Component, Feature, UI, UI -->, Unknown - 🏗️ **Layers:** Component, Feature, UI, UI -->, Unknown
@@ -1107,9 +1107,9 @@
### 📁 `__tests__/` ### 📁 `__tests__/`
- 🏗️ **Layers:** UI, UI (Tests) - 🏗️ **Layers:** UI, UI (Tests)
- 📊 **Tiers:** STANDARD: 6, TRIVIAL: 4 - 📊 **Tiers:** STANDARD: 7, TRIVIAL: 4
- 📄 **Files:** 6 - 📄 **Files:** 7
- 📦 **Entities:** 10 - 📦 **Entities:** 11
**Key Entities:** **Key Entities:**
@@ -1123,6 +1123,8 @@
- Validate report type profile mapping and unknown fallback be... - Validate report type profile mapping and unknown fallback be...
- 📦 **frontend.src.lib.components.reports.__tests__.reports_filter_performance** (Module) - 📦 **frontend.src.lib.components.reports.__tests__.reports_filter_performance** (Module)
- Guard test for report filter responsiveness on moderate in-m... - Guard test for report filter responsiveness on moderate in-m...
- 📦 **frontend.src.lib.components.reports.__tests__.reports_list.ux** (Module)
- Test ReportsList component iteration and event forwarding.
- 📦 **frontend.src.lib.components.reports.__tests__.reports_page.integration** (Module) - 📦 **frontend.src.lib.components.reports.__tests__.reports_page.integration** (Module)
- Integration-style checks for unified mixed-type reports rend... - Integration-style checks for unified mixed-type reports rend...
@@ -1657,6 +1659,8 @@ graph TD
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend
__tests__-->|TESTS|backend
__tests__-->|DEPENDS_ON|backend __tests__-->|DEPENDS_ON|backend
__tests__-->|DEPENDS_ON|backend __tests__-->|DEPENDS_ON|backend
__tests__-->|VERIFIES|backend __tests__-->|VERIFIES|backend
@@ -1729,6 +1733,11 @@ graph TD
clean_release-->|DEPENDS_ON|backend clean_release-->|DEPENDS_ON|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend
__tests__-->|VERIFIES|backend
__tests__-->|TESTS|backend
__tests__-->|TESTS|backend
__tests__-->|TESTS|backend
reports-->|DEPENDS_ON|backend reports-->|DEPENDS_ON|backend
reports-->|DEPENDS_ON|backend reports-->|DEPENDS_ON|backend
reports-->|DEPENDS_ON|backend reports-->|DEPENDS_ON|backend
@@ -1739,16 +1748,11 @@ graph TD
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
tests-->|TESTS|backend tests-->|TESTS|backend
routes-->|TESTS|backend
routes-->|TESTS|backend
core-->|TESTS|backend core-->|TESTS|backend
core-->|VERIFIES|backend core-->|VERIFIES|backend
core-->|VERIFIES|backend core-->|VERIFIES|backend
migration-->|VERIFIES|backend migration-->|VERIFIES|backend
migration-->|VERIFIES|backend migration-->|VERIFIES|backend
clean_release-->|VERIFIES|backend
clean_release-->|VERIFIES|backend
clean_release-->|TESTS|backend
__tests__-->|VERIFIES|components __tests__-->|VERIFIES|components
__tests__-->|VERIFIES|components __tests__-->|VERIFIES|components
__tests__-->|VERIFIES|lib __tests__-->|VERIFIES|lib

View File

@@ -489,7 +489,6 @@
- 📝 Render unified list of normalized reports with canonical minimum fields. - 📝 Render unified list of normalized reports with canonical minimum fields.
- 🏗️ Layer: UI - 🏗️ Layer: UI
- 🔒 Invariant: Every rendered row shows task_type label, status, summary, and updated_at. - 🔒 Invariant: Every rendered row shows task_type label, status, summary, and updated_at.
- ⚡ Events: select
- ➡️ WRITES_TO `props` - ➡️ WRITES_TO `props`
- 📦 **ReportsList** (`Module`) `[TRIVIAL]` - 📦 **ReportsList** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for frontend/src/lib/components/reports/ReportsList.svelte - 📝 Auto-generated module for frontend/src/lib/components/reports/ReportsList.svelte
@@ -534,6 +533,9 @@
- 📝 Validate report type profile mapping and unknown fallback behavior. - 📝 Validate report type profile mapping and unknown fallback behavior.
- 🏗️ Layer: UI (Tests) - 🏗️ Layer: UI (Tests)
- 🔒 Invariant: Unknown task_type always resolves to the fallback profile. - 🔒 Invariant: Unknown task_type always resolves to the fallback profile.
- 📦 **frontend.src.lib.components.reports.__tests__.reports_list.ux** (`Module`)
- 📝 Test ReportsList component iteration and event forwarding.
- 🏗️ Layer: UI
- 📦 **frontend.src.lib.components.reports.__tests__.report_card.ux** (`Module`) - 📦 **frontend.src.lib.components.reports.__tests__.report_card.ux** (`Module`)
- 📝 Test UX states and transitions for ReportCard component - 📝 Test UX states and transitions for ReportCard component
- 🏗️ Layer: UI - 🏗️ Layer: UI
@@ -2833,6 +2835,25 @@
- 📝 Create a sub-context with a different default source. - 📝 Create a sub-context with a different default source.
- ƒ **execute** (`Function`) `[TRIVIAL]` - ƒ **execute** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- 📦 **test_task_logger** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for backend/src/core/task_manager/__tests__/test_task_logger.py
- 🏗️ Layer: Unknown
- ƒ **mock_add_log** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **task_logger** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_task_logger_initialization** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_log_methods_delegation** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_with_source** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_missing_task_id** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_invalid_add_log_fn** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_progress_log** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.src.api.auth** (`Module`) `[CRITICAL]` - 📦 **backend.src.api.auth** (`Module`) `[CRITICAL]`
- 📝 Authentication API endpoints. - 📝 Authentication API endpoints.
- 🏗️ Layer: API - 🏗️ Layer: API
@@ -3478,6 +3499,41 @@
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- ƒ **test_reports_detail_openapi_required_keys** (`Function`) `[TRIVIAL]` - ƒ **test_reports_detail_openapi_required_keys** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- 📦 **backend.tests.api.routes.test_clean_release_source_policy** (`Module`)
- 📝 Validate API behavior for source isolation violations in clean release preparation.
- 🏗️ Layer: Domain
- 🔒 Invariant: External endpoints must produce blocking violation entries.
- ƒ **_repo_with_seed_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_blocks_external_source** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.api.routes.test_clean_release_api** (`Module`)
- 📝 Contract tests for clean release checks and reports endpoints.
- 🏗️ Layer: Domain
- 🔒 Invariant: API returns deterministic payload shapes for checks and reports.
- ƒ **_repo_with_seed_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_start_check_and_get_status_contract** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_report_not_found_returns_404** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_report_success** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_api_success** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **test_tasks_logs** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for backend/src/api/routes/__tests__/test_tasks_logs.py
- 🏗️ Layer: Unknown
- ƒ **client** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_task_logs_success** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_task_logs_not_found** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_task_logs_invalid_limit** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_task_log_stats_success** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.test_reports_api** (`Module`) - 📦 **backend.tests.test_reports_api** (`Module`)
- 📝 Contract tests for GET /api/reports defaults, pagination, and filtering behavior. - 📝 Contract tests for GET /api/reports defaults, pagination, and filtering behavior.
- 🏗️ Layer: Domain (Tests) - 🏗️ Layer: Domain (Tests)
@@ -4004,6 +4060,29 @@
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- ƒ **test_with_all_fields** (`Function`) `[TRIVIAL]` - ƒ **test_with_all_fields** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- 📦 **test_clean_release** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for backend/src/models/__tests__/test_clean_release.py
- 🏗️ Layer: Unknown
- ƒ **valid_candidate_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_release_candidate_valid** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_release_candidate_empty_id** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **valid_policy_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_enterprise_policy_valid** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_enterprise_policy_missing_prohibited** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_enterprise_policy_external_allowed** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_manifest_count_mismatch** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_compliant_run_validation** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_report_validation** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.src.services.resource_service** (`Module`) - 📦 **backend.src.services.resource_service** (`Module`)
- 📝 Shared service for fetching resource data with Git status and task status - 📝 Shared service for fetching resource data with Git status and task status
- 🏗️ Layer: Service - 🏗️ Layer: Service
@@ -4132,6 +4211,8 @@
- 📝 Wrapper for GitPython operations with semantic logging and error handling. - 📝 Wrapper for GitPython operations with semantic logging and error handling.
- ƒ **__init__** (`Function`) - ƒ **__init__** (`Function`)
- 📝 Initializes the GitService with a base path for repositories. - 📝 Initializes the GitService with a base path for repositories.
- ƒ **_ensure_base_path_exists** (`Function`)
- 📝 Ensure the repositories root directory exists and is a directory.
- ƒ **_resolve_base_path** (`Function`) - ƒ **_resolve_base_path** (`Function`)
- 📝 Resolve base repository directory from explicit argument or global storage settings. - 📝 Resolve base repository directory from explicit argument or global storage settings.
- ƒ **_normalize_repo_key** (`Function`) - ƒ **_normalize_repo_key** (`Function`)
@@ -4259,6 +4340,27 @@
- 📝 Verify provider binding resolution priority. - 📝 Verify provider binding resolution priority.
- ƒ **test_normalize_llm_settings_keeps_assistant_planner_settings** (`Function`) - ƒ **test_normalize_llm_settings_keeps_assistant_planner_settings** (`Function`)
- 📝 Ensure assistant planner provider/model fields are preserved and normalized. - 📝 Ensure assistant planner provider/model fields are preserved and normalized.
- 📦 **test_llm_provider** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for backend/src/services/__tests__/test_llm_provider.py
- 🏗️ Layer: Unknown
- ƒ **test_encryption_cycle** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_empty_string_encryption** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_decrypt_invalid_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **mock_db** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **service** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_all_providers** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_create_provider** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_decrypted_api_key** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_decrypted_api_key_not_found** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.src.services.__tests__.test_resource_service** (`Module`) - 📦 **backend.src.services.__tests__.test_resource_service** (`Module`)
- 📝 Unit tests for ResourceService - 📝 Unit tests for ResourceService
- 🏗️ Layer: Service - 🏗️ Layer: Service
@@ -4402,6 +4504,32 @@
- 📝 Initialize clean release service package and provide explicit module exports. - 📝 Initialize clean release service package and provide explicit module exports.
- 🏗️ Layer: Domain - 🏗️ Layer: Domain
- 🔒 Invariant: Package import must not execute runtime side effects beyond symbol export setup. - 🔒 Invariant: Package import must not execute runtime side effects beyond symbol export setup.
- 📦 **backend.tests.services.clean_release.test_audit_service** (`Module`)
- 📝 Validate audit hooks emit expected log patterns for clean release lifecycle.
- 🏗️ Layer: Infra
- ƒ **test_audit_preparation** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_audit_check_run** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_audit_report** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **test_policy_engine** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for backend/src/services/clean_release/__tests__/test_policy_engine.py
- 🏗️ Layer: Unknown
- ƒ **enterprise_clean_setup** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_policy_valid** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_missing_registry_ref** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_conflicting_registry** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_classify_artifact** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_validate_resource_source** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_evaluate_candidate** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.services.clean_release.test_compliance_orchestrator** (`Module`) - 📦 **backend.tests.services.clean_release.test_compliance_orchestrator** (`Module`)
- 📝 Validate compliance orchestrator stage transitions and final status derivation. - 📝 Validate compliance orchestrator stage transitions and final status derivation.
- 🏗️ Layer: Domain - 🏗️ Layer: Domain
@@ -4430,6 +4558,51 @@
- 📝 Verify violations counters remain consistent for blocking payload. - 📝 Verify violations counters remain consistent for blocking payload.
- ƒ **test_missing_operator_summary** (`Function`) - ƒ **test_missing_operator_summary** (`Function`)
- 📝 Validate non-terminal run prevents operator summary/report generation. - 📝 Validate non-terminal run prevents operator summary/report generation.
- 📦 **backend.tests.services.clean_release.test_manifest_builder** (`Module`)
- 📝 Validate deterministic manifest generation behavior for US1.
- 🏗️ Layer: Domain
- 🔒 Invariant: Same input artifacts produce identical deterministic hash.
- ƒ **test_manifest_deterministic_hash_for_same_input** (`Function`)
- 📝 Ensure hash is stable for same candidate/policy/artifact input.
- 📦 **backend.tests.services.clean_release.test_stages** (`Module`)
- 📝 Validate final status derivation logic from stage results.
- 🏗️ Layer: Domain
- ƒ **test_derive_final_status_compliant** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_derive_final_status_blocked** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_derive_final_status_failed_missing** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_derive_final_status_failed_skipped** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.services.clean_release.test_source_isolation** (`Module`)
- 📝 Verify internal source registry validation behavior.
- 🏗️ Layer: Domain
- 🔒 Invariant: External endpoints always produce blocking violations.
- ƒ **_registry** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_validate_internal_sources_all_internal_ok** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_validate_internal_sources_external_blocked** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.services.clean_release.test_preparation_service** (`Module`)
- 📝 Validate release candidate preparation flow, including policy evaluation and manifest persisting.
- 🏗️ Layer: Domain
- 🔒 Invariant: Candidate preparation always persists manifest and candidate status deterministically.
- ƒ **_mock_policy** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **_mock_registry** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **_mock_candidate** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_success** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_with_violations** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_not_found** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_no_active_policy** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.src.services.reports.normalizer** (`Module`) `[CRITICAL]` - 📦 **backend.src.services.reports.normalizer** (`Module`) `[CRITICAL]`
- 📝 Convert task manager task objects into canonical unified TaskReport entities with deterministic fallback behavior. - 📝 Convert task manager task objects into canonical unified TaskReport entities with deterministic fallback behavior.
- 🏗️ Layer: Domain - 🏗️ Layer: Domain
@@ -4490,6 +4663,17 @@
- 📝 Return filtered, sorted, paginated report collection. - 📝 Return filtered, sorted, paginated report collection.
- ƒ **get_report_detail** (`Function`) - ƒ **get_report_detail** (`Function`)
- 📝 Return one normalized report with timeline/diagnostics/next actions. - 📝 Return one normalized report with timeline/diagnostics/next actions.
- 📦 **test_type_profiles** (`Module`) `[TRIVIAL]`
- 📝 Auto-generated module for backend/src/services/reports/__tests__/test_type_profiles.py
- 🏗️ Layer: Unknown
- ƒ **test_resolve_task_type_fallbacks** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_resolve_task_type_valid** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_type_profile_valid** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_type_profile_fallback** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **test_report_service** (`Module`) - 📦 **test_report_service** (`Module`)
- 📝 Unit tests for ReportsService list/detail operations - 📝 Unit tests for ReportsService list/detail operations
- 🏗️ Layer: Domain - 🏗️ Layer: Domain
@@ -5224,6 +5408,8 @@
- 🏗️ Layer: Unknown - 🏗️ Layer: Unknown
- ƒ **test_git_service_get_repo_path_guard** (`Function`) `[TRIVIAL]` - ƒ **test_git_service_get_repo_path_guard** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- ƒ **test_git_service_get_repo_path_recreates_base_dir** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_superset_client_import_dashboard_guard** (`Function`) `[TRIVIAL]` - ƒ **test_superset_client_import_dashboard_guard** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- 📦 **backend.tests.core.test_migration_engine** (`Module`) - 📦 **backend.tests.core.test_migration_engine** (`Module`)
@@ -5269,59 +5455,3 @@
- 🏗️ Layer: Domain - 🏗️ Layer: Domain
- ƒ **test_extract_objects_from_zip_collects_all_types** (`Function`) `[TRIVIAL]` - ƒ **test_extract_objects_from_zip_collects_all_types** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan) - 📝 Auto-detected function (orphan)
- 📦 **backend.tests.api.routes.test_clean_release_source_policy** (`Module`)
- 📝 Validate API behavior for source isolation violations in clean release preparation.
- 🏗️ Layer: Domain
- 🔒 Invariant: External endpoints must produce blocking violation entries.
- ƒ **_repo_with_seed_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_prepare_candidate_blocks_external_source** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.api.routes.test_clean_release_api** (`Module`)
- 📝 Contract tests for clean release checks and reports endpoints.
- 🏗️ Layer: Domain
- 🔒 Invariant: API returns deterministic payload shapes for checks and reports.
- ƒ **_repo_with_seed_data** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_start_check_and_get_status_contract** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_get_report_not_found_returns_404** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- 📦 **backend.tests.services.clean_release.test_policy_engine** (`Module`)
- 📝 Validate policy model contracts and deterministic classification prerequisites for US1.
- 🏗️ Layer: Domain
- 🔒 Invariant: Enterprise policy rejects invalid activation states.
- ƒ **test_policy_enterprise_clean_valid** (`Function`)
- 📝 Ensure valid enterprise policy payload is accepted.
- ƒ **test_policy_missing_registry_fails** (`Function`)
- 📝 Verify missing registry ref violates policy contract.
- ƒ **test_policy_empty_prohibited_categories_fails** (`Function`)
- 📝 Verify enterprise policy cannot activate without prohibited categories.
- ƒ **test_policy_conflicting_external_forbidden_flag_fails** (`Function`)
- 📝 Verify enterprise policy enforces external_source_forbidden=true.
- ƒ **_policy_enterprise_clean** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **_registry** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_policy_valid** (`Function`)
- 📝 Validate policy valid scenario
- ƒ **test_conflicting_registry** (`Function`)
- 📝 Validate policy conflicting registry edge
- ƒ **test_external_endpoint** (`Function`)
- 📝 Validate policy external endpoint edge
- 📦 **backend.tests.services.clean_release.test_manifest_builder** (`Module`)
- 📝 Validate deterministic manifest generation behavior for US1.
- 🏗️ Layer: Domain
- 🔒 Invariant: Same input artifacts produce identical deterministic hash.
- ƒ **test_manifest_deterministic_hash_for_same_input** (`Function`)
- 📝 Ensure hash is stable for same candidate/policy/artifact input.
- 📦 **backend.tests.services.clean_release.test_source_isolation** (`Module`)
- 📝 Verify internal source registry validation behavior.
- 🏗️ Layer: Domain
- 🔒 Invariant: External endpoints always produce blocking violations.
- ƒ **_registry** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_validate_internal_sources_all_internal_ok** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)
- ƒ **test_validate_internal_sources_external_blocked** (`Function`) `[TRIVIAL]`
- 📝 Auto-detected function (orphan)

View File

@@ -19,6 +19,8 @@ from src.models.clean_release import (
ReleaseCandidateStatus, ReleaseCandidateStatus,
ResourceSourceEntry, ResourceSourceEntry,
ResourceSourceRegistry, ResourceSourceRegistry,
ComplianceReport,
CheckFinalStatus,
) )
from src.services.clean_release.repository import CleanReleaseRepository from src.services.clean_release.repository import CleanReleaseRepository
@@ -107,5 +109,49 @@ def test_get_report_not_found_returns_404():
client = TestClient(app) client = TestClient(app)
resp = client.get("/api/clean-release/reports/unknown-report") resp = client.get("/api/clean-release/reports/unknown-report")
assert resp.status_code == 404 assert resp.status_code == 404
finally:
app.dependency_overrides.clear()
def test_get_report_success():
repo = _repo_with_seed_data()
report = ComplianceReport(
report_id="rep-1",
check_run_id="run-1",
candidate_id="2026.03.03-rc1",
generated_at=datetime.now(timezone.utc),
final_status=CheckFinalStatus.COMPLIANT,
operator_summary="all systems go",
structured_payload_ref="manifest-1",
violations_count=0,
blocking_violations_count=0
)
repo.save_report(report)
app.dependency_overrides[get_clean_release_repository] = lambda: repo
try:
client = TestClient(app)
resp = client.get("/api/clean-release/reports/rep-1")
assert resp.status_code == 200
assert resp.json()["report_id"] == "rep-1"
finally:
app.dependency_overrides.clear()
def test_prepare_candidate_api_success():
repo = _repo_with_seed_data()
app.dependency_overrides[get_clean_release_repository] = lambda: repo
try:
client = TestClient(app)
response = client.post(
"/api/clean-release/candidates/prepare",
json={
"candidate_id": "2026.03.03-rc1",
"artifacts": [{"path": "file1.txt", "category": "system-init", "reason": "core"}],
"sources": ["repo.intra.company.local"],
"operator_id": "operator-1",
},
)
assert response.status_code == 200
data = response.json()
assert data["status"] == "prepared"
assert "manifest_id" in data
finally: finally:
app.dependency_overrides.clear() app.dependency_overrides.clear()

View File

@@ -182,6 +182,16 @@ async def get_task(
# @POST: Returns a list of log entries or raises 404. # @POST: Returns a list of log entries or raises 404.
# @RETURN: List[LogEntry] - List of log entries. # @RETURN: List[LogEntry] - List of log entries.
# @TIER: CRITICAL # @TIER: CRITICAL
# @TEST_CONTRACT get_task_logs_api ->
# {
# required_params: {task_id: str},
# optional_params: {level: str, source: str, search: str},
# invariants: ["returns 404 for non-existent task", "applies filters correctly"]
# }
# @TEST_FIXTURE valid_task_logs_request -> {"task_id": "test_1", "level": "INFO"}
# @TEST_EDGE task_not_found -> raises 404
# @TEST_EDGE invalid_limit -> Query(limit=0) returns 422
# @TEST_INVARIANT response_purity -> verifies: [valid_task_logs_request]
# @TEST_CONTRACT: TaskLogQueryInput -> List[LogEntry] # @TEST_CONTRACT: TaskLogQueryInput -> List[LogEntry]
# @TEST_SCENARIO: existing_task_logs_filtered -> Returns filtered logs by level/source/search with pagination. # @TEST_SCENARIO: existing_task_logs_filtered -> Returns filtered logs by level/source/search with pagination.
# @TEST_FIXTURE: valid_task_with_mixed_logs -> backend/tests/fixtures/task_logs/valid_task_with_mixed_logs.json # @TEST_FIXTURE: valid_task_with_mixed_logs -> backend/tests/fixtures/task_logs/valid_task_with_mixed_logs.json

View File

@@ -0,0 +1,149 @@
# [DEF:__tests__/test_clean_release:Module]
# @RELATION: VERIFIES -> ../clean_release.py
# @PURPOSE: Contract testing for Clean Release models
# [/DEF:__tests__/test_clean_release:Module]
import pytest
from datetime import datetime
from pydantic import ValidationError
from src.models.clean_release import (
ReleaseCandidate,
ReleaseCandidateStatus,
ProfileType,
CleanProfilePolicy,
DistributionManifest,
ManifestItem,
ManifestSummary,
ClassificationType,
ComplianceCheckRun,
CheckFinalStatus,
CheckStageResult,
CheckStageName,
CheckStageStatus,
ComplianceReport,
ExecutionMode
)
# @TEST_FIXTURE: valid_enterprise_candidate
@pytest.fixture
def valid_candidate_data():
return {
"candidate_id": "RC-001",
"version": "1.0.0",
"profile": ProfileType.ENTERPRISE_CLEAN,
"created_at": datetime.now(),
"created_by": "admin",
"source_snapshot_ref": "v1.0.0-snapshot"
}
def test_release_candidate_valid(valid_candidate_data):
rc = ReleaseCandidate(**valid_candidate_data)
assert rc.candidate_id == "RC-001"
assert rc.status == ReleaseCandidateStatus.DRAFT
def test_release_candidate_empty_id(valid_candidate_data):
valid_candidate_data["candidate_id"] = " "
with pytest.raises(ValueError, match="candidate_id must be non-empty"):
ReleaseCandidate(**valid_candidate_data)
# @TEST_FIXTURE: valid_enterprise_policy
@pytest.fixture
def valid_policy_data():
return {
"policy_id": "POL-001",
"policy_version": "1",
"active": True,
"prohibited_artifact_categories": ["test-data"],
"required_system_categories": ["core"],
"internal_source_registry_ref": "REG-1",
"effective_from": datetime.now(),
"profile": ProfileType.ENTERPRISE_CLEAN
}
# @TEST_INVARIANT: policy_purity
def test_enterprise_policy_valid(valid_policy_data):
policy = CleanProfilePolicy(**valid_policy_data)
assert policy.external_source_forbidden is True
# @TEST_EDGE: enterprise_policy_missing_prohibited
def test_enterprise_policy_missing_prohibited(valid_policy_data):
valid_policy_data["prohibited_artifact_categories"] = []
with pytest.raises(ValueError, match="enterprise-clean policy requires prohibited_artifact_categories"):
CleanProfilePolicy(**valid_policy_data)
# @TEST_EDGE: enterprise_policy_external_allowed
def test_enterprise_policy_external_allowed(valid_policy_data):
valid_policy_data["external_source_forbidden"] = False
with pytest.raises(ValueError, match="enterprise-clean policy requires external_source_forbidden=true"):
CleanProfilePolicy(**valid_policy_data)
# @TEST_INVARIANT: manifest_consistency
# @TEST_EDGE: manifest_count_mismatch
def test_manifest_count_mismatch():
summary = ManifestSummary(included_count=1, excluded_count=0, prohibited_detected_count=0)
item = ManifestItem(path="p", category="c", classification=ClassificationType.ALLOWED, reason="r")
# Valid
DistributionManifest(
manifest_id="m1", candidate_id="rc1", policy_id="p1",
generated_at=datetime.now(), generated_by="u", items=[item],
summary=summary, deterministic_hash="h"
)
# Invalid count
summary.included_count = 2
with pytest.raises(ValueError, match="manifest summary counts must match items size"):
DistributionManifest(
manifest_id="m1", candidate_id="rc1", policy_id="p1",
generated_at=datetime.now(), generated_by="u", items=[item],
summary=summary, deterministic_hash="h"
)
# @TEST_INVARIANT: run_integrity
# @TEST_EDGE: compliant_run_stage_fail
def test_compliant_run_validation():
base_run = {
"check_run_id": "run1",
"candidate_id": "rc1",
"policy_id": "p1",
"started_at": datetime.now(),
"triggered_by": "u",
"execution_mode": ExecutionMode.TUI,
"final_status": CheckFinalStatus.COMPLIANT,
"checks": [
CheckStageResult(stage=CheckStageName.DATA_PURITY, status=CheckStageStatus.PASS),
CheckStageResult(stage=CheckStageName.INTERNAL_SOURCES_ONLY, status=CheckStageStatus.PASS),
CheckStageResult(stage=CheckStageName.NO_EXTERNAL_ENDPOINTS, status=CheckStageStatus.PASS),
CheckStageResult(stage=CheckStageName.MANIFEST_CONSISTENCY, status=CheckStageStatus.PASS),
]
}
# Valid
ComplianceCheckRun(**base_run)
# One stage fails -> cannot be COMPLIANT
base_run["checks"][0].status = CheckStageStatus.FAIL
with pytest.raises(ValueError, match="compliant run requires PASS on all mandatory stages"):
ComplianceCheckRun(**base_run)
# Missing stage -> cannot be COMPLIANT
base_run["checks"] = base_run["checks"][1:]
with pytest.raises(ValueError, match="compliant run requires all mandatory stages"):
ComplianceCheckRun(**base_run)
def test_report_validation():
# Valid blocked report
ComplianceReport(
report_id="rep1", check_run_id="run1", candidate_id="rc1",
generated_at=datetime.now(), final_status=CheckFinalStatus.BLOCKED,
operator_summary="Blocked", structured_payload_ref="ref",
violations_count=2, blocking_violations_count=2
)
# BLOCKED with 0 blocking violations
with pytest.raises(ValueError, match="blocked report requires blocking violations"):
ComplianceReport(
report_id="rep1", check_run_id="run1", candidate_id="rc1",
generated_at=datetime.now(), final_status=CheckFinalStatus.BLOCKED,
operator_summary="Blocked", structured_payload_ref="ref",
violations_count=2, blocking_violations_count=0
)

View File

@@ -5,6 +5,28 @@
# @LAYER: Domain # @LAYER: Domain
# @RELATION: BINDS_TO -> specs/023-clean-repo-enterprise/data-model.md # @RELATION: BINDS_TO -> specs/023-clean-repo-enterprise/data-model.md
# @INVARIANT: Enterprise-clean policy always forbids external sources. # @INVARIANT: Enterprise-clean policy always forbids external sources.
#
# @TEST_CONTRACT CleanReleaseModels ->
# {
# required_fields: {
# ReleaseCandidate: [candidate_id, version, profile, source_snapshot_ref],
# CleanProfilePolicy: [policy_id, policy_version, internal_source_registry_ref]
# },
# invariants: [
# "enterprise-clean profile enforces external_source_forbidden=True",
# "manifest summary counts are consistent with items",
# "compliant run requires all mandatory stages to pass"
# ]
# }
# @TEST_FIXTURE valid_enterprise_candidate -> {"candidate_id": "RC-001", "version": "1.0.0", "profile": "enterprise-clean", "source_snapshot_ref": "v1.0.0-snapshot"}
# @TEST_FIXTURE valid_enterprise_policy -> {"policy_id": "POL-001", "policy_version": "1", "internal_source_registry_ref": "REG-1", "prohibited_artifact_categories": ["test-data"]}
# @TEST_EDGE enterprise_policy_missing_prohibited -> profile=enterprise-clean with empty prohibited_artifact_categories raises ValueError
# @TEST_EDGE enterprise_policy_external_allowed -> profile=enterprise-clean with external_source_forbidden=False raises ValueError
# @TEST_EDGE manifest_count_mismatch -> included + excluded != len(items) raises ValueError
# @TEST_EDGE compliant_run_stage_fail -> COMPLIANT run with failed stage raises ValueError
# @TEST_INVARIANT policy_purity -> verifies: [valid_enterprise_policy, enterprise_policy_external_allowed]
# @TEST_INVARIANT manifest_consistency -> verifies: [manifest_count_mismatch]
# @TEST_INVARIANT run_integrity -> verifies: [compliant_run_stage_fail]
# @TEST_CONTRACT: CleanReleaseModelPayload -> ValidatedCleanReleaseModel | ValidationError # @TEST_CONTRACT: CleanReleaseModelPayload -> ValidatedCleanReleaseModel | ValidationError
# @TEST_SCENARIO: valid_enterprise_models -> CRITICAL entities validate and preserve lifecycle/compliance invariants. # @TEST_SCENARIO: valid_enterprise_models -> CRITICAL entities validate and preserve lifecycle/compliance invariants.
# @TEST_FIXTURE: clean_release_models_baseline -> backend/tests/fixtures/clean_release/fixtures_clean_release.json # @TEST_FIXTURE: clean_release_models_baseline -> backend/tests/fixtures/clean_release/fixtures_clean_release.json

View File

@@ -0,0 +1,24 @@
# [DEF:backend.tests.services.clean_release.test_audit_service:Module]
# @TIER: STANDARD
# @SEMANTICS: tests, clean-release, audit, logging
# @PURPOSE: Validate audit hooks emit expected log patterns for clean release lifecycle.
# @LAYER: Infra
# @RELATION: TESTS -> backend.src.services.clean_release.audit_service
from unittest.mock import patch
from src.services.clean_release.audit_service import audit_preparation, audit_check_run, audit_report
@patch("src.services.clean_release.audit_service.logger")
def test_audit_preparation(mock_logger):
audit_preparation("cand-1", "PREPARED")
mock_logger.info.assert_called_with("[REASON] clean-release preparation candidate=cand-1 status=PREPARED")
@patch("src.services.clean_release.audit_service.logger")
def test_audit_check_run(mock_logger):
audit_check_run("check-1", "COMPLIANT")
mock_logger.info.assert_called_with("[REFLECT] clean-release check_run=check-1 final_status=COMPLIANT")
@patch("src.services.clean_release.audit_service.logger")
def test_audit_report(mock_logger):
audit_report("rep-1", "cand-1")
mock_logger.info.assert_called_with("[EXPLORE] clean-release report_id=rep-1 candidate=cand-1")

View File

@@ -0,0 +1,114 @@
# [DEF:__tests__/test_policy_engine:Module]
# @RELATION: VERIFIES -> ../policy_engine.py
# @PURPOSE: Contract testing for CleanPolicyEngine
# [/DEF:__tests__/test_policy_engine:Module]
import pytest
from datetime import datetime
from src.models.clean_release import (
CleanProfilePolicy,
ResourceSourceRegistry,
ResourceSourceEntry,
ProfileType,
RegistryStatus
)
from src.services.clean_release.policy_engine import CleanPolicyEngine
# @TEST_FIXTURE: policy_enterprise_clean
@pytest.fixture
def enterprise_clean_setup():
policy = CleanProfilePolicy(
policy_id="POL-1",
policy_version="1",
active=True,
prohibited_artifact_categories=["demo", "test"],
required_system_categories=["core"],
internal_source_registry_ref="REG-1",
effective_from=datetime.now(),
profile=ProfileType.ENTERPRISE_CLEAN
)
registry = ResourceSourceRegistry(
registry_id="REG-1",
name="Internal Registry",
entries=[
ResourceSourceEntry(source_id="S1", host="internal.com", protocol="https", purpose="p1", enabled=True)
],
updated_at=datetime.now(),
updated_by="admin",
status=RegistryStatus.ACTIVE
)
return policy, registry
# @TEST_SCENARIO: policy_valid
def test_policy_valid(enterprise_clean_setup):
policy, registry = enterprise_clean_setup
engine = CleanPolicyEngine(policy, registry)
result = engine.validate_policy()
assert result.ok is True
assert not result.blocking_reasons
# @TEST_EDGE: missing_registry_ref
def test_missing_registry_ref(enterprise_clean_setup):
policy, registry = enterprise_clean_setup
policy.internal_source_registry_ref = " "
engine = CleanPolicyEngine(policy, registry)
result = engine.validate_policy()
assert result.ok is False
assert "Policy missing internal_source_registry_ref" in result.blocking_reasons
# @TEST_EDGE: conflicting_registry
def test_conflicting_registry(enterprise_clean_setup):
policy, registry = enterprise_clean_setup
registry.registry_id = "WRONG-REG"
engine = CleanPolicyEngine(policy, registry)
result = engine.validate_policy()
assert result.ok is False
assert "Policy registry ref does not match provided registry" in result.blocking_reasons
# @TEST_INVARIANT: deterministic_classification
def test_classify_artifact(enterprise_clean_setup):
policy, registry = enterprise_clean_setup
engine = CleanPolicyEngine(policy, registry)
# Required
assert engine.classify_artifact({"category": "core", "path": "p1"}) == "required-system"
# Prohibited
assert engine.classify_artifact({"category": "demo", "path": "p2"}) == "excluded-prohibited"
# Allowed
assert engine.classify_artifact({"category": "others", "path": "p3"}) == "allowed"
# @TEST_EDGE: external_endpoint
def test_validate_resource_source(enterprise_clean_setup):
policy, registry = enterprise_clean_setup
engine = CleanPolicyEngine(policy, registry)
# Internal (OK)
res_ok = engine.validate_resource_source("internal.com")
assert res_ok.ok is True
# External (Blocked)
res_fail = engine.validate_resource_source("external.evil")
assert res_fail.ok is False
assert res_fail.violation["category"] == "external-source"
assert res_fail.violation["blocked_release"] is True
def test_evaluate_candidate(enterprise_clean_setup):
policy, registry = enterprise_clean_setup
engine = CleanPolicyEngine(policy, registry)
artifacts = [
{"path": "core.js", "category": "core"},
{"path": "demo.sql", "category": "demo"}
]
sources = ["internal.com", "google.com"]
classified, violations = engine.evaluate_candidate(artifacts, sources)
assert len(classified) == 2
assert classified[0]["classification"] == "required-system"
assert classified[1]["classification"] == "excluded-prohibited"
# 1 violation for demo artifact + 1 for google.com source
assert len(violations) == 2
assert violations[0]["category"] == "data-purity"
assert violations[1]["category"] == "external-source"

View File

@@ -0,0 +1,127 @@
# [DEF:backend.tests.services.clean_release.test_preparation_service:Module]
# @TIER: STANDARD
# @SEMANTICS: tests, clean-release, preparation, flow
# @PURPOSE: Validate release candidate preparation flow, including policy evaluation and manifest persisting.
# @LAYER: Domain
# @RELATION: TESTS -> backend.src.services.clean_release.preparation_service
# @INVARIANT: Candidate preparation always persists manifest and candidate status deterministically.
import pytest
from unittest.mock import MagicMock, patch
from datetime import datetime, timezone
from src.models.clean_release import (
CleanProfilePolicy,
ResourceSourceRegistry,
ResourceSourceEntry,
ReleaseCandidate,
ReleaseCandidateStatus,
ProfileType,
DistributionManifest
)
from src.services.clean_release.preparation_service import prepare_candidate
def _mock_policy() -> CleanProfilePolicy:
return CleanProfilePolicy(
policy_id="pol-1",
policy_version="1.0.0",
active=True,
prohibited_artifact_categories=["prohibited"],
required_system_categories=["system"],
external_source_forbidden=True,
internal_source_registry_ref="reg-1",
effective_from=datetime.now(timezone.utc),
profile=ProfileType.ENTERPRISE_CLEAN,
)
def _mock_registry() -> ResourceSourceRegistry:
return ResourceSourceRegistry(
registry_id="reg-1",
name="Reg",
entries=[ResourceSourceEntry(source_id="s1", host="nexus.internal", protocol="https", purpose="pkg", enabled=True)],
updated_at=datetime.now(timezone.utc),
updated_by="tester"
)
def _mock_candidate(candidate_id: str) -> ReleaseCandidate:
return ReleaseCandidate(
candidate_id=candidate_id,
version="1.0.0",
profile=ProfileType.ENTERPRISE_CLEAN,
created_at=datetime.now(timezone.utc),
status=ReleaseCandidateStatus.DRAFT,
created_by="tester",
source_snapshot_ref="v1.0.0-snapshot"
)
def test_prepare_candidate_success():
# Setup
repository = MagicMock()
candidate_id = "cand-1"
candidate = _mock_candidate(candidate_id)
repository.get_candidate.return_value = candidate
repository.get_active_policy.return_value = _mock_policy()
repository.get_registry.return_value = _mock_registry()
artifacts = [{"path": "file1.txt", "category": "system"}]
sources = ["nexus.internal"]
# Execute
with patch("src.services.clean_release.preparation_service.CleanPolicyEngine") as MockEngine:
mock_engine_instance = MockEngine.return_value
mock_engine_instance.validate_policy.return_value.ok = True
mock_engine_instance.evaluate_candidate.return_value = (
[{"path": "file1.txt", "category": "system", "classification": "required-system", "reason": "system-core"}],
[]
)
result = prepare_candidate(repository, candidate_id, artifacts, sources, "operator-1")
# Verify
assert result["status"] == ReleaseCandidateStatus.PREPARED.value
assert candidate.status == ReleaseCandidateStatus.PREPARED
repository.save_manifest.assert_called_once()
repository.save_candidate.assert_called_with(candidate)
def test_prepare_candidate_with_violations():
# Setup
repository = MagicMock()
candidate_id = "cand-1"
candidate = _mock_candidate(candidate_id)
repository.get_candidate.return_value = candidate
repository.get_active_policy.return_value = _mock_policy()
repository.get_registry.return_value = _mock_registry()
artifacts = [{"path": "bad.txt", "category": "prohibited"}]
sources = []
# Execute
with patch("src.services.clean_release.preparation_service.CleanPolicyEngine") as MockEngine:
mock_engine_instance = MockEngine.return_value
mock_engine_instance.validate_policy.return_value.ok = True
mock_engine_instance.evaluate_candidate.return_value = (
[{"path": "bad.txt", "category": "prohibited", "classification": "excluded-prohibited", "reason": "test-data"}],
[{"category": "data-purity", "blocked_release": True}]
)
result = prepare_candidate(repository, candidate_id, artifacts, sources, "operator-1")
# Verify
assert result["status"] == ReleaseCandidateStatus.BLOCKED.value
assert candidate.status == ReleaseCandidateStatus.BLOCKED
assert len(result["violations"]) == 1
def test_prepare_candidate_not_found():
repository = MagicMock()
repository.get_candidate.return_value = None
with pytest.raises(ValueError, match="Candidate not found"):
prepare_candidate(repository, "non-existent", [], [], "op")
def test_prepare_candidate_no_active_policy():
repository = MagicMock()
repository.get_candidate.return_value = _mock_candidate("cand-1")
repository.get_active_policy.return_value = None
with pytest.raises(ValueError, match="Active clean policy not found"):
prepare_candidate(repository, "cand-1", [], [], "op")

View File

@@ -0,0 +1,27 @@
# [DEF:backend.tests.services.clean_release.test_stages:Module]
# @TIER: STANDARD
# @SEMANTICS: tests, clean-release, compliance, stages
# @PURPOSE: Validate final status derivation logic from stage results.
# @LAYER: Domain
# @RELATION: TESTS -> backend.src.services.clean_release.stages
from src.models.clean_release import CheckFinalStatus, CheckStageName, CheckStageResult, CheckStageStatus
from src.services.clean_release.stages import derive_final_status, MANDATORY_STAGE_ORDER
def test_derive_final_status_compliant():
results = [CheckStageResult(stage=s, status=CheckStageStatus.PASS, details="ok") for s in MANDATORY_STAGE_ORDER]
assert derive_final_status(results) == CheckFinalStatus.COMPLIANT
def test_derive_final_status_blocked():
results = [CheckStageResult(stage=s, status=CheckStageStatus.PASS, details="ok") for s in MANDATORY_STAGE_ORDER]
results[1].status = CheckStageStatus.FAIL
assert derive_final_status(results) == CheckFinalStatus.BLOCKED
def test_derive_final_status_failed_missing():
results = [CheckStageResult(stage=MANDATORY_STAGE_ORDER[0], status=CheckStageStatus.PASS, details="ok")]
assert derive_final_status(results) == CheckFinalStatus.FAILED
def test_derive_final_status_failed_skipped():
results = [CheckStageResult(stage=s, status=CheckStageStatus.PASS, details="ok") for s in MANDATORY_STAGE_ORDER]
results[2].status = CheckStageStatus.SKIPPED
assert derive_final_status(results) == CheckFinalStatus.FAILED

View File

@@ -1,144 +0,0 @@
# [DEF:backend.tests.services.clean_release.test_policy_engine:Module]
# @TIER: CRITICAL
# @SEMANTICS: tests, clean-release, policy-engine, deterministic
# @PURPOSE: Validate policy model contracts and deterministic classification prerequisites for US1.
# @LAYER: Domain
# @RELATION: VERIFIES -> backend.src.models.clean_release.CleanProfilePolicy
# @INVARIANT: Enterprise policy rejects invalid activation states.
import pytest
from datetime import datetime, timezone
from src.models.clean_release import CleanProfilePolicy, ProfileType
# [DEF:test_policy_enterprise_clean_valid:Function]
# @PURPOSE: Ensure valid enterprise policy payload is accepted.
# @PRE: Fixture-like payload contains prohibited categories and registry ref.
# @POST: Model is created with external_source_forbidden=True.
def test_policy_enterprise_clean_valid():
policy = CleanProfilePolicy(
policy_id="policy-enterprise-clean-v1",
policy_version="1.0.0",
active=True,
prohibited_artifact_categories=["test-data", "demo-data"],
required_system_categories=["system-init"],
external_source_forbidden=True,
internal_source_registry_ref="registry-internal-v1",
effective_from=datetime.now(timezone.utc),
profile=ProfileType.ENTERPRISE_CLEAN,
)
assert policy.external_source_forbidden is True
assert policy.prohibited_artifact_categories == ["test-data", "demo-data"]
# [/DEF:test_policy_enterprise_clean_valid:Function]
# [DEF:test_policy_missing_registry_fails:Function]
# @PURPOSE: Verify missing registry ref violates policy contract.
# @PRE: enterprise-clean policy payload has blank registry ref.
# @POST: Validation error is raised.
def test_policy_missing_registry_fails():
with pytest.raises(ValueError):
CleanProfilePolicy(
policy_id="policy-enterprise-clean-v1",
policy_version="1.0.0",
active=True,
prohibited_artifact_categories=["test-data"],
required_system_categories=["system-init"],
external_source_forbidden=True,
internal_source_registry_ref="",
effective_from=datetime.now(timezone.utc),
profile=ProfileType.ENTERPRISE_CLEAN,
)
# [/DEF:test_policy_missing_registry_fails:Function]
# [DEF:test_policy_empty_prohibited_categories_fails:Function]
# @PURPOSE: Verify enterprise policy cannot activate without prohibited categories.
# @PRE: enterprise-clean policy payload has empty prohibited categories.
# @POST: Validation error is raised.
def test_policy_empty_prohibited_categories_fails():
with pytest.raises(ValueError):
CleanProfilePolicy(
policy_id="policy-enterprise-clean-v1",
policy_version="1.0.0",
active=True,
prohibited_artifact_categories=[],
required_system_categories=["system-init"],
external_source_forbidden=True,
internal_source_registry_ref="registry-internal-v1",
effective_from=datetime.now(timezone.utc),
profile=ProfileType.ENTERPRISE_CLEAN,
)
# [/DEF:test_policy_empty_prohibited_categories_fails:Function]
# [DEF:test_policy_conflicting_external_forbidden_flag_fails:Function]
# @PURPOSE: Verify enterprise policy enforces external_source_forbidden=true.
# @PRE: enterprise-clean policy payload sets external_source_forbidden to false.
# @POST: Validation error is raised.
def test_policy_conflicting_external_forbidden_flag_fails():
with pytest.raises(ValueError):
CleanProfilePolicy(
policy_id="policy-enterprise-clean-v1",
policy_version="1.0.0",
active=True,
prohibited_artifact_categories=["test-data"],
required_system_categories=["system-init"],
external_source_forbidden=False,
internal_source_registry_ref="registry-internal-v1",
effective_from=datetime.now(timezone.utc),
profile=ProfileType.ENTERPRISE_CLEAN,
)
# [/DEF:test_policy_conflicting_external_forbidden_flag_fails:Function]
# [/DEF:backend.tests.services.clean_release.test_policy_engine:Module]
from src.models.clean_release import ResourceSourceRegistry, ResourceSourceEntry, RegistryStatus
from src.services.clean_release.policy_engine import CleanPolicyEngine
def _policy_enterprise_clean() -> CleanProfilePolicy:
return CleanProfilePolicy(
policy_id="policy-enterprise-clean-v1",
policy_version="1.0.0",
active=True,
prohibited_artifact_categories=["test-data"],
required_system_categories=["system-init"],
external_source_forbidden=True,
internal_source_registry_ref="registry-internal-v1",
effective_from=datetime.now(timezone.utc),
profile=ProfileType.ENTERPRISE_CLEAN,
)
def _registry() -> ResourceSourceRegistry:
return ResourceSourceRegistry(
registry_id="registry-internal-v1",
name="Internal",
entries=[ResourceSourceEntry(source_id="1", host="nexus.internal", protocol="https", purpose="pkg", enabled=True)],
updated_at=datetime.now(timezone.utc),
updated_by="tester",
)
# [DEF:test_policy_valid:Function]
# @PURPOSE: Validate policy valid scenario
def test_policy_valid():
engine = CleanPolicyEngine(_policy_enterprise_clean(), _registry())
res = engine.validate_policy()
assert res.ok is True
# [DEF:test_conflicting_registry:Function]
# @PURPOSE: Validate policy conflicting registry edge
def test_conflicting_registry():
reg = _registry()
reg.registry_id = "other-registry"
engine = CleanPolicyEngine(_policy_enterprise_clean(), reg)
res = engine.validate_policy()
assert res.ok is False
assert "Policy registry ref does not match provided registry" in res.blocking_reasons
# [DEF:test_external_endpoint:Function]
# @PURPOSE: Validate policy external endpoint edge
def test_external_endpoint():
engine = CleanPolicyEngine(_policy_enterprise_clean(), _registry())
res = engine.validate_resource_source("external.org")
assert res.ok is False
assert res.violation["category"] == "external-source"

View File

@@ -1,5 +1,5 @@
// [DEF:frontend.src.components.__tests__.task_log_viewer:Module] // [DEF:frontend.src.components.__tests__.task_log_viewer:Module]
// @TIER: CRITICAL // @TIER: STANDARD
// @SEMANTICS: tests, task-log, viewer, mount, components // @SEMANTICS: tests, task-log, viewer, mount, components
// @PURPOSE: Unit tests for TaskLogViewer component by mounting it and observing the DOM. // @PURPOSE: Unit tests for TaskLogViewer component by mounting it and observing the DOM.
// @LAYER: UI (Tests) // @LAYER: UI (Tests)

View File

@@ -48,7 +48,7 @@ describe('AssistantChatPanel integration contract', () => {
const source = fs.readFileSync(COMPONENT_PATH, 'utf-8'); const source = fs.readFileSync(COMPONENT_PATH, 'utf-8');
expect(source).toContain('<!-- [DEF' + ':AssistantChatPanel:Component] -->'); expect(source).toContain('<!-- [DEF' + ':AssistantChatPanel:Component] -->');
expect(source).toContain('@TIER: CRITICAL'); expect(source).toContain('@TIER' + ': CRITICAL');
expect(source).toContain('@UX_STATE: LoadingHistory'); expect(source).toContain('@UX_STATE: LoadingHistory');
expect(source).toContain('@UX_STATE: Sending'); expect(source).toContain('@UX_STATE: Sending');
expect(source).toContain('@UX_STATE: Error'); expect(source).toContain('@UX_STATE: Error');

View File

@@ -27,14 +27,12 @@
* @TEST_INVARIANT correct_iteration -> verifies: [renders_list, empty_list] * @TEST_INVARIANT correct_iteration -> verifies: [renders_list, empty_list]
*/ */
import { createEventDispatcher } from "svelte";
import ReportCard from "./ReportCard.svelte"; import ReportCard from "./ReportCard.svelte";
let { reports = [], selectedReportId = null } = $props(); let { reports = [], selectedReportId = null, onselect } = $props();
const dispatch = createEventDispatcher();
function handleSelect(event) { function handleSelect(event) {
dispatch("select", { report: event.detail.report }); if (onselect) onselect({ report: event.detail.report });
} }
</script> </script>

View File

@@ -2,7 +2,7 @@
* @vitest-environment jsdom * @vitest-environment jsdom
*/ */
// [DEF:frontend.src.lib.components.reports.__tests__.report_card.ux:Module] // [DEF:frontend.src.lib.components.reports.__tests__.report_card.ux:Module]
// @TIER: CRITICAL // @TIER: STANDARD
// @SEMANTICS: reports, ux-tests, card, states, recovery // @SEMANTICS: reports, ux-tests, card, states, recovery
// @PURPOSE: Test UX states and transitions for ReportCard component // @PURPOSE: Test UX states and transitions for ReportCard component
// @LAYER: UI // @LAYER: UI

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,10 @@
| `clean_release.report_builder` | `report_builder.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 | | `clean_release.report_builder` | `report_builder.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `clean_release.manifest_builder` | `manifest_builder.py` | STANDARD | ✅ Yes | N/A | N/A | N/A | | `clean_release.manifest_builder` | `manifest_builder.py` | STANDARD | ✅ Yes | N/A | N/A | N/A |
| `clean_release.source_isolation` | `source_isolation.py` | STANDARD | ✅ Yes | N/A | N/A | N/A | | `clean_release.source_isolation` | `source_isolation.py` | STANDARD | ✅ Yes | N/A | N/A | N/A |
| `api.routes.clean_release` | `clean_release.py` | STANDARD | ✅ Yes | N/A | N/A | N/A | | `clean_release.preparation_service` | `preparation_service.py` | STANDARD | ✅ Yes | 1/1 | 2/2 | 1/1 |
| `clean_release.audit_service` | `audit_service.py` | STANDARD | ✅ Yes | N/A | N/A | 1/1 |
| `clean_release.stages` | `stages.py` | STANDARD | ✅ Yes | N/A | 3/3 | N/A |
| `api.routes.clean_release` | `clean_release.py` | STANDARD | ✅ Yes | 1/1 | 2/2 | 1/1 |
| `api.routes.tasks.get_task_logs` | `tasks.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 | | `api.routes.tasks.get_task_logs` | `tasks.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `models.clean_release` | `clean_release.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 | | `models.clean_release` | `clean_release.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `frontend.assistant_chat.integration` | `assistant_chat.integration.test.js` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 | | `frontend.assistant_chat.integration` | `assistant_chat.integration.test.js` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |