feat(poll): enforce auditable lifecycle transitions
This commit is contained in:
@@ -8,6 +8,7 @@ from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||||
|
||||
PollKind = Literal["single_choice", "multiple_choice", "yes_no", "yes_no_maybe", "ranked_choice", "availability"]
|
||||
PollStatus = Literal["draft", "open", "closed", "decided", "archived"]
|
||||
PollTransitionAction = Literal["open", "draft", "close", "decide", "archive", "unarchive"]
|
||||
PollVisibility = Literal["private", "tenant", "public", "unlisted"]
|
||||
PollResultVisibility = Literal["organizer", "after_response", "after_close", "public"]
|
||||
AvailabilityValue = Literal["available", "maybe", "unavailable"]
|
||||
@@ -85,6 +86,13 @@ class PollOptionResponse(BaseModel):
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class PollTransitionAvailabilityResponse(BaseModel):
|
||||
action: PollTransitionAction
|
||||
target_status: PollStatus | None = None
|
||||
available: bool
|
||||
reason: str | None = None
|
||||
|
||||
|
||||
class PollResponseItem(BaseModel):
|
||||
id: str
|
||||
respondent_id: str | None = None
|
||||
@@ -120,11 +128,13 @@ class PollResponse(BaseModel):
|
||||
closed_at: datetime | None = None
|
||||
decided_at: datetime | None = None
|
||||
decided_option_id: str | None = None
|
||||
archived_from_status: str | None = None
|
||||
created_by_user_id: str | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
options: list[PollOptionResponse] = Field(default_factory=list)
|
||||
lifecycle_actions: list[PollTransitionAvailabilityResponse] = Field(default_factory=list)
|
||||
|
||||
|
||||
class PollListResponse(BaseModel):
|
||||
@@ -175,8 +185,40 @@ class PollDecisionRequest(BaseModel):
|
||||
option_key: str | None = None
|
||||
|
||||
|
||||
class PollTransitionRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
action: PollTransitionAction
|
||||
option_id: str | None = None
|
||||
option_key: str | None = None
|
||||
|
||||
|
||||
class PollLifecycleTransitionResponse(BaseModel):
|
||||
id: str
|
||||
action: PollTransitionAction
|
||||
from_status: PollStatus
|
||||
to_status: PollStatus
|
||||
decision_option_id: str | None = None
|
||||
previous_decision_option_id: str | None = None
|
||||
idempotency_key: str | None = None
|
||||
actor_user_id: str | None = None
|
||||
actor_api_key_id: str | None = None
|
||||
created_at: datetime
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class PollStatusResponse(BaseModel):
|
||||
poll: PollResponse
|
||||
transition: PollLifecycleTransitionResponse | None = None
|
||||
replayed: bool = False
|
||||
|
||||
|
||||
class PollLifecycleResponse(BaseModel):
|
||||
poll_id: str
|
||||
status: PollStatus
|
||||
archived_from_status: str | None = None
|
||||
actions: list[PollTransitionAvailabilityResponse] = Field(default_factory=list)
|
||||
history: list[PollLifecycleTransitionResponse] = Field(default_factory=list)
|
||||
|
||||
|
||||
class PollResponseListResponse(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user