commit c756ac7cf655165f196da3f03d8169060f92225a Author: Padreug Date: Sun Jul 19 00:16:23 2026 +0200 chore: scaffold chatelet LNbits extension Nostr-native room rentals (Airbnb-style) for the castle. Establishes the extension manifest, license, README with the design overview, and static + template placeholders. No booking logic yet — subsequent commits build the model, schema, arbiter, Nostr layer, API, tasks, and wiring bottom-up. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f92351 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +__pycache__/ +*.py[cod] +*.egg-info/ +.venv/ +node_modules/ +*.sqlite3 +.DS_Store diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cc60ed4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 aiolabs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ae7536d --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# 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:** 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. + +## 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`](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 + +- [`docs/data-model.md`](docs/data-model.md) — tables, entities, lifecycle +- [`docs/event-flow.md`](docs/event-flow.md) — who publishes what, when (with sequence diagram) +- [`docs/adr-0001-nostr-event-model.md`](docs/adr-0001-nostr-event-model.md) — why these kinds + +## 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 +``` diff --git a/config.json b/config.json new file mode 100644 index 0000000..b4dd31c --- /dev/null +++ b/config.json @@ -0,0 +1,23 @@ +{ + "id": "chatelet", + "version": "0.1.0", + "name": "Chatelet", + "repo": "https://git.atitlan.io/aiolabs/chatelet", + "short_description": "Nostr-native room rentals (Airbnb-style) for LNbits", + "description": "", + "tile": "/chatelet/static/image/chatelet.png", + "min_lnbits_version": "1.4.0", + "contributors": [ + { + "name": "padreug", + "uri": "https://git.atitlan.io/padreug", + "role": "Author" + } + ], + "images": [], + "license": "MIT", + "paid_features": "", + "tags": ["Merchant", "Nostr"], + "donate": "", + "hidden": false +} diff --git a/static/js/index.js b/static/js/index.js new file mode 100644 index 0000000..e586d16 --- /dev/null +++ b/static/js/index.js @@ -0,0 +1,15 @@ +// Chatelet operator admin page — placeholder. +// Quasar 2 + Vue 3 as UMD globals (no build step). Remember: no +// self-closing tags in UMD templates, and use :style bindings (not