Future: ATM ↔ operator pairing via seed-URL + WalletSharePermission (+ NIP-46 bunker deep-dive) #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Today (
v2-bitspirebranch, post-a86f8dc), the ATM-to-LNbits authentication path has a known architectural gap. bitSpire is built around the rule "ATM's nostr keypair IS its credential" — when the ATM signs a kind-21000 event with key X, LNbits'nostr_transport.auth.resolve_nostr_auth()either looks up the matching account or, withNEW_ACCOUNTS_ALLOWED=true, auto-creates one. There's no built-in "this ATM belongs to operator Y" linkage.The v2 satmachineadmin design is operator-scoped: 1 LNbits user = 1 operator, with N wallets each owned by that operator. Each machine's settlements land on one of the operator's wallets. The wallet-IDOR fix (commit
3ede66f) enforces_assert_wallet_owned_byin the API.The mismatch: if the ATM generates a fresh keypair on first boot (which is bitSpire's design), LNbits auto-creates a new user — not the operator. The wallet lands on the ATM's auto-created user, not the operator's. Operator's
satmachineadminthen can't reach it (it's not "owned" by them in LNbits' model).Current stopgap (option 1 in design discussion)
The operator's existing nostr keypair is copied onto the ATM during
provision-atm.sh. The ATM signs as the operator. LNbits sees connections from the operator. Wallets live on the operator's account, satmachineadmin works as-is.Use for v1 dev/staging only. This issue tracks the proper fix.
Proposed v2: seed-URL pairing + LNbits WalletSharePermission
Pattern lifted from
aiolabs/lamassu-next#42(fleet management + seed-URL onboarding), adapted for LNbits' WalletSharePermission infrastructure (added on thenostr-transportbranch — seelnbits/core/models/wallets.pyfor the model).Flow
WalletSharePermissionon the operator's wallet (the new bit)Why this is the right model
satmachineadmin._assert_wallet_owned_byworks unchanged.dca_paymentstagged with the ATM's npub; revocation is a one-click event.Scope estimate
nostr-transportbranch)nostr_transportdispatcherWalletSharePermissionon claimwallet_idpaste-in inputlamassu-next/dev)Total ~1–2 weeks across both repos. The lamassu-next #42 issue already has groundwork for the bitSpire side; this issue is the LNbits-flavored implementation.
NIP-46 / Bunker deep-dive (rule in or out)
Before committing to the seed-URL+WalletSharePermission approach above, do a focused investigation of whether NIP-46 (Nostr Connect / Bunker) is the canonical pattern for this use case and we should adopt it instead.
Specific questions to answer
create_invoice/subscribe_paymentson wallet X," that's a real security gain over option 3.Likely outcome (predict before the dive)
Option 3 wins because:
But the dive should prove this rather than assume it. If we find that NIP-46 has matured into the standard for "machine-to-server with scoped auth" and there's tooling/UX advantage, switch.
Action
Before starting implementation of option 3:
Related
aiolabs/satmachineadmin#9— v2 epicaiolabs/satmachineadmin#11— v2 follow-up findingsaiolabs/lamassu-next#42— fleet management + seed-URL bootstrap (bitSpire side; this is the upstream design we'd align with)nostr-transportbranch —WalletSharePermissionmodel is already presentUpdate: LNbits already stores the operator's nostr
prvkeyDiscovered while wiring up option 1 for testing — the
nostr-transportbranch'saccountstable has aprvkeycolumn, and operator accounts created via the standard flow have it populated:Confirmed by querying our local dev DB: the 5 operator-side accounts on the regtest stack all have both
pubkeyANDprvkeypopulated. LNbits is, in effect, already a custodial holder of every user's nostr identity key.What this changes for the bunker deep-dive
The "bunker needs to live somewhere" objection I raised in the original framing of option 3-vs-NIP-46 partly dissolves: LNbits is the natural location for it, because LNbits already has the keys. A NIP-46 bunker endpoint on LNbits would be a thin wrapper around existing data — no new always-on service required.
Specifically, the bunker deep-dive should now also answer:
Should LNbits expose a NIP-46 bunker endpoint as a first-class feature? Given it already holds
prvkeyfor every user, the protocol-level cost of becoming a bunker is small. This isn't ATM-specific — any Nostr-enabled extension on LNbits could benefit (lightning addresses, NIP-98 auth flows, cross-instance comms). The ATM use case is one client of a more general capability.Does exposing
prvkeyfor bunker-style remote signing widen the LNbits trust model in a way operators are NOT already accepting? Currentlyprvkeysits in the DB; if compromised, the attacker already has full custody of the operator's identity. Bunker access doesn't expose new attack surface — it just makes the existing custody explicit and scoped.What this doesn't change for the v1 recommendation
WalletSharePermission (option 3) is still the right answer for ATM ↔ operator pairing because:
But this revelation makes NIP-46 a strictly more interesting general-purpose feature than I framed it. The deep-dive should explicitly evaluate "expose LNbits as a NIP-46 bunker" as a separate decision from "use NIP-46 for ATM pairing."
cc: the original ATM pairing decision is unchanged — go with WalletSharePermission. But this discovery should make the deep-dive worth doing as a standalone investigation regardless of ATM outcome.
Superseded in part by the new security pathway epic at #13. The seed-URL pairing + WalletSharePermission idea folds into S0 (pairing) + S2 (NIP-26 delegation enforcement); the NIP-46 bunker deep-dive folds into S7 (with
aiolabs/lnbits#9as the LNbits-side enabler).Keeping this issue open as the conversational record of the original analysis — content from here informed the structured plan. Close as duplicate once the relevant sub-issues land.
Closing as superseded by the security-pathway epic at #13.
This issue's content has been split across the epic's phased sub-issues:
aiolabs/lnbits#9(reframed 2026-05-25) andaiolabs/lnbits#18(sidecarnsecbunkerdintegration), the canonical pattern is now NIP-46 connection tokens issued by a bunker, not WalletSharePermission. See #14 (S0 — pairing payload swap), #16 (S2 — NIP-46 enforcement), #21 (S7 — consume the bunker).No content lost; consolidating to keep the tree clean.