From 7b8dd82a6e035e5d1367f1568362c813bca7dd35 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 19 Jul 2026 18:09:35 +0200 Subject: [PATCH] docs: relay-transport (nostrclient) section + dependency note Document the in-process nostrclient publish/subscribe path, the public-vs- encrypted split (encrypted events await bunker/server-signing), and the soft runtime dependency on the nostrclient extension. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD --- README.md | 15 ++++++++++++--- docs/event-flow.md | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae7536d..1ae8a1e 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,18 @@ Nostr-native room rentals for LNbits — an "Airbnb for the castle". List rooms, take booking requests, arbitrate availability, and settle stays over Lightning, with Nostr as the interop layer. -> **Status:** design sketch + scaffold. Data model, migrations, availability -> arbiter, REST surface, and Nostr event model are in place; relay plumbing, -> FX/invoice wiring, and the guest UI are stubbed with `TODO(...)` markers. +> **Status:** functional prototype. Data model, migrations, availability +> arbiter (atomic hold), FX + invoice + settlement, the REST + kind-21000 RPC +> doors, and the nostrclient relay layer (publish + availability queries) are +> in place and tested. The guest UI and encrypted-event delivery pre-bunker +> are the remaining gaps. +> +> **Soft dependency:** publishing/subscribing to relays uses the **nostrclient** +> extension (imported in-process). Install + activate it to reach relays; if +> absent, the booking flow still works over HTTP/RPC and relay publish is +> skipped with a logged warning. Encrypted events (reservation `30078`, check-in +> DMs) additionally need a bunker/server-signing signer (lnbits #18); on a +> LocalSigner they soft-fail until then. ## Why not just reuse an existing NIP? diff --git a/docs/event-flow.md b/docs/event-flow.md index 6b51df2..26b5976 100644 --- a/docs/event-flow.md +++ b/docs/event-flow.md @@ -70,6 +70,33 @@ wallet, so the guest confirms by polling `chatelet_booking_get` until | `1059` | 17/59 | both | Private booking DMs (request → quote → confirm → check-in) | | `22000/22001` | aiolabs | guest/operator | Live availability query + response (ephemeral) | +## Relay transport — nostrclient (in-process) + +Publishing app/discovery events and subscribing to inbound queries go through +the **`nostrclient` extension's** relay manager, imported in-process +(`nostr_client.relay_manager.publish_message(...)` / `.add_subscription(...)`), +the same pattern `spirekeeper`/`nostrmarket` use. This is separate from the +core kind-21000 RPC transport (Door 2): the core pool is RPC-only and can't +publish arbitrary kinds, so app events ride nostrclient. Adds a **soft runtime +dependency** on nostrclient — if it isn't installed, publish/subscribe skip +with a logged warning and the booking flow (HTTP/RPC) is unaffected. + +`nostr/service.py` implements it: + +- **Publish** (`_sign_and_publish`): sign as the operator (`resolve_signer`), + optionally NIP-44-encrypt, then `publish_message`. +- **Subscribe** (`subscribe_inbound`, a permanent task): register a + `kind:22000` subscription, poll `NostrRouter.received_subscription_events`, + answer each with a `kind:22001` reply. + +**Public vs encrypted — what works pre-bunker:** a `LocalSigner` can +`sign_event` but its `nip44_encrypt` raises (bunker-forward by design, lnbits +#18). So **public** events (listing `30402`, calendar `31923`, availability +`22001` — availability is public info, so `22000/22001` are plaintext) publish +today; **encrypted** events (reservation `30078`, and the `#5` check-in DM) +sign-encrypt via the operator signer and soft-fail with a clear log until the +operator has a bunker/server-signing signer. Nothing crashes either way. + ## Happy path ```mermaid