개선관리 요구사항과 Google 로그인을 완료

This commit is contained in:
Yun Chan 2026-08-28 16:07:09 +09:00
parent cc0a15b7c6
commit 2a39636163
112 changed files with 10166 additions and 527 deletions

View file

@ -24,7 +24,11 @@ from ..contracts.calibration_transfer import (
)
from ..config import Settings, get_settings
from ..deps import AIView, Principal, Role, db_for_ai_view, require_role
from ..services import calibration_transfer_store, session_learning_producer
from ..services import (
calibration_transfer_store,
feedback_policy,
session_learning_producer,
)
router = APIRouter(tags=["calibration-transfer"])
@ -337,8 +341,8 @@ class ActualTransferExecutionRequest(BaseModel):
class ActualTransferExecutionResponse(BaseModel):
execution: ActualTransferExecution
assessment: ActualTransferAssessment
execution: ActualTransferExecution | None = None
assessment: ActualTransferAssessment | None = None
idempotent_replay: bool
@ -532,6 +536,22 @@ class CalibrationTransferReadModelResponse(BaseModel):
)
def _learner_input_only_payload(payload: dict[str, Any]) -> dict[str, Any]:
"""자기예측 원문만 남기고 내부·교수자·AI 파생 판정을 제거한다."""
redacted = dict(payload)
redacted["prediction_histories"] = [
{**dict(history), "external_observation": None}
for history in payload.get("prediction_histories", [])
]
redacted["calibration_assessments"] = []
redacted["transfer_suites"] = []
redacted["teacher_reviews"] = []
redacted["actual_executions"] = []
redacted["actual_transfer_assessments"] = []
return redacted
def _http_error(exc: Exception) -> HTTPException:
if isinstance(
exc, calibration_transfer_store.CalibrationTransferNotFoundError
@ -673,12 +693,20 @@ async def create_actual_transfer_execution(
body: ActualTransferExecutionRequest,
principal: LearnerPrincipal,
) -> ActualTransferExecutionResponse:
expose_feedback = await feedback_policy.can_expose_session_learner_feedback(
body.practice_session_id,
principal,
)
try:
payload = await calibration_transfer_store.append_actual_transfer_execution(
principal=principal, **body.model_dump()
)
except _STORE_ERRORS as exc:
raise _http_error(exc) from exc
if not expose_feedback:
return ActualTransferExecutionResponse(
idempotent_replay=bool(payload.get("idempotent_replay", False))
)
return ActualTransferExecutionResponse.model_validate(payload)
@ -706,6 +734,7 @@ async def create_teacher_review(
)
async def get_my_calibration_transfer(
principal: LearnerPrincipal,
session_id: UUID | None = None,
) -> CalibrationTransferReadModelResponse:
try:
payload = await calibration_transfer_store.read_calibration_transfer(
@ -713,6 +742,23 @@ async def get_my_calibration_transfer(
)
except _STORE_ERRORS as exc:
raise _http_error(exc) from exc
payload = dict(payload)
snapshot_enabled = bool(
payload.pop("_learner_feedback_snapshot_enabled", True)
)
expose_feedback = bool(
principal.learner_feedback_enabled and snapshot_enabled
)
if session_id is not None:
expose_feedback = bool(
expose_feedback
and await feedback_policy.can_expose_session_learner_feedback(
session_id,
principal,
)
)
if not expose_feedback:
payload = _learner_input_only_payload(payload)
return CalibrationTransferReadModelResponse.model_validate(payload)