chore: update semantic contracts and git merge handling

This commit is contained in:
2026-03-16 20:34:28 +03:00
parent c53c3f77cc
commit 7e4124bc3f
19 changed files with 480 additions and 257 deletions

View File

@@ -1,8 +1,6 @@
# [DEF:backend.src.api.routes.clean_release_v2:Module]
# @COMPLEXITY: 3
# @SEMANTICS: api, clean-release, v2, headless
# @PURPOSE: Redesigned clean release API for headless candidate lifecycle.
# @LAYER: API
from fastapi import APIRouter, Depends, HTTPException, status
from typing import List, Dict, Any
@@ -18,17 +16,40 @@ from ...services.clean_release.dto import CandidateDTO, ManifestDTO
router = APIRouter(prefix="/api/v2/clean-release", tags=["Clean Release V2"])
# [DEF:ApprovalRequest:Class]
# @COMPLEXITY: 1
# @PURPOSE: Schema for approval request payload.
# @RELATION: USES -> [CandidateDTO]
class ApprovalRequest(dict):
pass
# [/DEF:ApprovalRequest:Class]
# [DEF:PublishRequest:Class]
# @COMPLEXITY: 1
# @PURPOSE: Schema for publication request payload.
# @RELATION: USES -> [CandidateDTO]
class PublishRequest(dict):
pass
# [/DEF:PublishRequest:Class]
# [DEF:RevokeRequest:Class]
# @COMPLEXITY: 1
# @PURPOSE: Schema for revocation request payload.
# @RELATION: USES -> [CandidateDTO]
class RevokeRequest(dict):
pass
# [/DEF:RevokeRequest:Class]
# [DEF:register_candidate:Function]
# @COMPLEXITY: 3
# @PURPOSE: Register a new release candidate.
# @PRE: Payload contains required fields (id, version, source_snapshot_ref, created_by).
# @POST: Candidate is saved in repository.
# @RETURN: CandidateDTO
# @RELATION: CALLS -> [CleanReleaseRepository.save_candidate]
# @RELATION: USES -> [CandidateDTO]
@router.post("/candidates", response_model=CandidateDTO, status_code=status.HTTP_201_CREATED)
async def register_candidate(
payload: Dict[str, Any],
@@ -51,7 +72,14 @@ async def register_candidate(
created_by=candidate.created_by,
status=CandidateStatus(candidate.status)
)
# [/DEF:register_candidate:Function]
# [DEF:import_artifacts:Function]
# @COMPLEXITY: 3
# @PURPOSE: Associate artifacts with a release candidate.
# @PRE: Candidate exists.
# @POST: Artifacts are processed (placeholder).
# @RELATION: CALLS -> [CleanReleaseRepository.get_candidate]
@router.post("/candidates/{candidate_id}/artifacts")
async def import_artifacts(
candidate_id: str,
@@ -75,7 +103,16 @@ async def import_artifacts(
pass
return {"status": "success"}
# [/DEF:import_artifacts:Function]
# [DEF:build_manifest:Function]
# @COMPLEXITY: 3
# @PURPOSE: Generate distribution manifest for a candidate.
# @PRE: Candidate exists.
# @POST: Manifest is created and saved.
# @RETURN: ManifestDTO
# @RELATION: CALLS -> [CleanReleaseRepository.save_manifest]
# @RELATION: CALLS -> [CleanReleaseRepository.get_candidate]
@router.post("/candidates/{candidate_id}/manifests", response_model=ManifestDTO, status_code=status.HTTP_201_CREATED)
async def build_manifest(
candidate_id: str,
@@ -109,7 +146,12 @@ async def build_manifest(
source_snapshot_ref=manifest.source_snapshot_ref,
content_json=manifest.content_json
)
# [/DEF:build_manifest:Function]
# [DEF:approve_candidate_endpoint:Function]
# @COMPLEXITY: 3
# @PURPOSE: Endpoint to record candidate approval.
# @RELATION: CALLS -> [approve_candidate]
@router.post("/candidates/{candidate_id}/approve")
async def approve_candidate_endpoint(
candidate_id: str,
@@ -128,8 +170,13 @@ async def approve_candidate_endpoint(
raise HTTPException(status_code=409, detail={"message": str(exc), "code": "APPROVAL_GATE_ERROR"})
return {"status": "ok", "decision": decision.decision, "decision_id": decision.id}
# [/DEF:approve_candidate_endpoint:Function]
# [DEF:reject_candidate_endpoint:Function]
# @COMPLEXITY: 3
# @PURPOSE: Endpoint to record candidate rejection.
# @RELATION: CALLS -> [reject_candidate]
@router.post("/candidates/{candidate_id}/reject")
async def reject_candidate_endpoint(
candidate_id: str,
@@ -148,8 +195,13 @@ async def reject_candidate_endpoint(
raise HTTPException(status_code=409, detail={"message": str(exc), "code": "APPROVAL_GATE_ERROR"})
return {"status": "ok", "decision": decision.decision, "decision_id": decision.id}
# [/DEF:reject_candidate_endpoint:Function]
# [DEF:publish_candidate_endpoint:Function]
# @COMPLEXITY: 3
# @PURPOSE: Endpoint to publish an approved candidate.
# @RELATION: CALLS -> [publish_candidate]
@router.post("/candidates/{candidate_id}/publish")
async def publish_candidate_endpoint(
candidate_id: str,
@@ -181,8 +233,13 @@ async def publish_candidate_endpoint(
"status": publication.status,
},
}
# [/DEF:publish_candidate_endpoint:Function]
# [DEF:revoke_publication_endpoint:Function]
# @COMPLEXITY: 3
# @PURPOSE: Endpoint to revoke a previous publication.
# @RELATION: CALLS -> [revoke_publication]
@router.post("/publications/{publication_id}/revoke")
async def revoke_publication_endpoint(
publication_id: str,
@@ -212,5 +269,6 @@ async def revoke_publication_endpoint(
"status": publication.status,
},
}
# [/DEF:revoke_publication_endpoint:Function]
# [/DEF:backend.src.api.routes.clean_release_v2:Module]