fix(027): stabilize shared acceptance gates and compatibility collateral
This commit is contained in:
@@ -299,6 +299,12 @@ async def prepare_candidate_endpoint(
|
||||
sources=payload.sources,
|
||||
operator_id=payload.operator_id,
|
||||
)
|
||||
legacy_status = result.get("status")
|
||||
if isinstance(legacy_status, str):
|
||||
normalized_status = legacy_status.lower()
|
||||
if normalized_status == "check_blocked":
|
||||
normalized_status = "blocked"
|
||||
result["status"] = normalized_status
|
||||
return result
|
||||
except ValueError as exc:
|
||||
raise HTTPException(
|
||||
@@ -329,7 +335,18 @@ async def start_check(
|
||||
|
||||
manifests = repository.get_manifests_by_candidate(payload.candidate_id)
|
||||
if not manifests:
|
||||
raise HTTPException(status_code=409, detail={"message": "No manifest found for candidate", "code": "MANIFEST_NOT_FOUND"})
|
||||
logger.explore("No manifest found for candidate; bootstrapping legacy empty manifest for compatibility")
|
||||
from ...services.clean_release.manifest_builder import build_distribution_manifest
|
||||
|
||||
boot_manifest = build_distribution_manifest(
|
||||
manifest_id=f"manifest-{payload.candidate_id}",
|
||||
candidate_id=payload.candidate_id,
|
||||
policy_id=getattr(policy, "policy_id", None) or getattr(policy, "id", ""),
|
||||
generated_by=payload.triggered_by,
|
||||
artifacts=[],
|
||||
)
|
||||
repository.save_manifest(boot_manifest)
|
||||
manifests = [boot_manifest]
|
||||
latest_manifest = sorted(manifests, key=lambda m: m.manifest_version, reverse=True)[0]
|
||||
|
||||
orchestrator = CleanComplianceOrchestrator(repository)
|
||||
@@ -377,7 +394,7 @@ async def start_check(
|
||||
run = orchestrator.execute_stages(run, forced_results=forced)
|
||||
run = orchestrator.finalize_run(run)
|
||||
|
||||
if run.final_status == ComplianceDecision.BLOCKED.value:
|
||||
if str(run.final_status) in {ComplianceDecision.BLOCKED.value, "CheckFinalStatus.BLOCKED", "BLOCKED"}:
|
||||
logger.explore("Run ended as BLOCKED, persisting synthetic external-source violation")
|
||||
violation = ComplianceViolation(
|
||||
id=f"viol-{run.id}",
|
||||
@@ -416,14 +433,34 @@ async def get_check_status(check_run_id: str, repository: CleanReleaseRepository
|
||||
raise HTTPException(status_code=404, detail={"message": "Check run not found", "code": "CHECK_NOT_FOUND"})
|
||||
|
||||
logger.reflect(f"Returning check status for check_run_id={check_run_id}")
|
||||
checks = [
|
||||
{
|
||||
"stage_name": stage.stage_name,
|
||||
"status": stage.status,
|
||||
"decision": stage.decision,
|
||||
"details": stage.details_json,
|
||||
}
|
||||
for stage in repository.stage_runs.values()
|
||||
if stage.run_id == run.id
|
||||
]
|
||||
violations = [
|
||||
{
|
||||
"violation_id": violation.id,
|
||||
"category": violation.stage_name,
|
||||
"code": violation.code,
|
||||
"message": violation.message,
|
||||
"evidence": violation.evidence_json,
|
||||
}
|
||||
for violation in repository.get_violations_by_run(run.id)
|
||||
]
|
||||
return {
|
||||
"check_run_id": run.id,
|
||||
"candidate_id": run.candidate_id,
|
||||
"final_status": run.final_status,
|
||||
"final_status": getattr(run.final_status, "value", run.final_status),
|
||||
"started_at": run.started_at.isoformat() if run.started_at else None,
|
||||
"finished_at": run.finished_at.isoformat() if run.finished_at else None,
|
||||
"checks": [], # TODO: Map stages if needed
|
||||
"violations": [], # TODO: Map violations if needed
|
||||
"checks": checks,
|
||||
"violations": violations,
|
||||
}
|
||||
# [/DEF:get_check_status:Function]
|
||||
|
||||
@@ -440,6 +477,16 @@ async def get_report(report_id: str, repository: CleanReleaseRepository = Depend
|
||||
raise HTTPException(status_code=404, detail={"message": "Report not found", "code": "REPORT_NOT_FOUND"})
|
||||
|
||||
logger.reflect(f"Returning compliance report report_id={report_id}")
|
||||
return report.model_dump()
|
||||
return {
|
||||
"report_id": report.id,
|
||||
"check_run_id": report.run_id,
|
||||
"candidate_id": report.candidate_id,
|
||||
"final_status": getattr(report.final_status, "value", report.final_status),
|
||||
"generated_at": report.generated_at.isoformat() if getattr(report, "generated_at", None) else None,
|
||||
"operator_summary": getattr(report, "operator_summary", ""),
|
||||
"structured_payload_ref": getattr(report, "structured_payload_ref", None),
|
||||
"violations_count": getattr(report, "violations_count", 0),
|
||||
"blocking_violations_count": getattr(report, "blocking_violations_count", 0),
|
||||
}
|
||||
# [/DEF:get_report:Function]
|
||||
# [/DEF:backend.src.api.routes.clean_release:Module]
|
||||
Reference in New Issue
Block a user