feat: complete Epic 1 production foundation

This commit is contained in:
2026-08-25 01:24:11 +03:00
parent 767428436d
commit 182bde8ac0
298 changed files with 35719 additions and 5299 deletions
@@ -0,0 +1,412 @@
#![allow(dead_code, unused_imports)]
use super::common::*;
use serde_json::Value;
use serial_test::serial;
const WORKSPACE_ID: &str = "ws_default";
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn portable_yaml_v2_is_redacted_and_semantic_replay_is_a_noop() {
let registry = test_registry().await;
let storage_root = test_storage_root("operation-yaml-v2");
let base_url = spawn_admin_api(build_test_app(registry, storage_root)).await;
let client = authorized_client(&base_url).await;
let created = client
.post(format!("{base_url}/operations"))
.json(&test_operation_payload("http://127.0.0.1:9", "portable_v2"))
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
let operation_id = created["operation_id"].as_str().unwrap();
let yaml = client
.get(format!("{base_url}/operations/{operation_id}/export"))
.send()
.await
.unwrap()
.text()
.await
.unwrap();
assert!(yaml.contains("format_version: '2'") || yaml.contains("format_version: 2"));
let parsed: serde_yaml::Value = serde_yaml::from_str(&yaml).unwrap();
let operation = parsed["operation"].as_mapping().unwrap();
for forbidden in ["id", "status", "created_at", "wizard_state", "samples"] {
assert!(!operation.contains_key(serde_yaml::Value::String(forbidden.to_owned())));
}
let replay = client
.post(format!("{base_url}/operations/import?mode=upsert"))
.header("content-type", "application/yaml")
.body(yaml.clone())
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
assert_eq!(replay["operation_id"], operation_id);
assert_eq!(replay["version"], 1);
let changed_yaml = yaml.replace(
"display_name: Create Lead",
"display_name: Portable Changed",
);
assert_ne!(changed_yaml, yaml);
let missing = client
.post(format!("{base_url}/operations/import?mode=upsert"))
.header("content-type", "application/yaml")
.body(changed_yaml.clone())
.send()
.await
.unwrap();
assert_eq!(missing.status(), reqwest::StatusCode::PRECONDITION_REQUIRED);
let missing = missing.json::<Value>().await.unwrap();
assert_eq!(missing["error"]["code"], "operation_precondition_required");
let changed = client
.post(format!("{base_url}/operations/import?mode=upsert"))
.header("content-type", "application/yaml")
.header(
reqwest::header::IF_MATCH,
operation_etag(&client, &base_url, operation_id).await,
)
.body(changed_yaml)
.send()
.await
.unwrap();
assert_eq!(changed.status(), reqwest::StatusCode::OK);
let changed = changed.json::<Value>().await.unwrap();
assert_eq!(changed["version"], 2);
let current_yaml = client
.get(format!("{base_url}/operations/{operation_id}/export"))
.send()
.await
.unwrap()
.text()
.await
.unwrap();
let archived = client
.post(format!("{base_url}/operations/{operation_id}/archive"))
.header(
reqwest::header::IF_MATCH,
operation_etag(&client, &base_url, operation_id).await,
)
.send()
.await
.unwrap();
assert!(archived.status().is_success());
let replay = client
.post(format!("{base_url}/operations/import?mode=upsert"))
.header("content-type", "application/yaml")
.body(current_yaml)
.send()
.await
.unwrap();
assert_eq!(replay.status(), reqwest::StatusCode::CONFLICT);
assert!(replay.text().await.unwrap().contains("operation_archived"));
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn hostile_and_oversized_yaml_fail_before_mutation_without_echoing_canary() {
let registry = test_registry().await;
let storage_root = test_storage_root("operation-yaml-hostile");
let base_url = spawn_admin_api(build_test_app(registry.clone(), storage_root)).await;
let client = authorized_client(&base_url).await;
let canary = "yaml-secret-canary-never-reflect";
let hostile = format!(
"format_version: '2'\nkind: operation\noperation:\n name: bad\n unknown_secret: {canary}\n"
);
let response = client
.post(format!("{base_url}/operations/import"))
.header("content-type", "application/yaml")
.body(hostile)
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
let body = response.text().await.unwrap();
assert!(!body.contains(canary));
assert!(body.contains("operation_yaml_invalid"));
let body: Value = serde_json::from_str(&body).unwrap();
assert_eq!(body["error"]["code"], "operation_yaml_invalid");
let oversized = "x".repeat(256 * 1024 + 1);
let response = client
.post(format!("{base_url}/operations/import"))
.header("content-type", "application/yaml")
.body(oversized)
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::PAYLOAD_TOO_LARGE);
let count = registry
.list_operations(&crank_core::WorkspaceId::new(WORKSPACE_ID))
.await
.unwrap()
.len();
assert_eq!(count, 0);
let alias = "format_version: '2'\nkind: operation\noperation: &shared\n name: alias\n";
let response = client
.post(format!("{base_url}/operations/import"))
.header("content-type", "application/yaml")
.body(alias)
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
assert!(
response
.text()
.await
.unwrap()
.contains("operation_yaml_unsupported")
);
let response = client
.post(format!("{base_url}/operations/import"))
.header("content-type", "application/yaml")
.body(vec![0xff, 0xfe, 0xfd])
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
assert!(
response
.text()
.await
.unwrap()
.contains("operation_yaml_invalid")
);
let mut credential_payload = serde_json::to_value(test_operation_payload(
"http://127.0.0.1:9",
"portable_credential_header",
))
.unwrap();
credential_payload["target"]["static_headers"]["X-Auth-Token"] =
Value::String("credential-canary".to_owned());
let created = client
.post(format!("{base_url}/operations"))
.json(&credential_payload)
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
let credential_operation_id = created["operation_id"].as_str().unwrap();
let response = client
.get(format!(
"{base_url}/operations/{credential_operation_id}/export"
))
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
assert!(!response.text().await.unwrap().contains("credential-canary"));
let mut portable = serde_json::to_value(test_operation_payload(
"http://127.0.0.1:9",
"unknown_nested_yaml",
))
.unwrap();
portable.as_object_mut().unwrap().remove("wizard_state");
portable["target"]["unknown_nested"] = Value::String(canary.to_owned());
let document = serde_yaml::to_string(&serde_json::json!({
"format_version": "2",
"kind": "operation",
"operation": portable
}))
.unwrap();
let response = client
.post(format!("{base_url}/operations/import"))
.header("content-type", "application/yaml")
.body(document)
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
assert!(!response.text().await.unwrap().contains(canary));
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn operation_mutations_require_identity_bound_etags_and_versions_are_stable() {
let registry = test_registry().await;
let storage_root = test_storage_root("operation-etag");
let base_url = spawn_admin_api(build_test_app(registry, storage_root)).await;
let client = authorized_client(&base_url).await;
let first = client
.post(format!("{base_url}/operations"))
.json(&test_operation_payload("http://127.0.0.1:9", "etag_first"))
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
let second = client
.post(format!("{base_url}/operations"))
.json(&test_operation_payload("http://127.0.0.1:9", "etag_second"))
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
let first_id = first["operation_id"].as_str().unwrap();
let second_id = second["operation_id"].as_str().unwrap();
let missing = client
.post(format!("{base_url}/operations/{first_id}/archive"))
.send()
.await
.unwrap();
assert_eq!(missing.status(), reqwest::StatusCode::PRECONDITION_REQUIRED);
let missing = missing.json::<Value>().await.unwrap();
assert_eq!(missing["error"]["code"], "operation_precondition_required");
let first_etag = operation_etag(&client, &base_url, first_id).await;
let replay = client
.post(format!("{base_url}/operations/{second_id}/archive"))
.header(reqwest::header::IF_MATCH, first_etag)
.send()
.await
.unwrap();
assert_eq!(replay.status(), reqwest::StatusCode::CONFLICT);
let replay = replay.json::<Value>().await.unwrap();
assert_eq!(replay["error"]["code"], "operation_stale_version");
let v1 = client
.get(format!("{base_url}/operations/{first_id}/versions/1"))
.send()
.await
.unwrap();
assert_eq!(v1.status(), reqwest::StatusCode::OK);
let v1_etag = v1.headers()[reqwest::header::ETAG]
.to_str()
.unwrap()
.to_owned();
let mut update =
serde_json::to_value(test_operation_payload("http://127.0.0.1:9", "etag_first")).unwrap();
update["display_name"] = Value::String("Changed Draft".to_owned());
let updated = client
.patch(format!("{base_url}/operations/{first_id}"))
.header(
reqwest::header::IF_MATCH,
operation_etag(&client, &base_url, first_id).await,
)
.json(&update)
.send()
.await
.unwrap();
assert_eq!(updated.status(), reqwest::StatusCode::OK);
let v1_after = client
.get(format!("{base_url}/operations/{first_id}/versions/1"))
.send()
.await
.unwrap();
assert_eq!(v1_after.status(), reqwest::StatusCode::OK);
assert_eq!(
v1_after.headers()[reqwest::header::ETAG].to_str().unwrap(),
v1_etag
);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn same_etag_concurrent_patches_have_exactly_one_winner() {
let registry = test_registry().await;
let storage_root = test_storage_root("operation-etag-race");
let base_url = spawn_admin_api(build_test_app(registry.clone(), storage_root)).await;
let client = authorized_client(&base_url).await;
let created = client
.post(format!("{base_url}/operations"))
.json(&test_operation_payload("http://127.0.0.1:9", "etag_race"))
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
let operation_id = created["operation_id"].as_str().unwrap();
let etag = operation_etag(&client, &base_url, operation_id).await;
let mut first =
serde_json::to_value(test_operation_payload("http://127.0.0.1:9", "etag_race")).unwrap();
first["display_name"] = Value::String("first winner candidate".to_owned());
let mut second = first.clone();
second["display_name"] = Value::String("second winner candidate".to_owned());
let url = format!("{base_url}/operations/{operation_id}");
let first_request = client
.patch(&url)
.header(reqwest::header::IF_MATCH, &etag)
.json(&first)
.send();
let second_request = client
.patch(&url)
.header(reqwest::header::IF_MATCH, &etag)
.json(&second)
.send();
let (first_response, second_response) = tokio::join!(first_request, second_request);
let statuses = [
first_response.unwrap().status(),
second_response.unwrap().status(),
];
assert_eq!(
statuses.iter().filter(|status| status.is_success()).count(),
1
);
assert_eq!(
statuses
.iter()
.filter(|status| **status == reqwest::StatusCode::CONFLICT)
.count(),
1
);
let summary = registry
.get_operation_summary(
&crank_core::WorkspaceId::new(WORKSPACE_ID),
&crank_core::OperationId::new(operation_id),
)
.await
.unwrap()
.unwrap();
assert_eq!(summary.current_draft_version, 2);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn operation_rejects_unscoped_auth_profile_reference_before_save() {
let registry = test_registry().await;
let storage_root = test_storage_root("operation-auth-reference");
let base_url = spawn_admin_api(build_test_app(registry, storage_root)).await;
let client = authorized_client(&base_url).await;
let mut payload = serde_json::to_value(test_operation_payload(
"http://127.0.0.1:9",
"missing_auth_profile",
))
.unwrap();
payload["execution_config"]["auth_profile_ref"] =
Value::String("auth_foreign_or_missing".to_owned());
let response = client
.post(format!("{base_url}/operations"))
.json(&payload)
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
let body = response.text().await.unwrap();
assert!(body.contains("operation_auth_profile_invalid"));
assert!(!body.contains("auth_foreign_or_missing"));
}