Complete source 6 engineering workflows and preserve release validation evidence

This commit is contained in:
Codex
2026-09-06 21:49:04 -07:00
parent 2b2d2bc18b
commit 4b6b5fc197
290 changed files with 48271 additions and 1791 deletions
+42 -10
View File
@@ -1065,6 +1065,19 @@ fn check_commands(commands: &[Command]) -> ApiResult<()> {
Ok(())
}
fn check_transition_request(request: &oa_core::transitions::TransitionRequest) -> ApiResult<()> {
if request.sources.len() > 100
|| request.mappings.len() > 200
|| request.communication_endpoints.len() > 200
|| request.resolutions.len() > 400
{
return Err(ApiError::bad_request(
"Transition requests allow at most 100 sources, 200 mappings or communication endpoint decisions and 400 field resolutions.",
));
}
Ok(())
}
async fn preview_transition(
State(state): State<AppState>,
id: ProjectPath,
@@ -1077,21 +1090,38 @@ async fn preview_transition(
let body = bytes(body)?;
blocking(state, move |store| {
let request: oa_core::transitions::TransitionRequest = json_body(&body)?;
if request.sources.len() > 100 || request.mappings.len() > 200 || request.resolutions.len() > 400 {
return Err(ApiError::bad_request("Transition requests allow at most 100 sources, 200 mappings and 400 field resolutions."));
}
check_transition_request(&request)?;
let snapshot = store.checked(id, &expected)?;
let current = &snapshot;
let plan = oa_core::transitions::plan_transition(&current.model, &request)
.map_err(|error| ApiError::new(StatusCode::UNPROCESSABLE_ENTITY, "transition_rejected", error.to_string()))?;
if !plan.commands.is_empty() { check_commands(&plan.commands)?; }
let plan =
oa_core::transitions::plan_transition(&current.model, &request).map_err(|error| {
ApiError::new(
StatusCode::UNPROCESSABLE_ENTITY,
"transition_rejected",
error.to_string(),
)
})?;
if !plan.commands.is_empty() {
check_commands(&plan.commands)?;
}
if plan.conflicts.is_empty() {
let candidate = oa_core::transitions::prepare_transition(&current.model, &plan)
.map_err(|error| ApiError::new(StatusCode::UNPROCESSABLE_ENTITY, "transition_rejected", error.to_string()))?;
.map_err(|error| {
ApiError::new(
StatusCode::UNPROCESSABLE_ENTITY,
"transition_rejected",
error.to_string(),
)
})?;
PreparedProject::from_command(current, candidate)?;
}
Ok(response(current, StatusCode::OK, json!({"base_revision":current.revision,"plan":plan})))
}).await
Ok(response(
current,
StatusCode::OK,
json!({"base_revision":current.revision,"plan":plan}),
))
})
.await
}
#[derive(Deserialize)]
@@ -1164,6 +1194,7 @@ fn check_semantic_request(request: &oa_core::semantic::SemanticTransitionRequest
});
if transition.sources.len() > 100
|| transition.mappings.len() > 200
|| transition.communication_endpoints.len() > 200
|| transition.resolutions.len() > 400
|| request.traces.len() > 100
|| request.references.len() > 5_000
@@ -1173,7 +1204,7 @@ fn check_semantic_request(request: &oa_core::semantic::SemanticTransitionRequest
|| request.accepted_impacts.len() > 200
{
return Err(ApiError::bad_request(
"Semantic transitions allow at most 100 sources/traces/reviews, 200 mappings/candidates/accepted impacts, 400 prose resolutions and 5,000 reference mappings or combined facet resolutions/resets.",
"Semantic transitions allow at most 100 sources/traces/reviews, 200 mappings/communication endpoint decisions/candidates/accepted impacts, 400 prose resolutions and 5,000 reference mappings or combined facet resolutions/resets.",
));
}
Ok(())
@@ -1271,6 +1302,7 @@ async fn commit_transition(
let body = bytes(body)?;
blocking(state, move |store| {
let request: TransitionApplyRequest = json_body(&body)?;
check_transition_request(&request.plan.request)?;
let snapshot = store.checked(id, &expected)?;
let current = &snapshot;
if current.revision != request.base_revision {