from __future__ import annotations from datetime import datetime from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field, field_validator from govoplan_core.api.v1.schemas import DeltaDeletedItem class TenantAdminItem(BaseModel): id: str slug: str = Field(min_length=1, max_length=100) name: str = Field(min_length=1, max_length=255) description: str | None = None default_locale: str = Field(default="en", min_length=1, max_length=20) settings: dict[str, Any] = Field(default_factory=dict) allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None allow_api_keys: bool | None = None effective_governance: dict[str, bool] = Field(default_factory=dict) is_active: bool counts: dict[str, int] = Field(default_factory=dict) created_at: datetime updated_at: datetime class TenantListResponse(BaseModel): tenants: list[TenantAdminItem] class TenantListDeltaResponse(BaseModel): tenants: list[TenantAdminItem] = Field(default_factory=list) deleted: list[DeltaDeletedItem] = Field(default_factory=list) watermark: str | None = None has_more: bool = False full: bool = False class TenantOwnerCandidate(BaseModel): account_id: str email: str display_name: str | None = None class TenantOwnerCandidateListResponse(BaseModel): accounts: list[TenantOwnerCandidate] class TenantCreateRequest(BaseModel): model_config = ConfigDict(extra="forbid") slug: str name: str owner_account_id: str | None = None description: str | None = None default_locale: str = "en" settings: dict[str, Any] = Field(default_factory=dict) allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None allow_api_keys: bool | None = None class TenantUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") name: str | None = Field(default=None, min_length=1, max_length=255) description: str | None = None default_locale: str | None = Field(default=None, min_length=1, max_length=20) settings: dict[str, Any] | None = None allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None allow_api_keys: bool | None = None is_active: bool | None = None class TenantLifecycleIssue(BaseModel): severity: Literal["blocker", "warning", "info"] code: str message: str module_id: str | None = None class TenantDeletionPlanResponse(BaseModel): tenant_id: str action: Literal["retire", "destroy"] = "retire" allowed: bool destructive_supported: bool = False issues: list[TenantLifecycleIssue] = Field(default_factory=list) counts: dict[str, int] = Field(default_factory=dict) class TenantDeleteRequest(BaseModel): model_config = ConfigDict(extra="forbid") mode: Literal["retire", "destroy"] = "retire" reason: str | None = None class TenantLifecycleResponse(BaseModel): item: TenantAdminItem plan: TenantDeletionPlanResponse class TenantContextSwitchRequest(BaseModel): model_config = ConfigDict(extra="forbid") tenant_id: str class TenantContextSwitchResponse(BaseModel): account_id: str membership_id: str tenant_id: str session_id: str | None = None class TenantSettingsItem(BaseModel): id: str slug: str name: str default_locale: str = Field(default="en", min_length=1, max_length=20) available_languages: list[dict[str, Any]] = Field(default_factory=list) system_enabled_language_codes: list[str] = Field(default_factory=list) enabled_language_codes: list[str] = Field(default_factory=list) settings: dict[str, Any] = Field(default_factory=dict) class TenantSettingsDeltaResponse(BaseModel): item: TenantSettingsItem | None = None sections: dict[str, Any] = Field(default_factory=dict) changed_sections: list[str] = Field(default_factory=list) deleted: list[DeltaDeletedItem] = Field(default_factory=list) watermark: str | None = None has_more: bool = False full: bool = False class TenantSettingsUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") default_locale: str = Field(min_length=1, max_length=20) enabled_language_codes: list[str] | None = None