feat: reject legacy plugin runtime manifests
This commit is contained in:
+108
-17
@@ -1853,6 +1853,39 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_raw_wasm_package_is_rejected_not_active_or_eligible() {
|
||||
let dir = tempdir().unwrap();
|
||||
let workspace = dir.path();
|
||||
fs::create_dir_all(workspace.join(".yoi/plugins")).unwrap();
|
||||
write_stored_zip(
|
||||
&workspace.join(".yoi/plugins/legacy.yoi-plugin"),
|
||||
&[
|
||||
("plugin.toml", plugin_legacy_manifest("legacy").as_bytes()),
|
||||
("plugin.wasm", b"not wasm"),
|
||||
],
|
||||
);
|
||||
|
||||
let snapshot = inspect_snapshot(workspace, &PluginConfig::default());
|
||||
let legacy = select_item(&snapshot, "project:legacy").unwrap();
|
||||
assert_eq!(legacy.status, "rejected");
|
||||
assert!(!legacy.discovered);
|
||||
assert!(!legacy.configured);
|
||||
assert!(legacy.enabled_surfaces.is_empty());
|
||||
assert!(legacy.diagnostics.iter().any(|diagnostic| {
|
||||
diagnostic.kind == "api"
|
||||
&& diagnostic.message.contains("legacy raw wasm")
|
||||
&& diagnostic.message.contains("wasm-component")
|
||||
}));
|
||||
|
||||
let list_output = render_list_snapshot_human(&snapshot).unwrap();
|
||||
assert!(list_output.contains("project:legacy [rejected]"));
|
||||
assert!(!list_output.contains("project:legacy [active]"));
|
||||
let show_output = render_item_human(legacy).unwrap();
|
||||
assert!(show_output.contains("status: rejected"));
|
||||
assert!(show_output.contains("legacy raw wasm"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn configured_invalid_or_incompatible_package_is_rejected_not_missing() {
|
||||
let dir = tempdir().unwrap();
|
||||
@@ -1867,7 +1900,7 @@ mod tests {
|
||||
&workspace.join(".yoi/plugins/incompat.yoi-plugin"),
|
||||
&[
|
||||
("plugin.toml", incompatible_manifest.as_bytes()),
|
||||
("plugin.wasm", b"not wasm"),
|
||||
("plugin.component.wasm", b"not wasm"),
|
||||
],
|
||||
);
|
||||
let mut config = PluginConfig::default();
|
||||
@@ -1934,7 +1967,7 @@ mod tests {
|
||||
fs::create_dir_all(workspace.join(".yoi/plugins")).unwrap();
|
||||
write_stored_zip(
|
||||
&workspace.join(".yoi/plugins/no_manifest.yoi-plugin"),
|
||||
&[("plugin.wasm", b"not wasm")],
|
||||
&[("plugin.component.wasm", b"not wasm")],
|
||||
);
|
||||
let missing_runtime_manifest = plugin_manifest_missing_runtime_entry("missing_runtime");
|
||||
write_stored_zip(
|
||||
@@ -2140,7 +2173,7 @@ mod tests {
|
||||
plugin_manifest("echo", "echo", "object", &["echo"]),
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(plugin.join("plugin.wasm"), b"not wasm").unwrap();
|
||||
fs::write(plugin.join("plugin.component.wasm"), b"not wasm").unwrap();
|
||||
|
||||
let human = render_check(&plugin, &PluginCliArgs::default()).unwrap();
|
||||
assert!(human.contains("[active]"));
|
||||
@@ -2163,6 +2196,42 @@ mod tests {
|
||||
assert_eq!(value["safety"]["no_plugin_execution"], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_check_rejects_legacy_raw_wasm_package() {
|
||||
let dir = tempdir().unwrap();
|
||||
let plugin = dir.path().join("legacy");
|
||||
fs::create_dir_all(&plugin).unwrap();
|
||||
fs::write(plugin.join("plugin.toml"), plugin_legacy_manifest("legacy")).unwrap();
|
||||
fs::write(plugin.join("plugin.wasm"), b"not wasm").unwrap();
|
||||
|
||||
let report = build_check_report(&plugin);
|
||||
assert_eq!(report.status, "rejected");
|
||||
assert!(report.diagnostics.iter().any(|diagnostic| {
|
||||
diagnostic.kind == "api"
|
||||
&& diagnostic.message.contains("legacy raw wasm")
|
||||
&& diagnostic.message.contains("wasm-component")
|
||||
}));
|
||||
let human = render_check_report(&report, &PluginCliArgs::default()).unwrap();
|
||||
assert!(human.contains("[rejected]"));
|
||||
assert!(human.contains("legacy raw wasm"));
|
||||
let json = render_check_report(
|
||||
&report,
|
||||
&PluginCliArgs {
|
||||
json: true,
|
||||
..PluginCliArgs::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let value: serde_json::Value = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(value["status"], "rejected");
|
||||
assert!(
|
||||
value["diagnostics"][0]["message"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.contains("wasm-component")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_check_rejects_invalid_manifest_and_missing_runtime_artifact() {
|
||||
let dir = tempdir().unwrap();
|
||||
@@ -2228,7 +2297,7 @@ mod tests {
|
||||
plugin_manifest("echo", "echo", "object", &["echo"]),
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(plugin.join("plugin.wasm"), b"not wasm").unwrap();
|
||||
fs::write(plugin.join("plugin.component.wasm"), b"not wasm").unwrap();
|
||||
let first = dir.path().join("first.yoi-plugin");
|
||||
let second = dir.path().join("second.yoi-plugin");
|
||||
|
||||
@@ -2466,9 +2535,9 @@ surfaces = ["tool"]
|
||||
permissions = [{{ kind = "surface", surface = "tool" }}, {{ kind = "tool", name = "Echo" }}]
|
||||
|
||||
[runtime]
|
||||
kind = "wasm"
|
||||
entry = "missing.wasm"
|
||||
abi = "yoi-plugin-wasm-1"
|
||||
kind = "wasm-component"
|
||||
component = "missing.component.wasm"
|
||||
world = "yoi:plugin/tool@1.0.0"
|
||||
|
||||
[[tools]]
|
||||
name = "Echo"
|
||||
@@ -2500,9 +2569,9 @@ surfaces = ["tool"]
|
||||
permissions = [{{ kind = "surface", surface = "tool" }}, {permissions}]
|
||||
|
||||
[runtime]
|
||||
kind = "wasm"
|
||||
entry = "plugin.wasm"
|
||||
abi = "yoi-plugin-wasm-1"
|
||||
kind = "wasm-component"
|
||||
component = "plugin.component.wasm"
|
||||
world = "yoi:plugin/tool@1.0.0"
|
||||
|
||||
[[tools]]
|
||||
name = "{tool_name}"
|
||||
@@ -2512,6 +2581,28 @@ input_schema = {{ type = "{schema_type}" }}
|
||||
)
|
||||
}
|
||||
|
||||
fn plugin_legacy_manifest(id: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
schema_version = 1
|
||||
id = "{id}"
|
||||
name = "{id}"
|
||||
version = "0.1.0"
|
||||
surfaces = ["tool"]
|
||||
|
||||
[runtime]
|
||||
kind = "wasm"
|
||||
entry = "plugin.wasm"
|
||||
abi = "yoi-plugin-wasm-1"
|
||||
|
||||
[[tools]]
|
||||
name = "Echo"
|
||||
description = "Legacy raw wasm tool"
|
||||
input_schema = {{ type = "object" }}
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
||||
fn write_plugin_package(workspace: &Path, id: &str) -> String {
|
||||
let manifest = format!(
|
||||
r#"
|
||||
@@ -2523,9 +2614,9 @@ surfaces = ["tool"]
|
||||
permissions = [{{ kind = "surface", surface = "tool" }}, {{ kind = "tool", name = "Echo" }}]
|
||||
|
||||
[runtime]
|
||||
kind = "wasm"
|
||||
entry = "plugin.wasm"
|
||||
abi = "yoi-plugin-wasm-1"
|
||||
kind = "wasm-component"
|
||||
component = "plugin.component.wasm"
|
||||
world = "yoi:plugin/tool@1.0.0"
|
||||
|
||||
[[tools]]
|
||||
name = "Echo"
|
||||
@@ -2547,9 +2638,9 @@ surfaces = ["tool"]
|
||||
permissions = [{{ kind = "surface", surface = "tool" }}, {{ kind = "tool", name = "Echo" }}, {{ kind = "tool", name = "Other" }}]
|
||||
|
||||
[runtime]
|
||||
kind = "wasm"
|
||||
entry = "plugin.wasm"
|
||||
abi = "yoi-plugin-wasm-1"
|
||||
kind = "wasm-component"
|
||||
component = "plugin.component.wasm"
|
||||
world = "yoi:plugin/tool@1.0.0"
|
||||
|
||||
[[tools]]
|
||||
name = "Echo"
|
||||
@@ -2573,7 +2664,7 @@ input_schema = {{ type = "object" }}
|
||||
&package,
|
||||
&[
|
||||
("plugin.toml", manifest.as_bytes()),
|
||||
("plugin.wasm", b"not wasm"),
|
||||
("plugin.component.wasm", b"not wasm"),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user