Checkpoint source 7 workflows and in-progress diagram authoring redesign
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s
Preserve current core, source, REST, desktop, recovery, documentation and validation work, including AGENTS.md and the development summary. This is a work-in-progress checkpoint: the new compact palette has outstanding compilation errors and native acceptance; earlier passing gates retain their documented scope.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! HTTP admission limits must reject endpoint decisions before transition planning.
|
||||
//! HTTP admission limits reject bounded explicit decisions before planning.
|
||||
use super::*;
|
||||
use oa_core::{semantic::SemanticTransitionRequest, transitions::*};
|
||||
|
||||
@@ -28,7 +28,7 @@ async fn unchanged(server: &TestServer, before: &StoredProject, disk: &Path, byt
|
||||
assert_eq!(std::fs::read(disk).unwrap(), bytes);
|
||||
}
|
||||
|
||||
async fn endpoint_limit(semantic: bool) {
|
||||
async fn decision_limit(semantic: bool, operations: bool) {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let mut model = Project::empty();
|
||||
@@ -40,19 +40,24 @@ async fn endpoint_limit(semantic: bool) {
|
||||
let disk = directory.path().join(format!("{id}.json"));
|
||||
let bytes = std::fs::read(&disk).unwrap();
|
||||
let transition = TransitionRequest::new(TransitionDirection::OaToSa, vec![source]);
|
||||
let (route, mut request, decision_path, applied_decision_path) = if semantic {
|
||||
let decision_name = if operations {
|
||||
"operation_omissions"
|
||||
} else {
|
||||
"communication_endpoints"
|
||||
};
|
||||
let (route, mut request, decision_parent, applied_decision_parent) = if semantic {
|
||||
(
|
||||
"semantic-transitions",
|
||||
serde_json::to_value(SemanticTransitionRequest::new(transition)).unwrap(),
|
||||
"/transition/communication_endpoints",
|
||||
"/plan/request/transition/communication_endpoints",
|
||||
"/transition",
|
||||
"/plan/request/transition",
|
||||
)
|
||||
} else {
|
||||
(
|
||||
"transitions",
|
||||
serde_json::to_value(transition).unwrap(),
|
||||
"/communication_endpoints",
|
||||
"/plan/request/communication_endpoints",
|
||||
"",
|
||||
"/plan/request",
|
||||
)
|
||||
};
|
||||
// Obtain a real prepared envelope first: apply must enforce the same bound,
|
||||
@@ -67,12 +72,24 @@ async fn endpoint_limit(semantic: bool) {
|
||||
// Syntactically typed but semantically inapplicable decisions deliberately
|
||||
// distinguish capacity admission (400) from core semantic rejection (422 or
|
||||
// a preview containing conflicts). The bound counts entries, not unique IDs.
|
||||
let decision = CommunicationEndpointDecision {
|
||||
source,
|
||||
source_port: CommunicationPortChoice::Reuse { port: source },
|
||||
target_port: CommunicationPortChoice::Reuse { port: source },
|
||||
let decision = if operations {
|
||||
json!(OperationOmission {
|
||||
source,
|
||||
rationale: "Explicitly abstract technical operation".into()
|
||||
})
|
||||
} else {
|
||||
json!(CommunicationEndpointDecision {
|
||||
source,
|
||||
source_port: CommunicationPortChoice::Reuse { port: source },
|
||||
target_port: CommunicationPortChoice::Reuse { port: source },
|
||||
})
|
||||
};
|
||||
*request.pointer_mut(decision_path).unwrap() = json!(vec![decision.clone(); 200]);
|
||||
request
|
||||
.pointer_mut(decision_parent)
|
||||
.unwrap()
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.insert(decision_name.into(), json!(vec![decision.clone(); 200]));
|
||||
let response = post(&server, id, &format!("{route}/preview"), &etag, &request).await;
|
||||
let status = response.status();
|
||||
let body: Value = response.json().await.unwrap();
|
||||
@@ -83,8 +100,17 @@ async fn endpoint_limit(semantic: bool) {
|
||||
unchanged(&server, &before, &disk, &bytes).await;
|
||||
|
||||
let over_limit = json!(vec![decision; 201]);
|
||||
*request.pointer_mut(decision_path).unwrap() = over_limit.clone();
|
||||
*plan.pointer_mut(applied_decision_path).unwrap() = over_limit;
|
||||
request
|
||||
.pointer_mut(decision_parent)
|
||||
.unwrap()
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.insert(decision_name.into(), over_limit.clone());
|
||||
plan.pointer_mut(applied_decision_parent)
|
||||
.unwrap()
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.insert(decision_name.into(), over_limit);
|
||||
for (operation, body) in [("preview", request), ("apply", plan)] {
|
||||
let response = post(&server, id, &format!("{route}/{operation}"), &etag, &body).await;
|
||||
let status = response.status();
|
||||
@@ -97,8 +123,9 @@ async fn endpoint_limit(semantic: bool) {
|
||||
assert_eq!(error["code"], "invalid_request", "{error}");
|
||||
let detail = error["detail"].as_str().unwrap().to_lowercase();
|
||||
assert!(
|
||||
detail.contains("200") && detail.contains("endpoint"),
|
||||
"Capacity rejection must identify endpoint decisions: {error}"
|
||||
detail.contains("200")
|
||||
&& detail.contains(if operations { "omission" } else { "endpoint" }),
|
||||
"Capacity rejection must identify the bounded decisions: {error}"
|
||||
);
|
||||
unchanged(&server, &before, &disk, &bytes).await;
|
||||
}
|
||||
@@ -110,10 +137,20 @@ async fn endpoint_limit(semantic: bool) {
|
||||
|
||||
#[tokio::test]
|
||||
async fn ordinary_transition_endpoint_decision_limit_rejects_201_without_mutation() {
|
||||
endpoint_limit(false).await;
|
||||
decision_limit(false, false).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn semantic_transition_endpoint_decision_limit_rejects_201_without_mutation() {
|
||||
endpoint_limit(true).await;
|
||||
decision_limit(true, false).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn ordinary_transition_operation_omission_limit_rejects_201_without_mutation() {
|
||||
decision_limit(false, true).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn semantic_transition_operation_omission_limit_rejects_201_without_mutation() {
|
||||
decision_limit(true, true).await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user