feat(backend): add publish readiness contract and pricing diagnostics

add backend readiness contract for publish prechecks

add pricing diagnostics to explain publish-blocking conditions
make publish decisions more explicit and easier to debug for clients
This commit is contained in:
greebo
2026-03-19 20:29:58 +03:00
parent 7b6c12f924
commit 8d4255181b
11 changed files with 251 additions and 301 deletions

View File

@@ -1,40 +1,42 @@
from __future__ import annotations
from fastapi import HTTPException, status
def raise_conflict(*, code: str, message: str, details: dict | None = None) -> None:
def build_error_detail(
*,
code: str,
message: str,
details: dict | None = None,
) -> dict:
payload = {
"code": code,
"message": message,
}
if details:
payload.update(details)
payload["details"] = details
return payload
def raise_conflict(
*,
code: str,
message: str,
details: dict | None = None,
) -> None:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=payload,
detail=build_error_detail(code=code, message=message, details=details),
)
def raise_unprocessable(*, code: str, message: str, details: dict | None = None) -> None:
payload = {
"code": code,
"message": message,
}
if details:
payload.update(details)
def raise_unprocessable(
*,
code: str,
message: str,
details: dict | None = None,
) -> None:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=payload,
)
def raise_publish_not_ready(*, reason: str, details: dict) -> None:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail={
"code": "publish_not_ready",
"message": reason,
"details": details,
},
detail=build_error_detail(code=code, message=message, details=details),
)