# mypy: disable-error-code="arg-type,assignment,union-attr,no-any-return,attr-defined,index,call-overload,type-arg,var-annotated,misc,call-arg,return-value" """ Vendor compliance extra entities — Findings, Control Instances, and Controls Library CRUD. Phase 1 Step 4: extracted from ``compliance.api.vendor_compliance_routes``. Shares helpers with ``compliance.services.vendor_compliance_service`` and row converters from ``compliance.services.vendor_compliance_sub_service``. """ import json import uuid from datetime import datetime, timezone from typing import Optional from sqlalchemy import text from sqlalchemy.orm import Session from compliance.domain import NotFoundError from compliance.services.vendor_compliance_service import ( DEFAULT_TENANT_ID, _get, _ok, _to_snake, _ts, ) from compliance.services.vendor_compliance_sub_service import ( _control_instance_to_response, _finding_to_response, ) # ============================================================================ # FindingService # ============================================================================ class FindingService: """Vendor findings CRUD.""" def __init__(self, db: Session) -> None: self._db = db def list_findings( self, tenant_id: Optional[str] = None, vendor_id: Optional[str] = None, severity: Optional[str] = None, status: Optional[str] = None, skip: int = 0, limit: int = 100, ) -> dict: tid = tenant_id or DEFAULT_TENANT_ID where = ["tenant_id = :tid"] params: dict = {"tid": tid} if vendor_id: where.append("vendor_id = :vendor_id") params["vendor_id"] = vendor_id if severity: where.append("severity = :severity") params["severity"] = severity if status: where.append("status = :status") params["status"] = status where_clause = " AND ".join(where) params["lim"] = limit params["off"] = skip rows = self._db.execute(text(f""" SELECT * FROM vendor_findings WHERE {where_clause} ORDER BY created_at DESC LIMIT :lim OFFSET :off """), params).fetchall() return _ok([_finding_to_response(r) for r in rows]) def get_finding(self, finding_id: str) -> dict: row = self._db.execute( text("SELECT * FROM vendor_findings WHERE id = :id"), {"id": finding_id}, ).fetchone() if not row: raise NotFoundError("Finding not found") return _ok(_finding_to_response(row)) def create_finding(self, body: dict) -> dict: data = _to_snake(body) fid = str(uuid.uuid4()) tid = data.get("tenant_id", DEFAULT_TENANT_ID) now = datetime.now(timezone.utc).isoformat() self._db.execute(text(""" INSERT INTO vendor_findings ( id, tenant_id, vendor_id, contract_id, finding_type, category, severity, title, description, recommendation, citations, status, assignee, due_date, created_at, updated_at, created_by ) VALUES ( :id, :tenant_id, :vendor_id, :contract_id, :finding_type, :category, :severity, :title, :description, :recommendation, CAST(:citations AS jsonb), :status, :assignee, :due_date, :created_at, :updated_at, :created_by ) """), { "id": fid, "tenant_id": tid, "vendor_id": data.get("vendor_id", ""), "contract_id": data.get("contract_id"), "finding_type": data.get("finding_type", "UNKNOWN"), "category": data.get("category", ""), "severity": data.get("severity", "MEDIUM"), "title": data.get("title", ""), "description": data.get("description", ""), "recommendation": data.get("recommendation", ""), "citations": json.dumps(data.get("citations", [])), "status": data.get("status", "OPEN"), "assignee": data.get("assignee", ""), "due_date": data.get("due_date"), "created_at": now, "updated_at": now, "created_by": data.get("created_by", "system"), }) self._db.commit() row = self._db.execute( text("SELECT * FROM vendor_findings WHERE id = :id"), {"id": fid}, ).fetchone() return _ok(_finding_to_response(row)) def update_finding(self, finding_id: str, body: dict) -> dict: existing = self._db.execute( text("SELECT id FROM vendor_findings WHERE id = :id"), {"id": finding_id}, ).fetchone() if not existing: raise NotFoundError("Finding not found") data = _to_snake(body) now = datetime.now(timezone.utc).isoformat() allowed = [ "vendor_id", "contract_id", "finding_type", "category", "severity", "title", "description", "recommendation", "status", "assignee", "due_date", "resolution", "resolved_at", "resolved_by", ] jsonb_fields = ["citations"] sets = ["updated_at = :updated_at"] params: dict = {"id": finding_id, "updated_at": now} for col in allowed: if col in data: sets.append(f"{col} = :{col}") params[col] = data[col] for col in jsonb_fields: if col in data: sets.append(f"{col} = CAST(:{col} AS jsonb)") params[col] = json.dumps(data[col]) self._db.execute( text( f"UPDATE vendor_findings SET {', '.join(sets)} WHERE id = :id", ), params, ) self._db.commit() row = self._db.execute( text("SELECT * FROM vendor_findings WHERE id = :id"), {"id": finding_id}, ).fetchone() return _ok(_finding_to_response(row)) def delete_finding(self, finding_id: str) -> dict: result = self._db.execute( text("DELETE FROM vendor_findings WHERE id = :id"), {"id": finding_id}, ) self._db.commit() if result.rowcount == 0: raise NotFoundError("Finding not found") return _ok({"deleted": True}) # ============================================================================ # ControlInstanceService # ============================================================================ class ControlInstanceService: """Vendor control instances CRUD.""" def __init__(self, db: Session) -> None: self._db = db def list_instances( self, tenant_id: Optional[str] = None, vendor_id: Optional[str] = None, skip: int = 0, limit: int = 100, ) -> dict: tid = tenant_id or DEFAULT_TENANT_ID where = ["tenant_id = :tid"] params: dict = {"tid": tid} if vendor_id: where.append("vendor_id = :vendor_id") params["vendor_id"] = vendor_id where_clause = " AND ".join(where) params["lim"] = limit params["off"] = skip rows = self._db.execute(text(f""" SELECT * FROM vendor_control_instances WHERE {where_clause} ORDER BY created_at DESC LIMIT :lim OFFSET :off """), params).fetchall() return _ok([_control_instance_to_response(r) for r in rows]) def get_instance(self, instance_id: str) -> dict: row = self._db.execute( text("SELECT * FROM vendor_control_instances WHERE id = :id"), {"id": instance_id}, ).fetchone() if not row: raise NotFoundError("Control instance not found") return _ok(_control_instance_to_response(row)) def create_instance(self, body: dict) -> dict: data = _to_snake(body) ciid = str(uuid.uuid4()) tid = data.get("tenant_id", DEFAULT_TENANT_ID) now = datetime.now(timezone.utc).isoformat() self._db.execute(text(""" INSERT INTO vendor_control_instances ( id, tenant_id, vendor_id, control_id, control_domain, status, evidence_ids, notes, last_assessed_at, last_assessed_by, next_assessment_date, created_at, updated_at, created_by ) VALUES ( :id, :tenant_id, :vendor_id, :control_id, :control_domain, :status, CAST(:evidence_ids AS jsonb), :notes, :last_assessed_at, :last_assessed_by, :next_assessment_date, :created_at, :updated_at, :created_by ) """), { "id": ciid, "tenant_id": tid, "vendor_id": data.get("vendor_id", ""), "control_id": data.get("control_id", ""), "control_domain": data.get("control_domain", ""), "status": data.get("status", "PLANNED"), "evidence_ids": json.dumps(data.get("evidence_ids", [])), "notes": data.get("notes", ""), "last_assessed_at": data.get("last_assessed_at"), "last_assessed_by": data.get("last_assessed_by", ""), "next_assessment_date": data.get("next_assessment_date"), "created_at": now, "updated_at": now, "created_by": data.get("created_by", "system"), }) self._db.commit() row = self._db.execute( text("SELECT * FROM vendor_control_instances WHERE id = :id"), {"id": ciid}, ).fetchone() return _ok(_control_instance_to_response(row)) def update_instance(self, instance_id: str, body: dict) -> dict: existing = self._db.execute( text("SELECT id FROM vendor_control_instances WHERE id = :id"), {"id": instance_id}, ).fetchone() if not existing: raise NotFoundError("Control instance not found") data = _to_snake(body) now = datetime.now(timezone.utc).isoformat() allowed = [ "vendor_id", "control_id", "control_domain", "status", "notes", "last_assessed_at", "last_assessed_by", "next_assessment_date", ] jsonb_fields = ["evidence_ids"] sets = ["updated_at = :updated_at"] params: dict = {"id": instance_id, "updated_at": now} for col in allowed: if col in data: sets.append(f"{col} = :{col}") params[col] = data[col] for col in jsonb_fields: if col in data: sets.append(f"{col} = CAST(:{col} AS jsonb)") params[col] = json.dumps(data[col]) self._db.execute(text( f"UPDATE vendor_control_instances SET {', '.join(sets)} " f"WHERE id = :id", ), params) self._db.commit() row = self._db.execute( text("SELECT * FROM vendor_control_instances WHERE id = :id"), {"id": instance_id}, ).fetchone() return _ok(_control_instance_to_response(row)) def delete_instance(self, instance_id: str) -> dict: result = self._db.execute( text("DELETE FROM vendor_control_instances WHERE id = :id"), {"id": instance_id}, ) self._db.commit() if result.rowcount == 0: raise NotFoundError("Control instance not found") return _ok({"deleted": True}) # ============================================================================ # ControlsLibraryService # ============================================================================ class ControlsLibraryService: """Controls library (vendor_compliance_controls catalog).""" def __init__(self, db: Session) -> None: self._db = db def list_controls( self, tenant_id: Optional[str] = None, domain: Optional[str] = None, ) -> dict: tid = tenant_id or DEFAULT_TENANT_ID where = ["tenant_id = :tid"] params: dict = {"tid": tid} if domain: where.append("domain = :domain") params["domain"] = domain where_clause = " AND ".join(where) rows = self._db.execute(text(f""" SELECT * FROM vendor_compliance_controls WHERE {where_clause} ORDER BY domain, control_code """), params).fetchall() items = [] for r in rows: items.append({ "id": str(r["id"]), "tenantId": r["tenant_id"], "domain": _get(r, "domain", ""), "controlCode": _get(r, "control_code", ""), "title": _get(r, "title", ""), "description": _get(r, "description", ""), "createdAt": _ts(r["created_at"]), }) return _ok(items) def create_control(self, body: dict) -> dict: cid = str(uuid.uuid4()) tid = body.get( "tenantId", body.get("tenant_id", DEFAULT_TENANT_ID), ) now = datetime.now(timezone.utc).isoformat() self._db.execute(text(""" INSERT INTO vendor_compliance_controls ( id, tenant_id, domain, control_code, title, description, created_at ) VALUES ( :id, :tenant_id, :domain, :control_code, :title, :description, :created_at ) """), { "id": cid, "tenant_id": tid, "domain": body.get("domain", ""), "control_code": body.get( "controlCode", body.get("control_code", ""), ), "title": body.get("title", ""), "description": body.get("description", ""), "created_at": now, }) self._db.commit() return _ok({ "id": cid, "tenantId": tid, "domain": body.get("domain", ""), "controlCode": body.get( "controlCode", body.get("control_code", ""), ), "title": body.get("title", ""), "description": body.get("description", ""), "createdAt": now, }) def delete_control(self, control_id: str) -> dict: result = self._db.execute( text("DELETE FROM vendor_compliance_controls WHERE id = :id"), {"id": control_id}, ) self._db.commit() if result.rowcount == 0: raise NotFoundError("Control not found") return _ok({"deleted": True})