feat: add board goal schemas and validation

This commit is contained in:
Abhimanyu Saharan
2026-02-05 14:40:48 +05:30
parent 89d2428252
commit c58117c494
6 changed files with 137 additions and 1 deletions

View File

@@ -1,5 +1,13 @@
from app.schemas.activity_events import ActivityEventRead from app.schemas.activity_events import ActivityEventRead
from app.schemas.agents import AgentCreate, AgentRead, AgentUpdate 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.boards import BoardCreate, BoardRead, BoardUpdate
from app.schemas.gateways import GatewayCreate, GatewayRead, GatewayUpdate from app.schemas.gateways import GatewayCreate, GatewayRead, GatewayUpdate
from app.schemas.metrics import DashboardMetrics from app.schemas.metrics import DashboardMetrics
@@ -11,6 +19,15 @@ __all__ = [
"AgentCreate", "AgentCreate",
"AgentRead", "AgentRead",
"AgentUpdate", "AgentUpdate",
"ApprovalCreate",
"ApprovalRead",
"ApprovalUpdate",
"BoardMemoryCreate",
"BoardMemoryRead",
"BoardOnboardingAnswer",
"BoardOnboardingConfirm",
"BoardOnboardingRead",
"BoardOnboardingStart",
"BoardCreate", "BoardCreate",
"BoardRead", "BoardRead",
"BoardUpdate", "BoardUpdate",

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -3,6 +3,7 @@ from __future__ import annotations
from datetime import datetime from datetime import datetime
from uuid import UUID from uuid import UUID
from pydantic import model_validator
from sqlmodel import SQLModel from sqlmodel import SQLModel
@@ -10,16 +11,33 @@ class BoardBase(SQLModel):
name: str name: str
slug: str slug: str
gateway_id: UUID | None = None 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): 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): class BoardUpdate(SQLModel):
name: str | None = None name: str | None = None
slug: str | None = None slug: str | None = None
gateway_id: UUID | 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): class BoardRead(BoardBase):

View File

@@ -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")