122 lines
5.6 KiB
Python
122 lines
5.6 KiB
Python
# [DEF:clean_release_facade:Module]
|
|
# @TIER: STANDARD
|
|
# @PURPOSE: Unified entry point for clean release operations.
|
|
# @LAYER: Application
|
|
|
|
from typing import List, Optional
|
|
from backend.src.services.clean_release.repositories import (
|
|
CandidateRepository, ArtifactRepository, ManifestRepository,
|
|
PolicyRepository, ComplianceRepository, ReportRepository,
|
|
ApprovalRepository, PublicationRepository, AuditRepository
|
|
)
|
|
from backend.src.services.clean_release.dto import (
|
|
CandidateDTO, ArtifactDTO, ManifestDTO, ComplianceRunDTO,
|
|
ReportDTO, CandidateOverviewDTO
|
|
)
|
|
from backend.src.services.clean_release.enums import CandidateStatus, RunStatus, ComplianceDecision
|
|
from backend.src.models.clean_release import CleanPolicySnapshot, SourceRegistrySnapshot
|
|
from backend.src.core.logger import belief_scope
|
|
from backend.src.core.config_manager import ConfigManager
|
|
|
|
class CleanReleaseFacade:
|
|
"""
|
|
@PURPOSE: Orchestrates repositories and services to provide a clean API for UI/CLI.
|
|
"""
|
|
def __init__(
|
|
self,
|
|
candidate_repo: CandidateRepository,
|
|
artifact_repo: ArtifactRepository,
|
|
manifest_repo: ManifestRepository,
|
|
policy_repo: PolicyRepository,
|
|
compliance_repo: ComplianceRepository,
|
|
report_repo: ReportRepository,
|
|
approval_repo: ApprovalRepository,
|
|
publication_repo: PublicationRepository,
|
|
audit_repo: AuditRepository,
|
|
config_manager: ConfigManager
|
|
):
|
|
self.candidate_repo = candidate_repo
|
|
self.artifact_repo = artifact_repo
|
|
self.manifest_repo = manifest_repo
|
|
self.policy_repo = policy_repo
|
|
self.compliance_repo = compliance_repo
|
|
self.report_repo = report_repo
|
|
self.approval_repo = approval_repo
|
|
self.publication_repo = publication_repo
|
|
self.audit_repo = audit_repo
|
|
self.config_manager = config_manager
|
|
|
|
def resolve_active_policy_snapshot(self) -> Optional[CleanPolicySnapshot]:
|
|
"""
|
|
@PURPOSE: Resolve the active policy snapshot based on ConfigManager.
|
|
"""
|
|
with belief_scope("CleanReleaseFacade.resolve_active_policy_snapshot"):
|
|
config = self.config_manager.get_config()
|
|
policy_id = config.settings.clean_release.active_policy_id
|
|
if not policy_id:
|
|
return None
|
|
return self.policy_repo.get_policy_snapshot(policy_id)
|
|
|
|
def resolve_active_registry_snapshot(self) -> Optional[SourceRegistrySnapshot]:
|
|
"""
|
|
@PURPOSE: Resolve the active registry snapshot based on ConfigManager.
|
|
"""
|
|
with belief_scope("CleanReleaseFacade.resolve_active_registry_snapshot"):
|
|
config = self.config_manager.get_config()
|
|
registry_id = config.settings.clean_release.active_registry_id
|
|
if not registry_id:
|
|
return None
|
|
return self.policy_repo.get_registry_snapshot(registry_id)
|
|
|
|
def get_candidate_overview(self, candidate_id: str) -> Optional[CandidateOverviewDTO]:
|
|
"""
|
|
@PURPOSE: Build a comprehensive overview for a candidate.
|
|
"""
|
|
with belief_scope("CleanReleaseFacade.get_candidate_overview"):
|
|
candidate = self.candidate_repo.get_by_id(candidate_id)
|
|
if not candidate:
|
|
return None
|
|
|
|
manifest = self.manifest_repo.get_latest_for_candidate(candidate_id)
|
|
runs = self.compliance_repo.list_runs_by_candidate(candidate_id)
|
|
latest_run = runs[-1] if runs else None
|
|
|
|
report = None
|
|
if latest_run:
|
|
report = self.report_repo.get_by_run(latest_run.id)
|
|
|
|
approval = self.approval_repo.get_latest_for_candidate(candidate_id)
|
|
publication = self.publication_repo.get_latest_for_candidate(candidate_id)
|
|
|
|
active_policy = self.resolve_active_policy_snapshot()
|
|
active_registry = self.resolve_active_registry_snapshot()
|
|
|
|
return CandidateOverviewDTO(
|
|
candidate_id=candidate.id,
|
|
version=candidate.version,
|
|
source_snapshot_ref=candidate.source_snapshot_ref,
|
|
status=CandidateStatus(candidate.status),
|
|
latest_manifest_id=manifest.id if manifest else None,
|
|
latest_manifest_digest=manifest.manifest_digest if manifest else None,
|
|
latest_run_id=latest_run.id if latest_run else None,
|
|
latest_run_status=RunStatus(latest_run.status) if latest_run else None,
|
|
latest_report_id=report.id if report else None,
|
|
latest_report_final_status=ComplianceDecision(report.final_status) if report else None,
|
|
latest_policy_snapshot_id=active_policy.id if active_policy else None,
|
|
latest_policy_version=active_policy.policy_version if active_policy else None,
|
|
latest_registry_snapshot_id=active_registry.id if active_registry else None,
|
|
latest_registry_version=active_registry.registry_version if active_registry else None,
|
|
latest_approval_decision=approval.decision if approval else None,
|
|
latest_publication_id=publication.id if publication else None,
|
|
latest_publication_status=publication.status if publication else None
|
|
)
|
|
|
|
def list_candidates(self) -> List[CandidateOverviewDTO]:
|
|
"""
|
|
@PURPOSE: List all candidates with their current status.
|
|
"""
|
|
with belief_scope("CleanReleaseFacade.list_candidates"):
|
|
candidates = self.candidate_repo.list_all()
|
|
return [self.get_candidate_overview(c.id) for c in candidates]
|
|
|
|
# [/DEF:clean_release_facade:Module] |