mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-20 00:11:34 +00:00
Drop the duplicate-key guard that no tool route can reach
FabroWorkflowVersionCreateParams deserialized `files` through a duplicate-rejecting map, but both production routes (rmcp Parameters and the native LLM tool dispatch) deserialize from an already-parsed serde_json::Value in which duplicate keys have collapsed last-wins. The only test that exercised the guard used serde_json::from_str, the one entry point production never uses, so the safeguard was misleading. Remove the attribute and its byte-level test, and drop the deserialize_unique_map export that existed only for it. The canonical WorkflowVersion wire type keeps its own duplicate-key rejection, which does run on the byte-level HTTP route. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
4b9db26027
commit
70b1090f58
3 changed files with 4 additions and 20 deletions
|
|
@ -21,8 +21,9 @@ pub struct FabroWorkflowVersionCreateParams {
|
|||
#[schemars(with = "String")]
|
||||
pub entrypoint: WorkflowPath,
|
||||
/// All local dependencies, keyed by package-relative path. Values are text
|
||||
/// contents.
|
||||
#[serde(deserialize_with = "fabro_types::deserialize_unique_map")]
|
||||
/// contents. Tool arguments arrive as an already-parsed JSON value on
|
||||
/// every production route, so duplicate keys have collapsed (last wins)
|
||||
/// before this type sees them; there is no byte-level guard to add here.
|
||||
#[schemars(with = "BTreeMap<String, String>")]
|
||||
pub files: BTreeMap<WorkflowPath, String>,
|
||||
}
|
||||
|
|
@ -127,12 +128,6 @@ mod tests {
|
|||
fn workflow_version_request_rejects_unknown_fields_and_invalid_paths() {
|
||||
let valid = json!({"entrypoint": "workflow", "files": {"workflow": "digraph W {}"}});
|
||||
validate(valid.clone()).unwrap();
|
||||
assert!(
|
||||
serde_json::from_str::<FabroWorkflowVersionCreateParams>(
|
||||
r#"{"entrypoint":"workflow","files":{"workflow":"a","workflow":"b"}}"#
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
for field in [
|
||||
"cwd",
|
||||
"url",
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ pub use workflow_path::{
|
|||
};
|
||||
pub use workflow_version::{
|
||||
MAX_WORKFLOW_VERSION_BYTES, MAX_WORKFLOW_VERSION_DEPENDENCIES, MAX_WORKFLOW_VERSION_FILE_BYTES,
|
||||
MAX_WORKFLOW_VERSION_FILES, WorkflowVersion, WorkflowVersionShapeError, deserialize_unique_map,
|
||||
MAX_WORKFLOW_VERSION_FILES, WorkflowVersion, WorkflowVersionShapeError,
|
||||
validate_workflow_source_paths,
|
||||
};
|
||||
pub use workflow_version_id::{WorkflowVersionId, WorkflowVersionIdParseError};
|
||||
|
|
|
|||
|
|
@ -236,17 +236,6 @@ impl<'de> Deserialize<'de> for WorkflowVersion {
|
|||
}
|
||||
}
|
||||
|
||||
/// Deserialize a map while rejecting duplicate keys, which serde would
|
||||
/// otherwise silently collapse to the last value.
|
||||
pub fn deserialize_unique_map<'de, D, K, V>(deserializer: D) -> Result<BTreeMap<K, V>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
K: Deserialize<'de> + Ord + fmt::Display,
|
||||
V: Deserialize<'de>,
|
||||
{
|
||||
UniqueBTreeMap::deserialize(deserializer).map(|map| map.0)
|
||||
}
|
||||
|
||||
struct UniqueBTreeMap<K, V>(BTreeMap<K, V>);
|
||||
|
||||
impl<'de, K, V> Deserialize<'de> for UniqueBTreeMap<K, V>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue