세션 계약과 메모리 경계 보강

This commit is contained in:
Yun Chan 2026-06-28 23:52:18 +09:00
parent 391639c1de
commit 2bb052f624
12 changed files with 836 additions and 116 deletions

View file

@ -13,9 +13,10 @@ from typing import Any
from fastapi import APIRouter, HTTPException, Request, Response, status
from fastapi.responses import HTMLResponse, PlainTextResponse
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, field_validator
from .. import session_persistence
from ..session_read_model import StageLabel, stage_label_or_none
router = APIRouter(tags=["share"])
@ -36,7 +37,7 @@ class PublicSessionShareResponse(BaseModel):
persona: str
date: str
durationLabel: str
reachedPhase: str
reachedPhase: StageLabel | None = None
sessionSignal: str
reviewReady: bool = False
goodMoments: list[str] = Field(default_factory=list)
@ -44,6 +45,11 @@ class PublicSessionShareResponse(BaseModel):
worksheetHighlights: list[dict[str, str]] = Field(default_factory=list)
privacy: str = ""
@field_validator("reachedPhase", mode="before")
@classmethod
def _normalize_reached_phase(cls, value: object) -> StageLabel | None:
return stage_label_or_none(value)
def _safe_payload(payload: dict[str, Any]) -> PublicSessionShareResponse:
return PublicSessionShareResponse(
@ -56,7 +62,7 @@ def _safe_payload(payload: dict[str, Any]) -> PublicSessionShareResponse:
persona=str(payload.get("persona") or ""),
date=str(payload.get("date") or ""),
durationLabel=str(payload.get("durationLabel") or ""),
reachedPhase=str(payload.get("reachedPhase") or ""),
reachedPhase=payload.get("reachedPhase"),
sessionSignal=str(payload.get("sessionSignal") or ""),
reviewReady=bool(payload.get("reviewReady")),
goodMoments=[str(item) for item in payload.get("goodMoments") or []][:3],