commit ee5b0e361da1c8bd09900c2cd53d66271e59921a
parent b08a9a6e98569ebcbcbd9975cb2c959c051fe5a9
Author: triesap <tyson@radroots.org>
Date: Tue, 16 Jun 2026 14:21:57 -0700
sdk: guard product examples and relay policy
Diffstat:
2 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/crates/sdk/README b/crates/sdk/README
@@ -31,6 +31,11 @@ targets already stored on each queued outbox event, so already queued work does
not require configured builder relays. `push_outbox_with_adapter(...)` remains
available for tests and controlled adapter-level substrate checks.
+Relay URL policy is explicit. Public relay URLs must use `wss://`. Local
+development `ws://` relay URLs are accepted only under `SdkRelayUrlPolicy::Localhost`
+and only for `localhost`, `127.0.0.1`, or `[::1]`. Non-local insecure `ws://`
+targets, including private LAN addresses, are rejected.
+
`sdk.orders().status(...)` reads local order projections and returns typed
source, event count, limit state, event IDs, and reducer issues. It is not a
network fetch.
@@ -52,6 +57,22 @@ explicit modules:
Product runtime callers do not need `WireEventParts`. Wire helpers are exposed
only through `protocol::wire`.
+## Examples
+
+Compile the SDK v1 product examples with:
+
+```bash
+cargo check -p radroots_sdk --example sdk_v1_listing_prepare --features runtime
+cargo check -p radroots_sdk --example sdk_v1_local_enqueue_and_mock_sync --features runtime,local-signer
+```
+
+`sdk_v1_listing_prepare` shows `RadrootsSdk::builder()`,
+`ListingPreparePublishRequest`, and `ListingPublishPlan`.
+`sdk_v1_local_enqueue_and_mock_sync` shows localhost relay target selection,
+prepared listing enqueue, `push_outbox_with_adapter(...)` with a mock relay
+adapter, and `OrderStatusRequest`. The examples stay on product APIs and do not
+use `WireEventParts`.
+
SDK v1 does not claim strict NIP-99 Markdown-content interoperability. It emits
and consumes Rad Roots v1 listing and trade event contracts.
diff --git a/crates/sdk/tests/runtime_foundation.rs b/crates/sdk/tests/runtime_foundation.rs
@@ -257,12 +257,42 @@ fn outbox_idempotency_conflict_maps_to_structured_sdk_error() {
}
#[test]
-fn runtime_local_example_stays_on_product_api_boundary() {
- let example = include_str!("../examples/runtime_local.rs");
-
- assert!(example.contains("prepare_publish"));
- assert!(example.contains("push_outbox"));
- assert!(!example.contains("WireEventParts"));
- assert!(!example.contains(".as_wire_parts("));
- assert!(!example.contains(".into_wire_parts("));
+fn sdk_examples_stay_on_product_api_boundary() {
+ let examples = [
+ (
+ "runtime_local",
+ include_str!("../examples/runtime_local.rs"),
+ ),
+ (
+ "sdk_v1_listing_prepare",
+ include_str!("../examples/sdk_v1_listing_prepare.rs"),
+ ),
+ (
+ "sdk_v1_local_enqueue_and_mock_sync",
+ include_str!("../examples/sdk_v1_local_enqueue_and_mock_sync.rs"),
+ ),
+ ];
+
+ for (name, example) in examples {
+ assert!(!example.contains("WireEventParts"), "{name}");
+ assert!(!example.contains("protocol::wire"), "{name}");
+ assert!(!example.contains("events_codec::wire"), "{name}");
+ assert!(!example.contains(".as_wire_parts("), "{name}");
+ assert!(!example.contains(".into_wire_parts("), "{name}");
+ }
+
+ let listing_prepare = include_str!("../examples/sdk_v1_listing_prepare.rs");
+ assert!(listing_prepare.contains("RadrootsSdk::builder()"));
+ assert!(listing_prepare.contains("ListingPreparePublishRequest"));
+ assert!(listing_prepare.contains("prepare_publish"));
+
+ let local_enqueue = include_str!("../examples/sdk_v1_local_enqueue_and_mock_sync.rs");
+ assert!(local_enqueue.contains("RadrootsSdk::builder()"));
+ assert!(local_enqueue.contains("ListingPreparePublishRequest"));
+ assert!(local_enqueue.contains("SdkRelayTargetPolicy"));
+ assert!(local_enqueue.contains("SdkRelayTargetSet"));
+ assert!(local_enqueue.contains("SdkRelayUrlPolicy::Localhost"));
+ assert!(local_enqueue.contains("enqueue_prepared_publish"));
+ assert!(local_enqueue.contains("push_outbox_with_adapter"));
+ assert!(local_enqueue.contains("OrderStatusRequest"));
}