from __future__ import annotations from datetime import datetime from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field class CaseStatusWriteRequest(BaseModel): model_config = ConfigDict(extra="forbid") status_key: str = Field(min_length=1, max_length=120) label: str = Field(min_length=1, max_length=255) category: str = Field(default="open", max_length=30) terminal: bool = False sort_order: int = Field(default=100, ge=-10_000, le=10_000) active: bool = True expected_revision: int | None = Field(default=None, ge=1) class CaseTypeWriteRequest(BaseModel): model_config = ConfigDict(extra="forbid") type_key: str = Field(min_length=1, max_length=120) label: str = Field(min_length=1, max_length=255) description: str | None = Field(default=None, max_length=4_000) initial_status_key: str = Field(min_length=1, max_length=120) allowed_status_keys: list[str] = Field(default_factory=list, max_length=100) active: bool = True expected_revision: int | None = Field(default=None, ge=1) class CaseWriteRequest(BaseModel): model_config = ConfigDict(extra="forbid") record: dict[str, Any] idempotency_key: str = Field(min_length=1, max_length=255) class CaseGrantRequest(BaseModel): model_config = ConfigDict(extra="forbid") subject_kind: Literal[ "account", "identity", "group", "role", "function", "function_assignment", "organization_unit", "service_account", ] subject_id: str = Field(min_length=1, max_length=255) permissions: list[Literal["read", "update", "share", "admin"]] = Field( default_factory=lambda: ["read"], min_length=1, max_length=4, ) class CaseUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") expected_revision: int = Field(ge=1) recorded_at: datetime change_reason: str = Field(min_length=1, max_length=1_000) idempotency_key: str = Field(min_length=1, max_length=255) status_key: str | None = Field(default=None, min_length=1, max_length=120) title: str | None = Field(default=None, min_length=1, max_length=500) access_mode: Literal["tenant", "restricted"] | None = None access_grants: list[CaseGrantRequest] | None = Field( default=None, max_length=500, ) party_refs: list[dict[str, Any]] | None = Field(default=None, max_length=500) assignment_refs: list[dict[str, Any]] | None = Field(default=None, max_length=500) evidence_refs: list[dict[str, Any]] | None = Field(default=None, max_length=1_000) decision_refs: list[dict[str, Any]] | None = Field(default=None, max_length=500) record_refs: list[dict[str, Any]] | None = Field(default=None, max_length=500) deadline_at: datetime | None = None closed_at: datetime | None = None metadata: dict[str, Any] | None = None class CaseOwnerReferenceRequest(BaseModel): model_config = ConfigDict(extra="forbid") owner_module: str = Field(min_length=1, max_length=120) kind: str = Field(min_length=1, max_length=120) object_id: str = Field(min_length=1, max_length=1_000) tenant_id: str = Field(min_length=1, max_length=255) version: str = Field(min_length=1, max_length=255) path: str = Field(min_length=1, max_length=2_000) class CaseEvidenceLinkRequest(BaseModel): model_config = ConfigDict(extra="forbid") expected_revision: int = Field(ge=1) recorded_at: datetime change_reason: str = Field(min_length=1, max_length=1_000) idempotency_key: str = Field(min_length=1, max_length=255) reference: CaseOwnerReferenceRequest class CaseEvidenceUnlinkRequest(BaseModel): model_config = ConfigDict(extra="forbid") expected_revision: int = Field(ge=1) recorded_at: datetime change_reason: str = Field(min_length=1, max_length=1_000) idempotency_key: str = Field(min_length=1, max_length=255) class CaseDecisionRequest(BaseModel): model_config = ConfigDict(extra="forbid") expected_case_revision: int = Field(ge=1) effective_at: datetime decision_type: str = Field(min_length=1, max_length=120) operative_result: str = Field(min_length=1, max_length=20_000) reasoning: str = Field(min_length=1, max_length=50_000) conditions: list[str] = Field(default_factory=list, max_length=100) change_reason: str = Field(min_length=1, max_length=1_000) idempotency_key: str = Field(min_length=1, max_length=255) class CaseListResponse(BaseModel): cases: list[dict[str, Any]] total: int offset: int limit: int class CaseHistoryResponse(BaseModel): revisions: list[dict[str, Any]] class CaseTimelineResponse(BaseModel): entries: list[dict[str, Any]] __all__ = [ "CaseGrantRequest", "CaseDecisionRequest", "CaseEvidenceLinkRequest", "CaseEvidenceUnlinkRequest", "CaseHistoryResponse", "CaseListResponse", "CaseStatusWriteRequest", "CaseTimelineResponse", "CaseTypeWriteRequest", "CaseUpdateRequest", "CaseWriteRequest", ]