"""Wire types. These are deliberately NOT the domain models. `Instance` carries `team`, `namespace` and `release_name` — placement details a tenant has no business seeing and no business setting. The response model is the allow-list that keeps them off the wire, which is why it is written out by hand instead of derived from `Instance`. """ from __future__ import annotations from uuid import UUID from pydantic import BaseModel, ConfigDict, Field from svcforge_core.domain.states import InstanceState class CreateInstanceRequest(BaseModel): """What a tenant may ask for. `service_type` and `size` are plain strings, not enums: the catalog is data loaded at runtime, so baking its keys into a type would mean a redeploy to add a service type, and a 422 (schema) where the spec wants a 404 (unknown resource). They are validated against the catalog in the handler. """ model_config = ConfigDict(extra="forbid") service_type: str = Field(min_length=1) size: str ttl_days: int | None = Field(default=None, ge=1, le=30) class InstanceResponse(BaseModel): """What a tenant gets back. A subset of Instance, on purpose.""" model_config = ConfigDict(from_attributes=True) id: UUID state: InstanceState service_type: str size: str endpoint: str | None chart_version: str error: str | None class ErrorBody(BaseModel): """Every non-2xx body. `code` is for machines, `message` is for humans.""" code: str message: str