안전 이벤트 대시보드 보강

This commit is contained in:
Yun Chan 2026-07-01 12:34:46 +09:00
parent fe2796f05a
commit 51053af536
15 changed files with 1081 additions and 423 deletions

View file

@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, patch
from fastapi import HTTPException
from . import auth_sessions, session_persistence
from . import auth_sessions, db, session_persistence
from .config import Settings, settings
from .deps import Principal, Role
from .routes import admin as admin_routes
@ -229,6 +229,57 @@ class RuntimeFallbackPolicyTest(unittest.IsolatedAsyncioTestCase):
self.assertIn(column, conn.query)
self.assertIn("HAVING count(*) = 5", conn.query)
async def test_healthcheck_requires_safety_events_schema(self) -> None:
class MissingSafetyEventsConn:
def __init__(self) -> None:
self.query = ""
async def fetchrow(self, query: str, *args, **kwargs):
self.query = query
return {
"has_user": True,
"has_auth_session": True,
"has_preferences": True,
"has_engine_config": True,
"has_admin_health_event": True,
"has_admin_health_daily_rollup": True,
"has_support_ticket": True,
"has_notification_event": True,
"has_notification_delivery": True,
"has_sessions": True,
"has_turns": True,
"has_safety_events": False,
"has_session_review_status": True,
"has_turn_voice_metadata_columns": True,
"has_safety_event_columns": False,
"has_session_review_worksheet_columns": True,
}
class MissingSafetyEventsAcquire:
def __init__(self, conn: MissingSafetyEventsConn) -> None:
self.conn = conn
async def __aenter__(self) -> MissingSafetyEventsConn:
return self.conn
async def __aexit__(self, exc_type, exc, tb) -> None:
return None
class MissingSafetyEventsPool:
def __init__(self, conn: MissingSafetyEventsConn) -> None:
self.conn = conn
def acquire(self):
return MissingSafetyEventsAcquire(self.conn)
conn = MissingSafetyEventsConn()
with patch.object(db, "get_pool", return_value=MissingSafetyEventsPool(conn)):
healthy = await db.healthcheck()
self.assertFalse(healthy)
self.assertIn("to_regclass('app.safety_events')", conn.query)
self.assertIn("has_safety_event_columns", conn.query)
async def test_staging_uses_env_engine_config_when_row_missing(self) -> None:
class EmptyConfigConn:
async def fetchrow(self, *args, **kwargs):