No description
  • Python 83.5%
  • HTML 9.5%
  • JavaScript 6.8%
  • Makefile 0.2%
Find a file
2026-07-19 21:17:11 +00:00
docs docs: document the NIP-17/59 check-in DM flow 2026-07-19 20:34:12 +02:00
nostr feat: NIP-17 gift-wrapped check-in DM on confirmation (#5) 2026-07-19 20:34:12 +02:00
static chore: add extension icon + fix broken tile reference 2026-07-19 23:15:05 +02:00
templates/chatelet chore: scaffold chatelet LNbits extension 2026-07-19 00:16:23 +02:00
tests test: NIP-59 gift wrap structure + crypto round-trip 2026-07-19 20:34:12 +02:00
.gitignore chore: scaffold chatelet LNbits extension 2026-07-19 00:16:23 +02:00
__init__.py feat: relay publish + availability subscription via nostrclient (#2) 2026-07-19 18:09:35 +02:00
config.json chore: add extension icon + fix broken tile reference 2026-07-19 23:15:05 +02:00
crud.py fix: make check-then-hold atomic against concurrent bookings (#4) 2026-07-19 17:08:43 +02:00
LICENSE chore: scaffold chatelet LNbits extension 2026-07-19 00:16:23 +02:00
Makefile chore: add test + lint tooling (pyproject, Makefile) 2026-07-19 17:48:11 +02:00
migrations.py fix: correct schema-qualified CREATE INDEX syntax (breaks SQLite install) 2026-07-19 23:15:05 +02:00
models.py feat: add Room.checkin_instructions + migration 2026-07-19 20:34:12 +02:00
pyproject.toml chore: add test + lint tooling (pyproject, Makefile) 2026-07-19 17:48:11 +02:00
README.md docs: relay-transport (nostrclient) section + dependency note 2026-07-19 18:09:35 +02:00
services.py fix: make check-then-hold atomic against concurrent bookings (#4) 2026-07-19 17:08:43 +02:00
tasks.py feat: NIP-17 gift-wrapped check-in DM on confirmation (#5) 2026-07-19 20:34:12 +02:00
transport_rpcs.py feat: expose Chatelet over the LNbits nostr transport (#1) 2026-07-19 01:30:13 +02:00
views.py feat: REST API + operator admin route 2026-07-19 00:16:57 +02:00
views_api.py refactor: extract booking flow into services.py 2026-07-19 01:30:13 +02:00

Chatelet

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: 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?

No single NIP models a rental-booking flow. Chatelet composes existing NIPs and only invents an event kind where nothing fits:

Concern Mechanism
Room listing NIP-99 classified listing (kind:30402)
Guest's reservation record NIP-78 app data (kind:30078), NIP-44 encrypted
Public availability calendar NIP-52 (kind:31923/31924), no guest PII
Private request → quote → confirm NIP-17/59 giftwrapped DMs
Live "is it free?" query aiolabs band kind:22000/22001 (ephemeral)
Payment / deposit LNbits Lightning invoice

Full rationale in docs/adr-0001-nostr-event-model.md.

The one invariant that matters

LNbits is the booking authority; Nostr events are requests, not locks. Availability is derived from the DB (bookings + blocks), never stored as a positive fact, and a date range is only truly locked when a held booking row is written. Payment — not any Nostr event — promotes a booking to confirmed.

Docs

Layout

config.json        LNbits extension manifest
models.py          data model (pydantic)
migrations.py      schema (ext_chatelet DB)
crud.py            persistence + the availability arbiter
views_api.py       REST surface (shares the booking flow with Nostr)
views.py           operator admin page route
tasks.py           invoice listener (settle) + hold-expiry sweep
nostr/             event kinds, builders, sign/publish/subscribe service
docs/              design docs