"""Request / response schemas for the HITL review endpoints (Phase 6). The API surface is deliberately small: * ``CorrectionRequest`` — body of ``PATCH /documents/{id}``. A list of ``FieldCorrection`` entries; each one is applied atomically (all-or- nothing) and recorded in the audit trail. * ``CorrectionEventResponse`` — single row in ``GET /documents/{id}/history``. * ``ApprovalResponse`` — echo back after ``POST /documents/{id}/approve``. """ from __future__ import annotations from datetime import datetime from typing import Any from uuid import UUID from pydantic import BaseModel, Field class FieldCorrection(BaseModel): """One field-level correction. ``path`` is a dotted JSON path into ``ExtractionResult``. Supported roots: ``header``, ``ttd``, ``personel[n]`` (n is a 0-based index), ``untuk``. The path is validated by the repository before being applied; unknown roots return 400. """ path: str = Field(..., description="Dotted JSON path, e.g. 'header.nomor_sprint'.") value: Any = Field(..., description="New value (any JSON-serialisable payload).") reason: str | None = Field( None, max_length=512, description="Optional free-form reason for the correction." ) class CorrectionRequest(BaseModel): """PATCH body — one or more field corrections, applied atomically.""" corrections: list[FieldCorrection] = Field(..., min_length=1) class CorrectionEventResponse(BaseModel): """One row of the audit log surfaced by GET /history.""" id: int job_id: UUID field_path: str old_value: Any | None = None new_value: Any | None = None corrected_by: str | None = None reason: str | None = None corrected_at: datetime class ApprovalResponse(BaseModel): """Echo returned after a job is approved.""" job_id: UUID approved: bool reviewed_by: str | None = None reviewed_at: datetime | None = None