feat(backend): harden draft, pricing and publish contracts

- unify typed API errors across draft, pricing and publish flows
- add stale draft and publish-state mutation guards
- add publish readiness contract and guarded publish flow
- add sellability reason codes to test seat preview
- add pricing diagnostics and strengthen snapshot/publish lifecycle consistency
This commit is contained in:
greebo
2026-03-19 20:58:14 +03:00
parent ac3a62f108
commit a266f56ddd
6 changed files with 368 additions and 297 deletions

View File

@@ -3,12 +3,17 @@ from __future__ import annotations
from fastapi import HTTPException, status
def raise_conflict(*, code: str, message: str, details: dict | None = None) -> None:
def raise_conflict(
*,
code: str,
message: str,
details: dict | None = None,
) -> None:
payload: dict = {
"code": code,
"message": message,
}
if details:
if details is not None:
payload["details"] = details
raise HTTPException(
@@ -17,13 +22,18 @@ def raise_conflict(*, code: str, message: str, details: dict | None = None) -> N
)
def raise_unprocessable(*, code: str, message: str, details: dict | None = None) -> None:
def raise_unprocessable(
*,
code: str,
message: str,
details: dict | None = None,
) -> None:
payload: dict = {
"code": code,
"message": message,
}
if details:
payload["details"] = details
if details is not None:
payload.update(details)
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,