fix: normalize webhook secret via schema validator instead of inline

Move blank/whitespace-only secret normalization to a shared
field_validator on both BoardWebhookCreate and BoardWebhookUpdate.
This ensures consistent behavior across create and update paths
and removes the inline normalization from the endpoint handlers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hugh Brown
2026-03-03 22:25:37 -07:00
committed by Abhimanyu Saharan
parent 91e8270364
commit 2ef6164cf8
2 changed files with 14 additions and 3 deletions

View File

@@ -359,7 +359,7 @@ async def create_board_webhook(
agent_id=payload.agent_id,
description=payload.description,
enabled=payload.enabled,
secret=payload.secret or None,
secret=payload.secret,
)
await crud.save(session, webhook)
return _to_webhook_read(webhook)
@@ -394,8 +394,6 @@ async def update_board_webhook(
webhook_id=webhook_id,
)
updates = payload.model_dump(exclude_unset=True)
if "secret" in updates:
updates["secret"] = updates["secret"] or None
if updates:
await _validate_agent_id(
session=session,

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
from datetime import datetime
from uuid import UUID
from pydantic import field_validator
from sqlmodel import SQLModel
from app.schemas.common import NonEmptyStr
@@ -12,6 +13,14 @@ from app.schemas.common import NonEmptyStr
RUNTIME_ANNOTATION_TYPES = (datetime, UUID, NonEmptyStr)
def _normalize_secret(v: str | None) -> str | None:
"""Normalize blank/whitespace-only secrets to None."""
if v is None:
return None
stripped = v.strip()
return stripped or None
class BoardWebhookCreate(SQLModel):
"""Payload for creating a board webhook."""
@@ -20,6 +29,8 @@ class BoardWebhookCreate(SQLModel):
agent_id: UUID | None = None
secret: str | None = None
_normalize_secret = field_validator("secret", mode="before")(_normalize_secret)
class BoardWebhookUpdate(SQLModel):
"""Payload for updating a board webhook."""
@@ -29,6 +40,8 @@ class BoardWebhookUpdate(SQLModel):
agent_id: UUID | None = None
secret: str | None = None
_normalize_secret = field_validator("secret", mode="before")(_normalize_secret)
class BoardWebhookRead(SQLModel):
"""Serialized board webhook configuration."""