From 6f475000f67acb21e117457286dee2e26b1f6e47 Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 8 Apr 2026 22:42:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(db):=20alert=5Foperation=5Flog.event=5Ftype?= =?UTF-8?q?=20String=E2=86=92PgEnum=20(create=5Ftype=3DFalse)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正 DatatypeMismatchError: DB 欄位為 native enum alert_event_type, SQLAlchemy model 誤用 String(50),導致 alert_operation_log 寫入失敗。 使用 PgEnum(create_type=False) 讓 SQLAlchemy 映射已存在的 DB enum, 不重建型別。18 個 event_type 值與 M-003 migration 一致。 Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/db/models.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/api/src/db/models.py b/apps/api/src/db/models.py index 7dc9f918..11eff1c0 100644 --- a/apps/api/src/db/models.py +++ b/apps/api/src/db/models.py @@ -25,6 +25,7 @@ from sqlalchemy import ( from sqlalchemy import ( Enum as SQLEnum, ) +from sqlalchemy.dialects.postgresql import ENUM as PgEnum from sqlalchemy.orm import Mapped, mapped_column from src.db.base import Base @@ -445,7 +446,18 @@ class AlertOperationLog(Base): auto_repair_id: Mapped[str | None] = mapped_column(String(36), nullable=True) # 事件核心 - event_type: Mapped[str] = mapped_column(String(50), nullable=False, index=True) + # 2026-04-08 Claude Sonnet 4.6: Sprint 5.1 — 修正 enum 型別不符 (String→PgEnum, create_type=False) + event_type: Mapped[str] = mapped_column( + PgEnum( + "ALERT_RECEIVED", "TELEGRAM_SENT", "USER_ACTION", "AUTO_REPAIR_TRIGGERED", + "EXECUTION_STARTED", "EXECUTION_COMPLETED", "TELEGRAM_RESULT_SENT", + "RESOLVED", "SILENCED", "ESCALATED", "GUARDRAIL_BLOCKED", + "PRE_FLIGHT_PASSED", "PRE_FLIGHT_FAILED", "BACKUP_TRIGGERED", + "BACKUP_COMPLETED", "BACKUP_FAILED", "APPROVAL_ESCALATED", "CHANGE_APPLIED", + name="alert_event_type", create_type=False, + ), + nullable=False, index=True, + ) actor: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True) action_detail: Mapped[str | None] = mapped_column(String(200), nullable=True)