diff --git a/backend/app/schemas/__init__.py b/backend/app/schemas/__init__.py index 9716653d..f93b7042 100644 --- a/backend/app/schemas/__init__.py +++ b/backend/app/schemas/__init__.py @@ -1,5 +1,13 @@ from app.schemas.activity_events import ActivityEventRead from app.schemas.agents import AgentCreate, AgentRead, AgentUpdate +from app.schemas.approvals import ApprovalCreate, ApprovalRead, ApprovalUpdate +from app.schemas.board_memory import BoardMemoryCreate, BoardMemoryRead +from app.schemas.board_onboarding import ( + BoardOnboardingAnswer, + BoardOnboardingConfirm, + BoardOnboardingRead, + BoardOnboardingStart, +) from app.schemas.boards import BoardCreate, BoardRead, BoardUpdate from app.schemas.gateways import GatewayCreate, GatewayRead, GatewayUpdate from app.schemas.metrics import DashboardMetrics @@ -11,6 +19,15 @@ __all__ = [ "AgentCreate", "AgentRead", "AgentUpdate", + "ApprovalCreate", + "ApprovalRead", + "ApprovalUpdate", + "BoardMemoryCreate", + "BoardMemoryRead", + "BoardOnboardingAnswer", + "BoardOnboardingConfirm", + "BoardOnboardingRead", + "BoardOnboardingStart", "BoardCreate", "BoardRead", "BoardUpdate", diff --git a/backend/app/schemas/approvals.py b/backend/app/schemas/approvals.py new file mode 100644 index 00000000..2277a581 --- /dev/null +++ b/backend/app/schemas/approvals.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from datetime import datetime +from uuid import UUID + +from sqlmodel import SQLModel + + +class ApprovalBase(SQLModel): + action_type: str + payload: dict[str, object] | None = None + confidence: int + rubric_scores: dict[str, int] | None = None + status: str = "pending" + + +class ApprovalCreate(ApprovalBase): + agent_id: UUID | None = None + + +class ApprovalUpdate(SQLModel): + status: str | None = None + + +class ApprovalRead(ApprovalBase): + id: UUID + board_id: UUID + agent_id: UUID | None = None + created_at: datetime + resolved_at: datetime | None = None diff --git a/backend/app/schemas/board_memory.py b/backend/app/schemas/board_memory.py new file mode 100644 index 00000000..97eec0a7 --- /dev/null +++ b/backend/app/schemas/board_memory.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from datetime import datetime +from uuid import UUID + +from sqlmodel import SQLModel + + +class BoardMemoryCreate(SQLModel): + content: str + tags: list[str] | None = None + source: str | None = None + + +class BoardMemoryRead(BoardMemoryCreate): + id: UUID + board_id: UUID + created_at: datetime diff --git a/backend/app/schemas/board_onboarding.py b/backend/app/schemas/board_onboarding.py new file mode 100644 index 00000000..5c28ca60 --- /dev/null +++ b/backend/app/schemas/board_onboarding.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from datetime import datetime +from uuid import UUID + +from sqlmodel import SQLModel + + +class BoardOnboardingStart(SQLModel): + pass + + +class BoardOnboardingAnswer(SQLModel): + answer: str + other_text: str | None = None + + +class BoardOnboardingConfirm(SQLModel): + board_type: str + objective: str | None = None + success_metrics: dict[str, object] | None = None + target_date: datetime | None = None + + +class BoardOnboardingRead(SQLModel): + id: UUID + board_id: UUID + session_key: str + status: str + messages: list[dict[str, object]] | None = None + draft_goal: dict[str, object] | None = None + created_at: datetime + updated_at: datetime diff --git a/backend/app/schemas/boards.py b/backend/app/schemas/boards.py index 458c38bc..79b12591 100644 --- a/backend/app/schemas/boards.py +++ b/backend/app/schemas/boards.py @@ -3,6 +3,7 @@ from __future__ import annotations from datetime import datetime from uuid import UUID +from pydantic import model_validator from sqlmodel import SQLModel @@ -10,16 +11,33 @@ class BoardBase(SQLModel): name: str slug: str gateway_id: UUID | None = None + board_type: str = "goal" + objective: str | None = None + success_metrics: dict[str, object] | None = None + target_date: datetime | None = None + goal_confirmed: bool = False + goal_source: str | None = None class BoardCreate(BoardBase): - pass + @model_validator(mode="after") + def validate_goal_fields(self): + if self.board_type == "goal": + if not self.objective or not self.success_metrics: + raise ValueError("Goal boards require objective and success_metrics") + return self class BoardUpdate(SQLModel): name: str | None = None slug: str | None = None gateway_id: UUID | None = None + board_type: str | None = None + objective: str | None = None + success_metrics: dict[str, object] | None = None + target_date: datetime | None = None + goal_confirmed: bool | None = None + goal_source: str | None = None class BoardRead(BoardBase): diff --git a/backend/tests/test_board_schema.py b/backend/tests/test_board_schema.py new file mode 100644 index 00000000..db18fa66 --- /dev/null +++ b/backend/tests/test_board_schema.py @@ -0,0 +1,20 @@ +import pytest + +from app.schemas.boards import BoardCreate + + +def test_goal_board_requires_objective_and_metrics(): + with pytest.raises(ValueError): + BoardCreate(name="Goal Board", slug="goal", board_type="goal") + + BoardCreate( + name="Goal Board", + slug="goal", + board_type="goal", + objective="Launch onboarding", + success_metrics={"emails": 3}, + ) + + +def test_general_board_allows_missing_objective(): + BoardCreate(name="General", slug="general", board_type="general")