diff --git a/backend/api/schemas.py b/backend/api/schemas.py new file mode 100644 index 0000000..f87b725 --- /dev/null +++ b/backend/api/schemas.py @@ -0,0 +1,42 @@ +"""Cross-package Pydantic response models. + +Models here are used by 2+ API packages and cannot live in a single package +without creating circular imports (D-10, RESEARCH.md Pitfall 3). +""" +from __future__ import annotations + +from datetime import datetime +from typing import Optional + +from pydantic import BaseModel, field_validator + + +class CloudConnectionOut(BaseModel): + """SEC-08: credentials_enc deliberately excluded from this response model. + + Any admin or user endpoint returning CloudConnection ORM objects MUST use + this model to prevent accidental exposure of encrypted credentials. + Safe-by-default: whitelist of allowed fields (not blacklist). + + Moved from api/admin.py to eliminate cross-package coupling between + api/cloud.py and api/admin.py (D-10, RESEARCH.md Pitfall 3). + Used by api/cloud.py and api/admin/ (after plan 08-04 admin split). + + Note: id is declared as str and coerced via validator so UUID ORM values + serialize correctly without json_encoders. + """ + + id: str + provider: str + display_name: str + status: str + connected_at: datetime + server_url: Optional[str] = None + connection_username: Optional[str] = None + model_config = {"from_attributes": True} + + @field_validator("id", mode="before") + @classmethod + def coerce_id_to_str(cls, v) -> str: + """Coerce UUID objects to str so the model validates from ORM instances.""" + return str(v)