commit 77a641133b5545c59afad193775275376fd825aa
parent 73cefddc6d9a7d2bde47a9b3341c5c0419889c02
Author: triesap <tyson@radroots.org>
Date: Thu, 7 May 2026 03:29:23 +0000
cli: gate listing update publish mode
Diffstat:
3 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/src/operation_listing.rs b/src/operation_listing.rs
@@ -119,7 +119,7 @@ impl OperationService<ListingUpdateRequest> for ListingOperationService<'_> {
request.operation_id(),
crate::runtime::listing::update(&config, &args),
)?;
- serialized_operation_result::<ListingUpdateResult, _>(&view)
+ mutation_result::<ListingUpdateResult>(request.operation_id(), &view)
}
}
diff --git a/src/operation_registry.rs b/src/operation_registry.rs
@@ -1155,6 +1155,7 @@ pub fn requires_nostr_relay_publish_mode(operation_id: &str) -> bool {
operation_id,
"farm.publish"
| "listing.publish"
+ | "listing.update"
| "listing.archive"
| "order.submit"
| "order.accept"
@@ -1513,6 +1514,7 @@ mod tests {
let expected = [
"farm.publish",
"listing.publish",
+ "listing.update",
"listing.archive",
"order.submit",
"order.accept",
diff --git a/tests/target_cli.rs b/tests/target_cli.rs
@@ -175,6 +175,88 @@ fn radrootsd_publish_mode_fails_closed_for_direct_relay_publish_paths() {
}
#[test]
+fn radrootsd_publish_mode_fails_closed_for_listing_update() {
+ let sandbox = RadrootsCliSandbox::new();
+ let missing_listing = sandbox.root().join("missing-listing.toml");
+
+ let (output, value) = sandbox.json_output(&[
+ "--format",
+ "json",
+ "--publish-mode",
+ "radrootsd",
+ "listing",
+ "update",
+ missing_listing.to_string_lossy().as_ref(),
+ ]);
+
+ assert!(!output.status.success());
+ assert_eq!(output.status.code(), Some(3));
+ assert_eq!(value["operation_id"], "listing.update");
+ assert_eq!(value["result"], Value::Null);
+ assert_eq!(value["errors"][0]["code"], "operation_unavailable");
+ assert_eq!(value["errors"][0]["detail"]["publish"]["mode"], "radrootsd");
+ assert_eq!(
+ value["errors"][0]["detail"]["publish"]["provider"]["provider_runtime_id"],
+ "radrootsd"
+ );
+ assert_eq!(
+ value["errors"][0]["detail"]["publish"]["provider"]["state"],
+ "unavailable"
+ );
+}
+
+#[test]
+fn listing_update_unavailable_support_exits_nonzero() {
+ let sandbox = RadrootsCliSandbox::new();
+ sandbox.json_success(&["--format", "json", "account", "create"]);
+ let farm = sandbox.json_success(&[
+ "--format",
+ "json",
+ "farm",
+ "create",
+ "--name",
+ "Update Farm",
+ "--location",
+ "farmstand",
+ "--country",
+ "US",
+ "--delivery-method",
+ "pickup",
+ ]);
+ let listing_file = create_listing_draft(&sandbox, "update-unavailable");
+ make_listing_publishable(
+ &listing_file,
+ farm["result"]["config"]["farm_d_tag"]
+ .as_str()
+ .expect("farm d tag"),
+ );
+
+ let (output, value) = sandbox.json_output(&[
+ "--format",
+ "json",
+ "--relay",
+ "ws://127.0.0.1:9",
+ "listing",
+ "update",
+ listing_file.to_string_lossy().as_ref(),
+ ]);
+
+ assert!(!output.status.success());
+ assert_eq!(output.status.code(), Some(3));
+ assert_eq!(value["operation_id"], "listing.update");
+ assert_eq!(value["result"], Value::Null);
+ assert_eq!(value["errors"][0]["code"], "operation_unavailable");
+ assert!(
+ value["errors"][0]["message"]
+ .as_str()
+ .expect("error message")
+ .contains("direct Nostr relay publishing is not implemented for listing update")
+ );
+ assert_no_removed_command_reference(&value, &["listing", "update"]);
+ assert_no_daemon_runtime_reference(&value, &["listing", "update"]);
+}
+
+#[test]
fn removed_order_submit_watch_flag_is_rejected_publicly() {
let output = radroots()
.args(["order", "submit", "--watch"])