feat(backend): add publish readiness contract and guarded publish flow

add backend readiness contract for publish prechecks

guard publish flow with explicit validation and version-aware checks
make publish behavior more predictable for clients and safer against stale state
This commit is contained in:
greebo
2026-03-19 20:41:08 +03:00
parent 8d4255181b
commit ac3a62f108
8 changed files with 224 additions and 116 deletions

View File

@@ -52,31 +52,14 @@ async def create_draft_pricing_snapshot(
@router.get(
f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/publish-readiness",
response_model=PublishReadinessResponse,
f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/publish-preview",
response_model=PublishPreviewResponse,
)
async def get_draft_publish_readiness(
scheme_id: str,
expected_scheme_version_id: str | None = Query(default=None),
role: str = Depends(require_api_key),
):
scheme, version = await get_current_draft_context(
scheme_id,
expected_scheme_version_id=expected_scheme_version_id,
)
readiness = await build_publish_readiness(
scheme_id=scheme.scheme_id,
scheme_version_id=version.scheme_version_id,
)
return PublishReadinessResponse(**readiness)
@router.get(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/publish-preview", response_model=PublishPreviewResponse)
async def get_publish_preview(
scheme_id: str,
baseline_scheme_version_id: str | None = Query(default=None),
expected_scheme_version_id: str | None = Query(default=None),
refresh: bool = Query(default=False),
expected_scheme_version_id: str | None = Query(default=None),
role: str = Depends(require_api_key),
):
scheme, version = await get_current_draft_context(
@@ -100,7 +83,31 @@ async def get_publish_preview(
)
@router.post(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/remap/preview", response_model=RemapPreviewResponse)
@router.get(
f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/publish-readiness",
response_model=PublishReadinessResponse,
)
async def get_publish_readiness(
scheme_id: str,
expected_scheme_version_id: str | None = Query(default=None),
role: str = Depends(require_api_key),
):
scheme, version = await get_current_draft_context(
scheme_id,
expected_scheme_version_id=expected_scheme_version_id,
)
readiness = await build_publish_readiness(
scheme_id=scheme.scheme_id,
scheme_version_id=version.scheme_version_id,
status=version.status,
)
return PublishReadinessResponse(**readiness)
@router.post(
f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/remap/preview",
response_model=RemapPreviewResponse,
)
async def preview_draft_remap(
scheme_id: str,
payload: RemapPreviewRequest,
@@ -128,7 +135,10 @@ async def preview_draft_remap(
)
@router.post(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/remap/apply", response_model=RemapApplyResponse)
@router.post(
f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/remap/apply",
response_model=RemapApplyResponse,
)
async def apply_draft_remap(
scheme_id: str,
payload: RemapApplyRequest,