Commit graph

58 commits

Author SHA1 Message Date
43cfa5d921 feat: background tasks — settle on payment, expire holds
Payment (not any nostr event) is the commit point: the invoice listener
promotes held/awaiting_payment bookings to confirmed, hard-blocks the
dates, and republishes the encrypted reservation object. expire_holds_loop
sweeps lapsed holds every minute so abandoned requests free their dates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:57 +02:00
d5df9ab662 feat: REST API + operator admin route
views_api.py exposes the booking flow over HTTP — availability check,
guest booking request (check-then-hold with canonical amount_sat), room
publish, blocks. REST and Nostr are two doors into the same crud flow;
FX + invoice creation marked TODO. views.py serves the operator page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:57 +02:00
900b682986 feat: nostr event layer (builders + sign/publish service)
Implements ADR-0001. kinds.py pins the allocations; events.py has pure
builders (30402 listing, 30078 encrypted reservation, 31923 blocked-range
calendar, 22001 availability response); service.py signs/encrypts via
resolve_signer (spirekeeper hybrid pattern — no nsec at rest) and sketches
publish + inbound subscription. Relay plumbing marked TODO(relay).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:39 +02:00
f0c24ebba6 docs: ADR-0001 nostr event model
Records the decision to compose standard NIPs (99 listing, 78 reservation,
52 calendar, 17/59 DMs) and reserve aiolabs kind:22000/22001 only for the
ephemeral availability RPC. Documents rejected alternatives (bespoke 2200x
booking record, RSVP-as-booking, deprecated NIP-15) and flags the 22000/1
allocation to register in workspace CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:39 +02:00
e7fabd57bf feat: CRUD + availability arbiter
Room/booking/block persistence, and is_available() — the authority for
whether a range is free: room active AND no occupying booking or block
overlaps [check_in, check_out) (half-open, so back-to-back stays are fine).
expire_stale_holds() frees dates for lapsed unpaid holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:39 +02:00
95e5bcb136 feat: schema migrations
settings/rooms/bookings/blocks in ext_chatelet, with room+status and
payment_hash indexes for the overlap and settle hot paths. Ordinary
migrations (not the fork split — this is aio-original, no upstream to
rebase onto); still idempotent-friendly. No availability table by design.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:23 +02:00
ab892cabec feat: data model
Pydantic entities: ChateletSettings (operator/castle config), Room (a
rentable unit == one NIP-99 listing), Booking (a reservation), Block
(manual owner unavailability), plus availability query/result DTOs.

Two invariants encoded here: amount_sat is the canonical booking total
(never re-derived downstream), and availability is derived, never stored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:23 +02:00
c756ac7cf6 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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 00:16:23 +02:00