docs: finish the LNbits-era doc sweep across docs/ + .claude/skills/

Second + final batch of the doc refresh. README + CLAUDE went out in
8c9ae29; deploy/nixos/README + obsolete-flow flags in 924844f. This
commit covers everything left.

docs/machine-installation.md
  Was describing a manual AppImage scp deploy + a `lamassu-kiosk`
  systemd unit that hasn't been the deployment path for months.
  Replaced with a high-level "what the pipeline does and why"
  overview that points at deploy/nixos/README.md for the full
  command-by-command walkthrough. Includes the BATM3 chassis-mod
  note (custom Dell OptiPlex retrofit, not a stock Dell).

docs/architecture-comparison.md
  Rewrote the comparison to be lamassu-server (≤ v8.1.5) vs bitSpire
  (LNbits-backed) instead of the original lamassu-server vs LP-backed
  lamassu-next framing. Updated the cash-out + cash-in flow diagrams
  to show the actual nostr-transport path (LNbits-bundled nostrrelay
  extension at ws://<host>:5001/nostrrelay/test, no separate strfry
  container). Replaced the migration-path section with a softer
  "when to choose what" framing that includes Lamassu's current
  commercial offering as a legitimate third option. Added a header
  pointer to the Acknowledgements section.

docs/business-model.md
  Light touch-ups: Lightning.Pub → LNbits where it appeared, swapped
  the [[ndebit-cash-in-flow]] link for [[architecture-comparison]],
  noted the kind-30078 service beacon for availability broadcasts.

docs/device-configuration.md
  Dropped "Lamassu" branding from the machine-model headings
  (Sintra / tejo / douro / batm3 are referenced by hardware identity
  here, not by Lamassu's product line). Added the Sintra-specific
  ttyS4-vs-placeholder-ttyS1..3 gotcha we hard-learned during the
  first flash. Corrected the BATM3 entry: stock GeneralBytes chassis
  with a Dell OptiPlex 9030 AIO motherboard physically grafted in,
  NOT a Dell out of the box. Updated the example /dev/ttyJ* symlink
  output to match what a healthy Sintra actually shows.

docs/adr/001-hal-architecture.md
  ADRs are historical artifacts — kept the original decision text
  intact. Added a postscript noting:
    - The package rename @lamassu/hal → @bitSpire/hal
    - The v8.1.5 boundary on any lamassu-machine source-tree
      references (Lamassu's 2024-01-26 license transition)
    - That the "Remaining Work" list is complete and the first
      successful Sintra hardware integration ran on 2026-05-13

.claude/skills/lightning-check.md
  Rewrote end-to-end. Was Lightning.Pub-flavoured with CLINK kinds
  21001/21002 as the primary flows; now validates the LNbits nostr-
  transport surface (kind-21000 envelope, NIP-44 v2 encryption,
  subscribe_payments filter discipline, lnurlw link composition).
  Preserved a --clink mode for the still-live kind-21003 operator-
  management surface. Includes a "what to check" rubric for cash-out
  vs cash-in flows that mirrors the actual code in
  apps/machine/src/services/lightning.ts.

.claude/skills/hal-check.md
  Two pivots: (1) acknowledge ADR-001's TypeScript-not-Rust choice
  and reframe all the safety checklists in TS-flavour (type safety,
  discriminated unions, single-writer serial, bounded emitters)
  instead of Rust-flavour (unsafe, borrow checker). (2) Add explicit
  v8.1.5 provenance boundary plus a "forbidden operations" section
  that prohibits diffing or porting from v8.1.6+ lamassu-machine
  source. Updated the port-validation source-reference table to
  list TS file paths under packages/hal/ instead of Rust paths.

.claude/skills/docs.md
  @lamassu/* → @bitSpire/*. Replaced the Lightning.Pub mermaid
  diagram with a current cash-out flow showing the nostr-transport
  RPC + subscribe_payments push path. Left the createOffer noffer
  example in the API-docs template section since it's illustrative
  ("here's what a good TSDoc block looks like") rather than current
  reference documentation.

.claude/skills/test.md
  One-line: @lamassu/nostr-client → @bitSpire/nostr-client in the
  pnpm-filter example.

deploy/nixos/README.md
  Single touch-up: clarified the douro/batm3 hardware-module comments
  to reflect that BATM3 is a custom-installed Dell board in a
  GeneralBytes BATM3 chassis (not a Dell OEM).

Files NOT touched in this sweep (intentionally):
  - packages/hal/src/**/*.ts attribution comments — those reference
    "lamassu-machine" in their port-source headers. Those are
    factually accurate (the drivers ARE ported from there, up to
    v8.1.5) and constitute necessary license/attribution metadata.
    Editing them would erase the provenance trail.
  - .claude/skills/{nostr-check,security}.md — already protocol-
    neutral, no LP/lamassu references to clean up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-14 08:25:18 +02:00
commit 53b0d382e8
10 changed files with 692 additions and 792 deletions

View file

@ -1,338 +1,306 @@
# Architecture Comparison: Nostr-Native vs Traditional Lamassu
# Architecture Comparison: bitSpire vs Traditional Lamassu
This document compares the Nostr-native Lightning ATM architecture (Lamassu Next) with the traditional lamassu-server/machine implementation to help operators evaluate the transition.
This document compares the bitSpire architecture — a Nostr-native Lightning ATM talking to LNbits over the nostr-native-transport — with the traditional `lamassu-server` + `lamassu-machine` architecture. The goal is to help an operator evaluating an open-source Lightning ATM stack understand what they're choosing between.
## Executive Summary
> A note on prior art: bitSpire's hardware drivers and cash-flow state machine derive from Lamassu Industries AG's open-source `lamassu-machine` and `lamassu-server` projects up to and including the v8.1.5 release line (the last published under a fully-open license). Lamassu [transitioned to a proprietary source-available license](https://blog.lamassu.is/updates-to-our-lamassu-software-license/) on 2024-01-26; bitSpire does **not** incorporate code from v8.1.6 or later and is not affiliated with Lamassu Industries AG. See the [Acknowledgements](../README.md#acknowledgements) section of the top-level README.
| Aspect | Traditional (lamassu-server) | Nostr-Native (lamassu-next) |
| ------------------------ | ---------------------------- | ---------------------------------- |
| **Communication** | Custom WebSocket protocol | Nostr relay (NIP-01) |
| **Identity** | Server-issued credentials | Cryptographic keypairs (npub/nsec) |
| **Account System** | PostgreSQL + custom auth | Lightning.Pub (Nostr-native) |
| **Payment Protocol** | Direct LND RPC | CLINK protocol (kinds 21001-21003) |
| **Infrastructure** | Server + DB + Admin UI | Relay (optional self-hosted) |
| **Wallet Compatibility** | Lamassu-specific | Any CLINK-compatible wallet |
## Executive summary
| Aspect | Traditional (`lamassu-server` ≤ v8.1.5) | bitSpire |
|---|---|---|
| **Software license** | AGPL-3.0 (v8.1.5); v8.1.6+ is proprietary SLA | AGPL-3.0 |
| **Communication** | Custom WebSocket + GraphQL over HTTPS | Nostr kind-21000 events (NIP-01, NIP-44 v2) over a relay |
| **Identity** | Server-issued client certs | Nostr keypairs (`nsec`/`npub`) |
| **Account system** | PostgreSQL + custom auth | LNbits wallet auto-created from ATM's nostr pubkey |
| **Payment protocol** | Direct LND RPC | BOLT11 (cash-out) + LNURL-withdraw (cash-in) |
| **Server infrastructure** | App server + DB + Admin UI | A relay + an LNbits instance (both can be one container) |
| **Wallet compatibility** | Any Lightning wallet (cash-out); custom flow for cash-in | Any Lightning wallet (BOLT11 + LNURL-withdraw — both widely supported) |
| **State location** | Centralized in PostgreSQL | Distributed: LNbits holds Lightning state, ATM holds session state |
---
## Traditional Architecture (lamassu-server/machine)
### Overview
## Traditional architecture (lamassu-server / lamassu-machine, v8.1.5)
```
┌─────────────────┐ WebSocket ┌─────────────────────┐
│ ATM Machine │◄─────────────────────────►│ lamassu-server │
│ (lamassu-machine)│ │ │
└─────────────────┘ │ ┌───────────────┐ │
│ │ PostgreSQL │ │
┌─────────────────┐ HTTPS │ └───────────────┘ │
│ Admin UI │◄─────────────────────────►│ │
│ (React SPA) │ GraphQL │ ┌───────────────┐ │
└─────────────────┘ │ │ LND │ │
│ └───────────────┘ │
┌─────────────────┐ │ │
│ Customer Wallet │◄── Lightning Invoice ─────│ ┌───────────────┐ │
│ (any LN wallet) │ │ │ Compliance │ │
└─────────────────┘ │ │ Services │ │
│ └───────────────┘ │
└─────────────────────┘
┌──────────────────┐ WebSocket ┌─────────────────────┐
│ ATM (kiosk) │◄──────────────────────────►│ lamassu-server │
│ lamassu-machine │ client-cert auth │ │
└──────────────────┘ │ ┌───────────────┐ │
│ │ PostgreSQL │ │
┌──────────────────┐ HTTPS │ └───────────────┘ │
│ Admin UI │◄──────────────────────────►│ │
│ (React SPA) │ GraphQL │ ┌───────────────┐ │
└──────────────────┘ │ │ LND │ │
│ └───────────────┘ │
┌──────────────────┐ │ │
│ Customer Wallet │◄── Lightning Invoice ──────│ ┌───────────────┐ │
│ (any LN wallet) │ │ │ Compliance │ │
└──────────────────┘ │ │ Services │ │
│ └───────────────┘ │
└─────────────────────┘
```
### Components
| Component | Description |
| ------------------- | ------------------------------------------------ |
| **lamassu-server** | Node.js Express + Apollo GraphQL backend |
| **lamassu-machine** | Node.js kiosk application with hardware drivers |
| **PostgreSQL** | Central database for transactions, users, config |
| **Admin UI** | React dashboard for fleet management |
| **LND** | Lightning Network Daemon for payments |
| Component | Description |
|---|---|
| `lamassu-server` | Node.js (Express + Apollo GraphQL) backend |
| `lamassu-machine` | Node.js kiosk app with hardware drivers |
| PostgreSQL | Central DB for transactions, users, config |
| Admin UI | React dashboard for fleet management |
| LND | Lightning Network Daemon for payments |
### Communication Flow
### Cash-out flow
1. Machine boots and authenticates with server via client certificate
2. Server pushes configuration and state via WebSocket
3. Customer initiates transaction at machine
4. Machine requests invoice/address from server
1. Machine boots, authenticates via client cert
2. Server pushes config + state over WebSocket
3. Customer initiates cash-out at machine
4. Machine asks server for an invoice
5. Server creates invoice via LND, stores in PostgreSQL
6. Customer pays invoice
7. Server detects payment, updates database
8. Server notifies machine to dispense cash
9. Transaction logged in PostgreSQL for compliance
6. Customer pays the invoice
7. Server polls LND, detects payment, updates DB
8. Server notifies machine to dispense
9. Compliance services log the transaction
### Characteristics
- **Centralized**: All state lives in server's PostgreSQL
- **Operator-managed**: Requires significant infrastructure
- **Custom protocol**: WebSocket messages are Lamassu-specific
- **Tight coupling**: Machine depends entirely on server availability
- **Compliance-ready**: Built-in KYC/AML features
- **Centralized**: all state in `lamassu-server`'s PostgreSQL
- **Operator-managed**: requires real infrastructure (server, DB, certs, monitoring)
- **Tightly coupled**: machine doesn't transact if server is unreachable
- **Compliance-ready**: KYC/AML hooks built in (relevant in regulated jurisdictions)
---
## Nostr-Native Architecture (lamassu-next)
### Overview
## bitSpire architecture
```
┌─────────────────┐ ┌─────────────────┐
│ ATM Machine │ │ Customer │
│ (npub_atm) │ │ Wallet │
└────────┬────────┘ │ (npub_user) │
│ └────────┬────────┘
│ NIP-01 events │
│ NIP-44 encrypted │ CLINK protocol
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Nostr Relay │
│ (strfry, nostr-rs, etc.) │
└─────────────────────────────────────────────────────────────────┘
│ │
│ Kind 21000 (RPC) │
│ Kind 21001-21003 (CLINK) │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Lightning.Pub │ │ Lightning.Pub │
│ (ATM account) │◄── Lightning Payment ─────►│ (User account) │
└────────┬────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ LND │
└─────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ ATM (kiosk) │ │ Customer wallet │
│ npub_atm │ │ (any LN wallet) │
└────────┬─────────┘ └────────┬─────────┘
│ kind-21000 │
│ NIP-44 v2 encrypted │ BOLT11
▼ │ LNURL-withdraw
┌───────────────────────────────┐ │
│ Nostr Relay │ │
│ (LNbits' bundled │ │
│ nostrrelay extension, or │ │
│ any standalone relay) │ │
└────────────────┬──────────────┘ │
│ │
│ kind-21000 RPC + push │
▼ │
┌───────────────────────┐ ◄──────────────────────┘
│ LNbits │ BOLT11 settle / LNURLw redeem
│ ┌──────────────────┐ │
│ │ FakeWallet (dev) │ │
│ │ or LND/CLN/etc. │ │
│ └──────────────────┘ │
└───────────────────────┘
```
### Components
| Component | Description |
| ------------------- | ----------------------------------------------- |
| **Nostr Relay** | Message broker (strfry, nostr-rs-relay) |
| **Lightning.Pub** | Nostr-native account system wrapping LND |
| **ATM Machine** | Tauri + Vue 3 kiosk identified by npub |
| **Customer Wallet** | Any CLINK-compatible wallet (ShockWallet, etc.) |
| Component | Description |
|---|---|
| Nostr relay | Message broker. In the dev compose, this is LNbits's bundled `nostrrelay` extension at `ws://<host>:5001/nostrrelay/test`. Production can use any standalone relay both peers subscribe to |
| LNbits | Lightning wallet platform; runs the `nostr-native-transport` branch. Auto-creates a wallet on first contact from any nostr pubkey |
| ATM machine | Electron + Vue 3 kiosk identified by its `npub`. Signing key IS the credential to LNbits |
| Customer wallet | Any LN wallet that handles BOLT11 (cash-out) and LNURL-withdraw (cash-in) — most do |
### Communication Flow (Cash-In Example)
### Cash-out flow (customer pays ATM, gets cash)
1. ATM generates ephemeral keypair or uses persistent npub
2. Customer scans QR containing `ndebit` (debit authorization)
3. Customer's wallet connects to relay, finds ATM's Lightning.Pub
4. Wallet creates invoice via Lightning.Pub RPC (kind 21000)
5. Wallet sends debit request (kind 21002) to ATM's npub
6. ATM verifies request, approves payment
7. Lightning.Pub pays invoice, returns preimage
8. ATM detects payment confirmation
9. ATM dispenses cash
10. Transaction recorded as Nostr event (optional)
1. ATM publishes a kind-21000 event to LNbits: `{rpc_name: "create_invoice", body: {amount: <sats>, memo: "..."}}`
2. LNbits replies on the same relay with the BOLT11 invoice
3. ATM displays the BOLT11 as a QR
4. Customer scans, pays from any LN wallet
5. LNbits's Lightning backend (FakeWallet / LND / CLN / etc.) settles the payment
6. LNbits pushes a kind-21000 settlement event to the ATM, filtered by `payment_hash`
7. ATM dispenses cash
### Cash-in flow (customer hands ATM cash, gets sats)
1. ATM publishes `lnurlw_create_link` (kind-21000) to LNbits with `{uses: 1, max_withdrawable: <sats>}`
2. LNbits replies with a `WithdrawLink` (a `unique_hash` plus metadata)
3. ATM composes the callback URL: `{LNBITS_HTTP_URL}/withdraw/api/v1/lnurl/{unique_hash}` and bech32-encodes it as an LNURL
4. ATM displays the LNURL as a QR
5. Customer scans with any LNURL-withdraw-capable wallet, redeems it
6. LNbits settles the withdrawal via its Lightning backend
7. LNbits pushes a kind-21000 settlement event to the ATM, filtered by `tag="withdraw"` + `link_id`
8. ATM marks the session complete (cash already physically accepted earlier in the flow)
### Characteristics
- **Decentralized**: No single server owns state
- **Interoperable**: Standard protocols (Nostr, CLINK, Lightning)
- **Keypair identity**: ATM is identified by npub, not server account
- **Loose coupling**: ATM can work with any relay/Lightning.Pub
- **Privacy-first**: No central transaction logs required
- **Decentralized message layer**: any nostr relay works, no proprietary protocol
- **No admin tokens on the kiosk**: the ATM's signing key IS the credential — there are no HTTP API tokens or client certs to leak. LNbits derives the calling identity from the event signature.
- **Loose coupling**: ATM and LNbits don't need to share a network segment; only a relay both reach
- **Privacy-first**: no central transaction logs unless the operator builds them. LNbits stores its own ledger, but bitSpire writes no user-identifying data anywhere on its side.
---
## Detailed Comparison
## Detailed comparison
### 1. Infrastructure Requirements
### 1. Infrastructure requirements
| Requirement | Traditional | Nostr-Native |
| -------------------- | ------------------------------------ | -------------------------------- |
| **Server Hardware** | Dedicated server (4+ GB RAM, SSD) | Optional (can use public relays) |
| **Database** | PostgreSQL (backup, maintenance) | None required |
| **SSL Certificates** | Required (client certs for machines) | Not required |
| **Domain Name** | Required | Optional |
| **Static IP** | Recommended | Not required |
| **Firewall Rules** | Complex (multiple ports) | Simple (outbound WebSocket only) |
| Requirement | Traditional | bitSpire |
|---|---|---|
| Server hardware | Dedicated server (4+ GB RAM, SSD) | An LNbits instance (1 GB RAM is plenty in production) |
| Database | PostgreSQL (operator managed) | LNbits's SQLite (or its configured DB; LNbits manages it) |
| Client TLS | Required (client certs per machine) | Not required (signature-based auth over a nostr relay) |
| Domain | Required | Optional (only if exposing LNbits HTTP for LNURL redemption from the public internet) |
| Static IP | Recommended | Not required |
| Firewall | Multiple inbound ports | Outbound WebSocket to a relay; inbound only on the LNbits HTTP port for LNURL callbacks |
**Advantage: Nostr-Native** - Dramatically simpler infrastructure. An operator can start with public relays and self-host later.
**Edge: bitSpire.** A single-container LNbits with FakeWallet is enough for an operator to evaluate the whole stack end-to-end.
### 2. Security Model
### 2. Security model
| Aspect | Traditional | Nostr-Native |
| -------------------- | ------------------------------- | ------------------------ |
| **Machine Auth** | Client certificates | Keypair (nsec) |
| **Message Security** | TLS | NIP-44 encryption |
| **Identity Theft** | Steal cert + key | Steal nsec only |
| **Compromise Scope** | All machines if server breached | Individual machine only |
| **Key Storage** | Server manages | Machine manages own keys |
| Aspect | Traditional | bitSpire |
|---|---|---|
| Machine auth | Client certificates | Nostr signing key |
| Transport security | TLS | NIP-44 v2 (XChaCha20 + HMAC-SHA256) |
| Compromise scope | Server breach exposes all machines | One machine's `nsec` compromises only that machine |
| Key storage | Server manages | Machine manages its own keys (`/var/lib/bitspire/.env`, mode 0600) |
| Revocation | CA-style cert revocation | Operator can stop honoring a pubkey at the LNbits layer; no fleet-wide blast radius |
**Advantage: Nostr-Native** - Compromise of one machine doesn't affect others. No central point of failure.
**Edge: bitSpire.** No central authority that, if compromised, exposes the whole fleet. Per-machine compromise stays contained.
### 3. Payment Flow
### 3. Payment flow
| Aspect | Traditional | Nostr-Native |
| ------------------------ | ---------------------- | ------------------------------ |
| **Invoice Creation** | Server creates via LND | Lightning.Pub via Nostr RPC |
| **Payment Detection** | Server polls LND | Subscription to payment events |
| **Wallet Compatibility** | Any Lightning wallet | CLINK-compatible wallets |
| **Offline Capability** | None | Cashu ecash (planned) |
| **Payment Protocol** | BOLT11 only | BOLT11 + CLINK + noffer |
| Aspect | Traditional | bitSpire |
|---|---|---|
| Invoice creation | Server creates via LND | LNbits creates via its Lightning backend, returned over kind-21000 |
| Payment detection | Server polls LND | LNbits pushes a settlement event over kind-21000 (`subscribe_payments` filtered by `payment_hash`) |
| Cash-in detection | Custom flow | LNbits pushes a `tag="withdraw"` + `link_id` event when the LNURL is redeemed |
| Wallet compatibility | Any BOLT11 wallet | Any BOLT11 wallet (cash-out) + any LNURL-withdraw wallet (cash-in) |
| Offline capability | None | Cashu ecash (placeholder package, not yet wired) |
**Mixed**: Traditional has broader wallet compatibility today. Nostr-Native enables advanced features (ndebit, noffer) but requires CLINK wallets.
**Tied.** Both architectures end up using BOLT11 + LNURL-withdraw at the customer-wallet boundary. The difference is on the ATM side: traditional polls a server it owns; bitSpire subscribes to a push channel on a wallet it shares with anyone who can reach the relay.
### 4. Operator Experience
### 4. Operator experience
| Aspect | Traditional | Nostr-Native |
| ----------------------- | ------------------------------- | -------------------------- |
| **Setup Time** | Hours (server, DB, certs) | Minutes (connect to relay) |
| **Maintenance** | DB backups, updates, monitoring | Minimal |
| **Fleet Management** | Admin UI (full-featured) | Dashboard (planned) |
| **Transaction History** | PostgreSQL queries | Nostr event queries |
| **Configuration** | Server-pushed | Local or relay-stored |
| Aspect | Traditional | bitSpire |
|---|---|---|
| Setup time | Hours (provision server, DB, TLS, cert each machine) | Minutes (run an LNbits instance + a relay; flash + provision each ATM) |
| Maintenance | DB backups, server updates, monitoring | Update LNbits + the bitSpire ATMs (the latter auto-upgrades from the `dev` branch nightly) |
| Fleet management | Mature Admin UI | Per-ATM `journalctl`; centralized dashboard is planned, not built |
| Transaction history | PostgreSQL queries | Per-ATM `/var/lib/bitspire/state.db` (SQLite); operator-side aggregation is on them to build |
| Configuration | Server-pushed | Per-ATM `.env` written via `provision-atm.sh` |
**Mixed**: Traditional has mature tooling. Nostr-Native is simpler but dashboard is still in development.
**Mixed.** Traditional has mature operator tooling. bitSpire is simpler to stand up but the fleet-management story is currently "ssh + scripts" rather than a UI.
### 5. Customer Experience
### 5. Customer experience
| Aspect | Traditional | Nostr-Native |
| ----------------------- | ------------------------ | ----------------------- |
| **Cash-In** | Scan invoice, pay | Scan ndebit, authorize |
| **Cash-Out** | Enter phone, receive SMS | Scan noffer, receive |
| **Wallet Requirements** | Any Lightning wallet | CLINK-compatible wallet |
| **Account Required** | Sometimes (compliance) | Never |
| **Transaction Speed** | ~10 seconds | ~5 seconds |
| Aspect | Traditional | bitSpire |
|---|---|---|
| Cash-out | Scan BOLT11, pay | Scan BOLT11, pay |
| Cash-in | Varies by deployment (LNURL-withdraw common, sometimes custom) | Scan LNURL-withdraw QR, redeem |
| Wallet requirements | Any LN wallet for cash-out | Any LN wallet for cash-out + any LNURL-w wallet for cash-in |
| Account required | Sometimes (compliance) | Never |
| Transaction speed | ~10 seconds | ~3-5 seconds (push-based; no server polling delay) |
**Advantage: Nostr-Native** - Faster, more private, no accounts. But requires specific wallet support.
**Tied on protocol; slight edge to bitSpire on speed** because LNbits push events skip the polling cycle that traditional setups have between LND and the application server.
### 6. Compliance & Regulation
### 6. Compliance & regulation
| Aspect | Traditional | Nostr-Native |
| -------------------- | ----------------------- | --------------------- |
| **KYC Integration** | Built-in | Not included |
| **Transaction Logs** | PostgreSQL | Optional Nostr events |
| **Audit Trail** | Comprehensive | Operator-defined |
| **Reporting** | Admin UI exports | Custom tooling needed |
| **Regulatory Fit** | Designed for compliance | Privacy-first design |
| Aspect | Traditional | bitSpire |
|---|---|---|
| KYC integration | Built-in | Not included |
| Transaction logs | PostgreSQL (server) | Per-ATM SQLite + whatever LNbits records on its side |
| Audit trail | Comprehensive | Operator-defined; LNbits's ledger is the canonical Lightning-side record |
| Reporting | Admin UI exports | Custom tooling needed |
| Regulatory fit | Designed for KYC/AML jurisdictions | Privacy-first design; suits jurisdictions without identity-collection requirements |
**Advantage: Traditional** - If you need KYC/AML, traditional is ready. Nostr-Native assumes jurisdictions without these requirements.
**Edge: Traditional** if you need built-in compliance. bitSpire targets KYC-free operation; operators in regulated jurisdictions would need to add compliance hooks themselves.
### 7. Resilience & Availability
### 7. Resilience & availability
| Aspect | Traditional | Nostr-Native |
| --------------------------- | ---------------------- | ------------------------- |
| **Server Down** | All machines offline | Machines continue working |
| **Network Partition** | Transactions fail | Can use multiple relays |
| **Database Corruption** | Catastrophic | No database to corrupt |
| **Recovery** | Restore from backup | Re-sync from relay |
| **Geographic Distribution** | Single server location | Relay anywhere |
| Aspect | Traditional | bitSpire |
|---|---|---|
| Server down | All machines stop transacting | Machines stop transacting if LNbits is down; relay outage means RPCs hang |
| Network partition | Transactions fail | Can connect to multiple relays for failover |
| Database corruption | Catastrophic (cascading impact across fleet) | LNbits-side issue affects only the affected operator's wallet; per-ATM SQLite is local and independent |
| Recovery | Restore from backup | LNbits-side restore is its concern; ATMs come back up clean by re-reading `.env` |
| Geographic distribution | Single server | LNbits can be regional; relays can be anywhere |
**Advantage: Nostr-Native** - No single point of failure. Machines are autonomous.
**Edge: bitSpire** for blast-radius reasons. LNbits-side failures are no worse than `lamassu-server`-side failures, but bitSpire's per-ATM state is genuinely isolated.
### 8. Development & Extensibility
### 8. Development & extensibility
| Aspect | Traditional | Nostr-Native |
| --------------------------- | ----------------- | ------------------------- |
| **Codebase** | Large monolith | Modular packages |
| **Protocol** | Proprietary | Open standards |
| **Third-party Integration** | Custom API needed | Standard Nostr/CLINK |
| **Community** | Lamassu operators | Nostr + Bitcoin ecosystem |
| **Forkability** | Complex | Straightforward |
| Aspect | Traditional | bitSpire |
|---|---|---|
| Codebase | Large monolith (`lamassu-server` is hundreds of files) | Modular workspace; ATM, transport client, HAL, state machine are separate packages |
| Protocol | Custom WebSocket schema | NIP-01 + NIP-44 v2 + a thin documented kind-21000 envelope |
| Third-party integration | Custom API needed | Any nostr/Lightning client can talk to LNbits over the transport |
| Community | Lamassu operators (and ex-operators after the license change) | Nostr + Bitcoin ecosystem; LNbits community |
| Forkability | Complex (server + machine are coupled) | Straightforward (replace any one package without touching the others) |
**Advantage: Nostr-Native** - Open protocols mean broader ecosystem participation.
**Edge: bitSpire.** Open protocols mean a wider ecosystem of compatible clients, wallets, and tools.
---
## Migration Path
## When to choose what
### Phase 1: Parallel Operation
### Choose bitSpire if
Run both systems simultaneously:
- You operate in a jurisdiction without mandatory KYC/AML
- You want minimal infrastructure
- You value customer privacy (no PII collection, no central server-side ledger of who-paid-what)
- You're comfortable with emerging tooling (no admin UI yet)
- You want a license that stays open (AGPL-3.0)
- Existing machines continue with lamassu-server
- New machines or test units use lamassu-next
- Compare reliability and customer feedback
### Phase 2: Hybrid Mode
Bridge the systems:
- lamassu-server creates Nostr events for transactions
- Dashboard reads from both PostgreSQL and relay
- Gradual feature parity validation
### Phase 3: Full Migration
Complete transition:
- All machines run lamassu-next firmware
- Retire lamassu-server infrastructure
- Optional: Keep PostgreSQL as read-only archive
### Migration Considerations
| Consideration | Notes |
| -------------------------- | ----------------------------------------------- |
| **Hardware Compatibility** | Same bill validators/dispensers, new software |
| **Customer Education** | May need CLINK-compatible wallet guidance |
| **Operator Training** | Different mental model (events vs database) |
| **Regulatory Review** | Verify compliance in your jurisdiction |
| **Rollback Plan** | Keep lamassu-server available during transition |
---
## Trade-offs & Honest Assessment
### Where Nostr-Native Excels
1. **Simplicity**: No server to manage, no database to backup
2. **Privacy**: No central transaction logs
3. **Resilience**: No single point of failure
4. **Interoperability**: Works with any CLINK wallet
5. **Speed**: Direct relay communication is faster
6. **Cost**: No server hosting costs (can use public relays)
### Where Traditional May Be Better
1. **Compliance**: Built-in KYC/AML if required by law
2. **Wallet Support**: Works with any Lightning wallet today
3. **Maturity**: Battle-tested over years of operation
4. **Tooling**: Full-featured admin dashboard exists
5. **Support**: Established support channels and documentation
### Current Limitations of Nostr-Native
| Limitation | Status | Mitigation |
| ---------------------- | ------------- | ---------------------------------- |
| Dashboard not complete | In progress | Use relay queries directly |
| Limited wallet support | Growing | ShockWallet, others adopting CLINK |
| No offline mode yet | Cashu planned | Requires internet currently |
| Less documentation | Improving | This document helps |
---
## Conclusion
The Nostr-native architecture represents a fundamental shift from centralized to decentralized ATM operation. It trades the comprehensive compliance features of lamassu-server for simplicity, privacy, and resilience.
**Choose Nostr-Native if:**
- You operate in jurisdictions without KYC requirements
- You want minimal infrastructure overhead
- You value customer privacy
- You're comfortable with emerging technology
**Stick with Traditional if:**
### Stick with `lamassu-server` v8.1.5 if
- You need built-in compliance features
- You require extensive fleet management tools today
- You need to support any Lightning wallet
- You prefer mature, battle-tested systems
- You need a mature admin dashboard *today*
- You have existing infrastructure investment in PostgreSQL + LND tooling
- You're comfortable being on a code line that no longer receives upstream updates (v8.1.5 is the last open release; bug fixes in v8.1.6+ are paid-license-only)
**Consider Hybrid if:**
### Choose Lamassu's current commercial offering if
- You want to evaluate both approaches
- You're planning a gradual migration
- You have mixed regulatory requirements across locations
- You want vendor support, official updates, and a commercial SLA
- You're willing to pay the per-machine subscription
- You operate in a regulated jurisdiction where KYC tooling matters
This last option is outside the scope of this document — see [lamassu.is](https://lamassu.is) for their current commercial terms.
---
## Further Reading
## Trade-offs & honest assessment
- [CLINK Protocol Specification](https://github.com/shocknet/clink)
- [Lightning.Pub Documentation](https://github.com/shocknet/Lightning.Pub)
- [Nostr Protocol (NIP-01)](https://github.com/nostr-protocol/nips/blob/master/01.md)
- [NIP-44 Encryption](https://github.com/nostr-protocol/nips/blob/master/44.md)
- [ndebit Cash-In Flow](./ndebit-cash-in-flow.md)
### Where bitSpire excels
1. **Simplicity** — LNbits + a relay is a much smaller surface than a stateful application server + DB + admin tooling
2. **Privacy** — no central transaction logs by design
3. **Resilience** — no single point of failure on the ATM side; LNbits is replaceable
4. **Interoperability** — works with any BOLT11 / LNURL-withdraw wallet
5. **Speed** — push-based settlement detection skips the LND-poll cycle
6. **Cost** — no Lamassu license fees; no commercial admin-server hosting
### Where traditional (`lamassu-server` ≤ v8.1.5) is still better
1. **Compliance** — built-in KYC/AML if your jurisdiction requires it
2. **Tooling** — mature admin dashboard, fleet management, transaction reporting
3. **Maturity** — battle-tested in production over many years
4. **Documentation** — established support channels for operators (community-maintained for v8.1.5; commercial for v8.1.6+)
### Current limitations of bitSpire
| Limitation | Status | Mitigation |
|---|---|---|
| No fleet dashboard | Planned, not built | Per-ATM `journalctl` + custom scripts |
| Limited transaction reporting | SQLite per ATM | Aggregate via operator-side ETL if needed |
| No offline mode | `@bitSpire/cashu` is a placeholder | Requires LNbits connectivity currently |
| Smaller operator community | Growing | This doc + the README walkthrough |
---
## Further reading
- [LNbits nostr-native-transport docs](https://git.atitlan.io/aiolabs/lnbits) — the wire spec for what's actually happening on kind-21000
- [NIP-01 Nostr basics](https://github.com/nostr-protocol/nips/blob/master/01.md)
- [NIP-44 v2 encryption](https://github.com/nostr-protocol/nips/blob/master/44.md)
- [LUD-03 LNURL-withdraw](https://github.com/lnurl/luds/blob/luds/03.md)
- [CLINK Protocol](./clink-protocol.md) — historical reference, dormant on `dev`
- [bitSpire deployment walkthrough](../deploy/nixos/README.md)
- [machine-installation.md](./machine-installation.md) — high-level deployment overview