""" Repository Interfaces - Protocol 定義 ====================================== Phase 16 R3: Repository 層 Protocol 介面 設計原則: - 使用 Python Protocol 實現 DI - Service 層只依賴 Protocol,不依賴具體實作 - 便於測試 (可注入 Mock Repository) 版本: v1.0 建立: 2026-03-26 (台北時區) 建立者: Claude Code (Phase 16 架構重構) """ from datetime import datetime from typing import Protocol, runtime_checkable from uuid import UUID from src.models.approval import ApprovalRequest, ApprovalRequestCreate, ApprovalStatus from src.models.incident import Incident from src.models.knowledge import ( EntryStatus, EntryType, KnowledgeEntry, KnowledgeEntryCreate, ) from src.models.playbook import ( Playbook, PlaybookStatus, SymptomPattern, ) @runtime_checkable class IApprovalRepository(Protocol): """ Approval Repository Protocol 職責: ApprovalRecord CRUD 操作 實作: ApprovalDBRepository (PostgreSQL) """ async def create(self, data: dict) -> ApprovalRequest: """ 建立新的 Approval Phase 22 P2: 簽名修正為 dict (與實作一致) 2026-03-31 Claude Code (首席架構師 P2 修復) Args: data: ApprovalRecord 建立資料 dict Returns: ApprovalRequest """ ... async def get_by_id(self, approval_id: UUID) -> ApprovalRequest | None: """根據 ID 取得 Approval""" ... async def get_pending(self) -> list[ApprovalRequest]: """取得所有待審核的 Approval""" ... async def update_status( self, approval_id: UUID, status: ApprovalStatus, actor: str | None = None, ) -> ApprovalRequest | None: """更新 Approval 狀態""" ... async def add_signature( self, approval_id: UUID, signer: str, decision: str, comment: str | None = None, ) -> ApprovalRequest | None: """新增簽核""" ... async def find_by_fingerprint( self, fingerprint: str, ) -> ApprovalRequest | None: """ 根據指紋查找 Approval (告警收斂用) Phase 22 P2: 補齊缺失 Protocol 方法 2026-03-31 Claude Code (首席架構師 P2 修復) """ ... async def increment_hit_count( self, approval_id: UUID, ) -> ApprovalRequest | None: """ 增加 hit_count (告警收斂用) Phase 22 P2: 補齊缺失 Protocol 方法 2026-03-31 Claude Code (首席架構師 P2 修復) """ ... @runtime_checkable class IIncidentRepository(Protocol): """ Incident Repository Protocol 職責: IncidentRecord CRUD 操作 實作: IncidentDBRepository (PostgreSQL) """ async def create(self, incident: Incident) -> Incident: """建立新的 Incident""" ... async def get_by_id(self, incident_id: str) -> Incident | None: """根據 ID 取得 Incident""" ... async def get_active( self, *, project_id: str | None = None, ) -> list[Incident]: """取得所有活躍的 Incident""" ... async def update(self, incident: Incident) -> Incident | None: """更新 Incident""" ... async def upsert(self, incident: Incident) -> bool: """Upsert Incident (存在則更新,不存在則建立)""" ... @runtime_checkable class ITimelineRepository(Protocol): """ Timeline Repository Protocol 職責: TimelineEvent CRUD 操作 實作: TimelineDBRepository (PostgreSQL) """ async def add_event( self, approval_id: UUID, event_type: str, actor: str, details: dict | None = None, ) -> bool: """新增 Timeline 事件""" ... async def get_events( self, approval_id: UUID, limit: int = 100, ) -> list[dict]: """取得 Approval 的 Timeline 事件""" ... async def get_recent_events( self, limit: int = 50, hours: int = 24, ) -> list[dict]: """取得最近的 Timeline 事件""" ... @runtime_checkable class IMetricsRepository(Protocol): """ Metrics Repository Protocol 職責: Metrics 相關 DB 查詢 (AI Success Rate) 實作: MetricsDBRepository (PostgreSQL) 版本: v1.0 建立: 2026-03-26 (台北時區) 建立者: Claude Code (Phase 17 技術債修復) """ async def get_ai_success_rate( self, hours: int = 24, ) -> tuple[float, int, int]: """ 計算 AI 提案成功執行率 Args: hours: 統計時間範圍 (小時) Returns: (success_rate_percent, executed_count, total_count) """ ... async def get_ai_success_trend( self, hours: int = 24, points: int = 10, ) -> list[float]: """ 取得 AI 成功率趨勢 (Sparkline 用) Args: hours: 統計時間範圍 (小時) points: 趨勢點數量 Returns: list[float]: 每小時成功率列表 (由舊到新) """ ... @runtime_checkable class IKnowledgeRepository(Protocol): """ Knowledge Repository Protocol 職責: KnowledgeEntry CRUD 操作 (PostgreSQL) 實作: KnowledgeDBRepository 建立: 2026-04-02 (台北時區) 建立者: Claude Code (Knowledge Base Phase 1) """ async def create(self, data: KnowledgeEntryCreate) -> KnowledgeEntry: """建立知識條目""" ... async def get_by_id(self, entry_id: str) -> KnowledgeEntry | None: """根據 ID 取得知識條目""" ... async def update(self, entry_id: str, data: dict) -> KnowledgeEntry | None: """更新知識條目""" ... async def delete(self, entry_id: str) -> bool: """軟刪除知識條目 (status → archived)""" ... async def list_entries( self, category: str | None = None, entry_type: EntryType | None = None, status: EntryStatus | None = None, tags: list[str] | None = None, q: str | None = None, limit: int = 20, offset: int = 0, ) -> tuple[list[KnowledgeEntry], int]: """列出知識條目 (支援篩選)""" ... async def get_categories(self) -> list[tuple[str, int]]: """取得分類統計 [(category, count)]""" ... async def get_asset_taxonomy_counts(self) -> list[tuple[str, int]]: """取得 AI 自動化資產維度統計 [(taxonomy_key, count)]""" ... async def search(self, query: str, limit: int = 20) -> list[KnowledgeEntry]: """關鍵字搜尋 (title + content + tags)""" ... async def increment_view_count(self, entry_id: str) -> bool: """view_count +1""" ... async def save_embedding(self, entry_id: str, embedding: list[float]) -> bool: """儲存向量 embedding (1024 維, pgvector, bge-m3:latest)""" ... async def semantic_search( self, query_embedding: list[float], limit: int = 10, threshold: float = 0.5, ) -> list[tuple["KnowledgeEntry", float]]: """語意搜尋 — cosine similarity, 回傳 (entry, score) 降序""" ... async def list_unembedded_entries( self, ) -> list[tuple[str, str, str]]: """列出尚未產生 embedding 的條目 [(id, title, content)]""" ... @runtime_checkable class IPlaybookRepository(Protocol): """ Playbook Repository Protocol 職責: Playbook CRUD 操作 (PostgreSQL + Redis 雙層) 實作: PlaybookRepository 版本: v1.0 建立: 2026-03-26 (台北時區) 建立者: Claude Code (#7 Playbook 萃取) """ async def create(self, playbook: Playbook) -> Playbook: """建立新的 Playbook""" ... async def get_by_id(self, playbook_id: str) -> Playbook | None: """根據 ID 取得 Playbook""" ... async def update(self, playbook: Playbook) -> Playbook | None: """更新 Playbook""" ... async def delete(self, playbook_id: str) -> bool: """刪除 Playbook (軟刪除 → DEPRECATED)""" ... async def list_playbooks( self, status: PlaybookStatus | None = None, tags: list[str] | None = None, limit: int = 20, offset: int = 0, ) -> tuple[list[Playbook], int]: """ 列出 Playbooks Returns: (items, total_count) """ ... async def find_by_symptoms( self, symptoms: SymptomPattern, top_k: int = 5, min_similarity: float = 0.5, ) -> list[tuple[Playbook, float]]: """ 根據症狀模式找相似 Playbook Returns: list[(Playbook, similarity_score)] """ ... async def update_stats( self, playbook_id: str, success: bool, ) -> bool: """更新執行統計""" ... async def find_by_source_incident( self, incident_id: str, ) -> list[Playbook]: """ 根據來源 Incident ID 找 Playbook 2026-03-30 Claude Code: Learning Service 信心度調整用 尋找 source_incident_ids 包含此 incident_id 的 Playbooks """ ... async def adjust_confidence( self, playbook_id: str, delta: float, reason: str, ) -> Playbook | None: """ 調整 Playbook 信心度 2026-03-30 Claude Code: Learning Service 信心度調整用 Args: playbook_id: Playbook ID delta: 調整量 (+/- 0.0~1.0) reason: 調整原因 (審計用) Returns: 更新後的 Playbook,或 None (如果不存在) """ ... @runtime_checkable class ILearningRepository(Protocol): """ Learning Repository Protocol 職責: 學習數據持久化 (Redis) 實作: LearningRepository 版本: v1.0 建立: 2026-03-29 (台北時區) 建立者: Claude Code (Phase D-G P0 修正) 設計原則: - Service 層不直接存取 Redis - 透過 Repository 進行資料存取 - 符合 leWOOOgo 積木化原則 """ async def record_repair( self, anomaly_key: str, repair_action: str, success: bool, root_cause: str | None = None, fix_description: str | None = None, execution_time_seconds: float | None = None, ) -> bool: """記錄修復結果""" ... async def get_repair_stats( self, anomaly_key: str, repair_action: str, ) -> dict: """取得修復統計 (成功率、執行次數)""" ... async def get_all_repair_stats( self, anomaly_key: str, ) -> dict[str, dict]: """取得所有修復動作的統計""" ... async def get_repair_history( self, anomaly_key: str, repair_action: str, limit: int = 20, ) -> list[dict]: """取得修復歷史記錄""" ... async def get_learning_summary( self, anomaly_key: str, ) -> dict: """取得學習摘要""" ... @runtime_checkable class IEmbeddingCacheRepository(Protocol): """ Embedding Cache Repository Protocol 職責: Playbook 向量快取 (Redis) 實作: EmbeddingCacheRepository 2026-03-27 ogt: 模組化改造 (P1 違規修復) """ async def store( self, playbook_id: str, embedding: list[float], metadata: dict | None = None, ) -> bool: """儲存 Playbook 向量""" ... async def get(self, playbook_id: str) -> list[float] | None: """取得 Playbook 向量""" ... async def get_all(self) -> dict[str, list[float]]: """取得所有 Playbook 向量""" ... async def remove(self, playbook_id: str) -> bool: """移除 Playbook 向量""" ... @runtime_checkable class IK8sRepository(Protocol): """ K8s Repository Protocol 職責: K8s API 操作 (Pods/Deployments/Events) 實作: K8sRepository (kubernetes_asyncio) 版本: v1.0 建立: 2026-03-30 (台北時區) 建立者: Claude Code (首席架構師 P1 改進) 設計原則: - Service 層不直接呼叫 kubernetes_asyncio - 透過 Repository 進行 K8s 操作 - 符合 leWOOOgo 積木化原則 """ async def list_pods( self, namespace: str = "awoooi", ) -> list[dict]: """ 列出 Namespace 下的 Pods Returns: list[{name, phase, ready, restarts, age}] """ ... async def list_deployments( self, namespace: str = "awoooi", ) -> list[dict]: """ 列出 Namespace 下的 Deployments Returns: list[{name, ready_replicas, replicas, available}] """ ... async def get_pod_status_summary( self, namespace: str = "awoooi", ) -> dict: """ 取得 Pod 狀態摘要 Returns: {total, running, pending, failed, problem_pods: [...]} """ ... async def is_available(self) -> bool: """ 檢查 K8s API 是否可用 Returns: True 如果 K8s 連線正常 """ ... # ============================================================================= # Phase 18: Failure Auto-Repair Loop Protocols # ============================================================================= # 2026-03-31 Claude Code (統帥批准) # ============================================================================= @runtime_checkable class IFailureWatcher(Protocol): """ Failure Watcher Protocol 職責: 監聽失敗事件並觸發修復流程 實作: FailureWatcherService 版本: v1.0 建立: 2026-03-31 (台北時區) 建立者: Claude Code (Phase 18 失敗自動修復) """ async def process_failure( self, audit_log_id: str, failure_data: dict, ) -> dict: """ 處理單一失敗事件 Args: audit_log_id: AuditLog ID failure_data: 失敗詳情 Returns: { "repair_attempted": bool, "repair_result": str | None, "risk_level": str, # LOW/MEDIUM/CRITICAL "next_action": str, # auto_repair/await_approval/escalate } """ ... async def analyze_failure( self, error_message: str, operation_type: str, target_resource: str, ) -> dict: """ AI 分析失敗原因 Args: error_message: 錯誤訊息 operation_type: 操作類型 target_resource: 目標資源 Returns: { "classification": str, # TIMEOUT/K8S_ERROR/NETWORK_ERROR/PERMISSION_DENIED "root_cause": str, "suggested_repair": str, "risk_level": str, "confidence": float, } """ ... async def execute_auto_repair( self, audit_log_id: str, repair_strategy: str, failure_data: dict | None = None, ) -> tuple[bool, str]: """ 執行自動修復 (僅限 LOW 風險) Phase 18.3: K8s Executor 整合 2026-03-31 Claude Code (統帥批准) Args: audit_log_id: 原始失敗的 AuditLog ID repair_strategy: 修復策略 failure_data: 失敗詳情 (含 target_resource, namespace) Returns: (success, result_message) """ ... @runtime_checkable class ITrustRepository(Protocol): """ Trust Repository Protocol 職責: TrustRecord 持久化 (PostgreSQL) 實作: TrustRepository ADR-088: TrustScoreManager 持久化層 2026-04-17 ogt + Claude Sonnet 4.6(亞太): Phase 4 信任持久化 """ async def upsert( self, action_pattern: str, score: int, total_approvals: int, total_rejections: int, last_approval_by: str | None = None, last_approval_at: datetime | None = None, last_rejection_by: str | None = None, last_rejection_at: datetime | None = None, ) -> bool: """INSERT or UPDATE trust record (upsert by action_pattern)""" ... async def load_all(self) -> list[dict]: """ 載入所有 trust records 供啟動 warm-up Returns: list[{action_pattern, score, total_approvals, total_rejections, last_approval_by, last_approval_at, last_rejection_by, last_rejection_at}] """ ...