Reject coerced and out-of-range skip_on_away values

Review remediation for PR #194:
- Admin create/edit request models use StrictBool so JSON 0/1 and
  "true"/"false" are 422 instead of being coerced to a bool.
- Fresh-schema quest_definitions gains CHECK (skip_on_away IN (0, 1));
  migrated databases (column added without the CHECK) are guarded by a
  DAO validator applied at every write path that takes the flag.
- QuestDefinitionsDao.update() accepts skip_on_away (None leaves it
  unchanged), validated like the other write paths.

Task: ded75ab8-0219-4d52-aefa-82c09e0b5e6b

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-23 20:40:22 -04:00
co-authored by Claude Opus 5.5
parent ab0a320f3f
commit e8ae25e5eb
6 changed files with 191 additions and 8 deletions
+3 -3
View File
@@ -251,7 +251,7 @@ import datetime
from typing import Annotated, Literal, NoReturn
from fastapi import APIRouter, Depends, HTTPException, Request, Response
from pydantic import BaseModel, field_validator, model_validator
from pydantic import BaseModel, StrictBool, field_validator, model_validator
from api import transitions as api_transitions
from api.auth import require_admin
@@ -464,7 +464,7 @@ class AdminQuestDefinitionCreateRequest(BaseModel):
windows: list[str | tuple[str, str | None]]
description: str | None = None
icon: str | None = None
skip_on_away: bool = True
skip_on_away: StrictBool = True
class AdminQuestDefinitionEditRequest(BaseModel):
@@ -488,7 +488,7 @@ class AdminQuestDefinitionEditRequest(BaseModel):
icon: str | None = None
rule: AdminRuleRequest | None = None
windows: list[str | tuple[str, str | None]] | None = None
skip_on_away: bool | None = None
skip_on_away: StrictBool | None = None
class AdminQuestDefinitionActiveRequest(BaseModel):