feat: relay publish + availability subscription via nostrclient (#2)

Wire the Nostr layer through the nostrclient extension's relay manager
in-process (spirekeeper pattern), replacing the sketch stubs:

- _sign_and_publish: sign as operator (resolve_signer), optional NIP-44
  encrypt, publish via nostr_client.relay_manager.publish_message. Soft-
  fails (logs, returns None) if no operator onboarded, nostrclient absent,
  or signer can't encrypt — never crashes the booking flow.
- publish_listing (30402) + publish_block_calendar (31923): public, work
  today (sign_event only).
- publish_reservation (30078): NIP-44 encrypted to guest; soft-fails on a
  LocalSigner until a bunker/server-signing signer lands (lnbits#18).
- subscribe_inbound: permanent task answering kind:22000 availability
  queries with kind:22001 (plaintext — availability is public info), the
  client-agnostic availability path parallel to the RPC.

events.py: drop the _plaintext scaffolding (service.py encrypts content in
place) and a broken {operator_pubkey} calendar tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
This commit is contained in:
Padreug 2026-07-19 18:09:35 +02:00
commit cf9f8699da
3 changed files with 182 additions and 63 deletions

View file

@ -36,6 +36,15 @@ def chatelet_start():
create_permanent_unique_task("chatelet_hold_expiry", expire_holds_loop)
)
# Inbound Nostr: answer kind:22000 availability queries over relays via
# nostrclient (client-agnostic availability path). Self-backs-off if
# nostrclient isn't installed.
from .nostr.service import subscribe_inbound
scheduled_tasks.append(
create_permanent_unique_task("chatelet_availability_sub", subscribe_inbound)
)
# Expose the booking flow over the core LNbits nostr transport (kind-21000
# RPC) so an HTTP-allergic client can drive Chatelet over relays. Also wire
# the booking-owner resolver so the operator can stream booking