# [DEF:backend.src.services.clean_release.repository:Module] # @TIER: STANDARD # @SEMANTICS: clean-release, repository, persistence, in-memory # @PURPOSE: Provide repository adapter for clean release entities with deterministic access methods. # @LAYER: Infra # @RELATION: DEPENDS_ON -> backend.src.models.clean_release # @INVARIANT: Repository operations are side-effect free outside explicit save/update calls. from __future__ import annotations from dataclasses import dataclass, field from typing import Any, Dict, List, Optional from ...models.clean_release import ( CleanPolicySnapshot, ComplianceRun, ComplianceReport, ComplianceStageRun, ComplianceViolation, DistributionManifest, ReleaseCandidate, SourceRegistrySnapshot, ) # [DEF:CleanReleaseRepository:Class] # @PURPOSE: Data access object for clean release lifecycle. @dataclass class CleanReleaseRepository: candidates: Dict[str, ReleaseCandidate] = field(default_factory=dict) policies: Dict[str, CleanPolicySnapshot] = field(default_factory=dict) registries: Dict[str, SourceRegistrySnapshot] = field(default_factory=dict) artifacts: Dict[str, object] = field(default_factory=dict) manifests: Dict[str, DistributionManifest] = field(default_factory=dict) check_runs: Dict[str, ComplianceRun] = field(default_factory=dict) stage_runs: Dict[str, ComplianceStageRun] = field(default_factory=dict) reports: Dict[str, ComplianceReport] = field(default_factory=dict) violations: Dict[str, ComplianceViolation] = field(default_factory=dict) audit_events: List[Dict[str, Any]] = field(default_factory=list) def save_candidate(self, candidate: ReleaseCandidate) -> ReleaseCandidate: self.candidates[candidate.id] = candidate return candidate def get_candidate(self, candidate_id: str) -> Optional[ReleaseCandidate]: return self.candidates.get(candidate_id) def save_policy(self, policy: CleanPolicySnapshot) -> CleanPolicySnapshot: self.policies[policy.id] = policy return policy def get_policy(self, policy_id: str) -> Optional[CleanPolicySnapshot]: return self.policies.get(policy_id) def get_active_policy(self) -> Optional[CleanPolicySnapshot]: # In-memory repo doesn't track 'active' flag on snapshot, # this should be resolved by facade using ConfigManager. return next(iter(self.policies.values()), None) def save_registry(self, registry: SourceRegistrySnapshot) -> SourceRegistrySnapshot: self.registries[registry.id] = registry return registry def get_registry(self, registry_id: str) -> Optional[SourceRegistrySnapshot]: return self.registries.get(registry_id) def save_artifact(self, artifact) -> object: self.artifacts[artifact.id] = artifact return artifact def get_artifacts_by_candidate(self, candidate_id: str) -> List[object]: return [a for a in self.artifacts.values() if a.candidate_id == candidate_id] def save_manifest(self, manifest: DistributionManifest) -> DistributionManifest: self.manifests[manifest.id] = manifest return manifest def get_manifest(self, manifest_id: str) -> Optional[DistributionManifest]: return self.manifests.get(manifest_id) def save_distribution_manifest(self, manifest: DistributionManifest) -> DistributionManifest: return self.save_manifest(manifest) def get_distribution_manifest(self, manifest_id: str) -> Optional[DistributionManifest]: return self.get_manifest(manifest_id) def save_check_run(self, check_run: ComplianceRun) -> ComplianceRun: self.check_runs[check_run.id] = check_run return check_run def get_check_run(self, check_run_id: str) -> Optional[ComplianceRun]: return self.check_runs.get(check_run_id) def save_compliance_run(self, run: ComplianceRun) -> ComplianceRun: return self.save_check_run(run) def get_compliance_run(self, run_id: str) -> Optional[ComplianceRun]: return self.get_check_run(run_id) def save_report(self, report: ComplianceReport) -> ComplianceReport: existing = self.reports.get(report.id) if existing is not None: raise ValueError(f"immutable report snapshot already exists for id={report.id}") self.reports[report.id] = report return report def get_report(self, report_id: str) -> Optional[ComplianceReport]: return self.reports.get(report_id) def save_violation(self, violation: ComplianceViolation) -> ComplianceViolation: self.violations[violation.id] = violation return violation def get_violations_by_run(self, run_id: str) -> List[ComplianceViolation]: return [v for v in self.violations.values() if v.run_id == run_id] def get_manifests_by_candidate(self, candidate_id: str) -> List[DistributionManifest]: return [m for m in self.manifests.values() if m.candidate_id == candidate_id] def clear_history(self) -> None: self.check_runs.clear() self.reports.clear() self.violations.clear() # [/DEF:CleanReleaseRepository:Class] # [/DEF:backend.src.services.clean_release.repository:Module]