"""REST-adapter request / response bodies. Most payloads reuse the core contracts directly (:class:`RequestIX`, :class:`Job`). The only adapter-specific shape is the lightweight POST /jobs response (`job_id`, `ix_id`, `status`) โ€” callers don't need the full Job envelope back on submit; they poll ``GET /jobs/{id}`` for that. """ from __future__ import annotations from typing import Literal from uuid import UUID from pydantic import BaseModel, ConfigDict class JobSubmitResponse(BaseModel): """What POST /jobs returns: just enough to poll or subscribe to callbacks.""" model_config = ConfigDict(extra="forbid") job_id: UUID ix_id: str status: Literal["pending", "running", "done", "error"] class HealthStatus(BaseModel): """Body of GET /healthz. Each field reports per-subsystem state. Overall HTTP status is 200 iff every field is ``"ok"`` (spec ยง5). ``ollama`` can be ``"degraded"`` when the backend is reachable but the default model isn't pulled โ€” monitoring surfaces that as non-200. """ model_config = ConfigDict(extra="forbid") postgres: Literal["ok", "fail"] ollama: Literal["ok", "degraded", "fail"] ocr: Literal["ok", "fail"] class MetricsResponse(BaseModel): """Body of GET /metrics โ€” plain JSON (no Prometheus format for MVP).""" model_config = ConfigDict(extra="forbid") jobs_pending: int jobs_running: int jobs_done_24h: int jobs_error_24h: int by_use_case_seconds: dict[str, float]