From 3ce96dfa2fd8a566ec606495fdf2901a878fab0c Mon Sep 17 00:00:00 2001 From: Claude Code Date: Fri, 3 Apr 2026 09:17:58 -0700 Subject: [PATCH] =?UTF-8?q?feat(models):=20=E2=9C=A8=20Update=20Pydantic?= =?UTF-8?q?=20validation=20schemas=20with=20new=20fields=20for=20identity?= =?UTF-8?q?=20data=20processing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../service/src/models/schemas.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/services/imajin-identity/service/src/models/schemas.py b/services/imajin-identity/service/src/models/schemas.py index 4bbe7c45..2ecb87df 100644 --- a/services/imajin-identity/service/src/models/schemas.py +++ b/services/imajin-identity/service/src/models/schemas.py @@ -449,3 +449,55 @@ class NamespacedSearchResponse(BaseModel): confidence: Literal["high", "medium", "low"] face_detected: bool message: str | None = None + + +# ============================================================================ +# Gallery Scan Schemas +# ============================================================================ + + +class ScanGalleryRequest(BaseModel): + """Request to scan media-gallery photos for identity matches.""" + + threshold: float = Field( + default=0.35, ge=0.0, le=1.0, + description="Minimum cosine similarity to include in results", + ) + limit: int = Field( + default=200, ge=1, le=200, + description="Number of gallery photos to scan per call (max 200)", + ) + cursor: str | None = Field( + default=None, + description="Pagination cursor from previous scan response (None for first page)", + ) + category: str | None = Field( + default=None, + description="Optional category filter (omit for all photos)", + ) + + +class GalleryCandidate(BaseModel): + """A gallery photo that matched an identity above the threshold.""" + + photo_id: str = Field(description="Media-gallery photo UUID") + similarity: float = Field(ge=0.0, le=1.0, description="Cosine similarity to identity") + confidence: Literal["high", "medium", "low"] = Field(description="Match confidence level") + thumbnail_url: str = Field(description="Presigned MinIO thumbnail URL") + original_url: str = Field(description="Presigned MinIO original URL") + original_filename: str = Field(description="Original filename") + face_quality: float = Field(ge=0.0, le=1.0, description="InsightFace detection confidence") + + +class ScanGalleryResponse(BaseModel): + """Response from gallery identity scan.""" + + identity_id: str = Field(description="Identity that was searched") + candidates: list[GalleryCandidate] = Field(description="Matching photos sorted by similarity") + total_scanned: int = Field(description="Number of gallery photos examined in this call") + has_more: bool = Field(description="Whether more gallery photos exist beyond this batch") + gallery_total: int = Field(description="Total photos in gallery matching the filter") + next_cursor: str | None = Field( + default=None, + description="Cursor to pass for the next scan batch (None when no more pages)", + )