commit 09eb8e11bcc1ab0e0a17e23b3f9c98f7e3c5655f
parent 4f12d0215da93b51d2b9a6a8b597c7308938515e
Author: triesap <tyson@radroots.org>
Date: Mon, 15 Jun 2026 22:43:00 -0700
sdk: document product runtime completion
Diffstat:
2 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/crates/sdk/README b/crates/sdk/README
@@ -12,11 +12,18 @@ Configured relay URLs are also opt-in. Product sync publish requires configured
relay URLs and the `relay-runtime` feature.
`sdk.listings().prepare_publish(...)` is side-effect-free and returns a typed
-`ListingPublishPlan`. `sdk.listings().enqueue_publish(...)` signs the authorized
-listing event, ingests it into the local event store, queues signed outbox work,
-and returns a typed `ListingEnqueueReceipt`. The enqueue request uses typed relay
-target and idempotency inputs; omitted idempotency keys are derived
-deterministically.
+`ListingPublishPlan`. `sdk.listings().enqueue_prepared_publish(...)` signs that
+prepared plan, ingests it into the local event store, queues signed outbox work,
+and returns a typed `ListingEnqueueReceipt`. `sdk.listings().enqueue_publish(...)`
+is the convenience path that prepares once and delegates to
+`enqueue_prepared_publish(...)`. The enqueue path uses typed relay target and
+idempotency inputs; omitted idempotency keys are derived deterministically.
+
+Event `created_at` and local observation time are separate contracts. The event
+timestamp remains the authored Nostr event timestamp, while event-store and
+outbox mutation timestamps use the SDK clock at enqueue time. Listing enqueue
+receipts report mutation state with the product names `StoredAndQueued` and
+`AlreadyQueued`.
`sdk.sync().push_outbox(...)` is the product sync entrypoint. It publishes queued
signed outbox work only when relay runtime support and configured relay URLs are
diff --git a/crates/sdk/examples/runtime_local.rs b/crates/sdk/examples/runtime_local.rs
@@ -15,8 +15,8 @@ use radroots_sdk::protocol::listing::{
RadrootsListing, RadrootsListingBin, RadrootsListingProduct,
};
use radroots_sdk::{
- ListingEnqueuePublishRequest, ListingPreparePublishRequest, OrderStatusRequest,
- PushOutboxRequest, RadrootsSdk, RadrootsSdkError, RadrootsSdkTimestamp, SdkRelayTargetPolicy,
+ ListingPreparePublishRequest, OrderStatusRequest, PushOutboxRequest, RadrootsSdk,
+ RadrootsSdkError, RadrootsSdkTimestamp, SdkIdempotencyKey, SdkRelayTargetPolicy,
SdkRelayUrlPolicy,
};
@@ -80,19 +80,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.await?;
let actor = RadrootsActorContext::test(SELLER, [RadrootsActorRole::Seller])?;
let listing = sample_listing();
- let prepare_request = ListingPreparePublishRequest::new(actor.clone(), listing.clone());
- let enqueue_request = ListingEnqueuePublishRequest::new(
- actor,
- listing,
- SdkRelayTargetPolicy::UseConfiguredRelays,
- )
- .try_with_target_relays([RELAY], SdkRelayUrlPolicy::Public)?
- .try_with_idempotency_key("example-1")?;
+ let prepare_request = ListingPreparePublishRequest::new(actor.clone(), listing);
+ let target_relays = SdkRelayTargetPolicy::try_explicit([RELAY], SdkRelayUrlPolicy::Public)?;
+ let idempotency_key = SdkIdempotencyKey::new("example-1")?;
let prepared = sdk.listings().prepare_publish(prepare_request)?;
let enqueue = sdk
.listings()
- .enqueue_publish(enqueue_request, &FixtureSigner::new(SELLER))
+ .enqueue_prepared_publish(
+ &actor,
+ prepared.clone(),
+ target_relays,
+ Some(idempotency_key),
+ &FixtureSigner::new(SELLER),
+ )
.await?;
let push = sdk
.sync()