S7 — Consume LNbits sidecar bunker (was: NIP-46 bunker option) #21
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?
Part of #13. Closes gap G6 in full (
Account.prvkeyreadable from DB) and the residual part of G5.2026-05-26 — no longer "future / optional"
aiolabs/lnbits#9was reframed 2026-05-25: the bunker is now the steady-state architecture, not a sovereignty escape valve.aiolabs/lnbits#18(filed same day) is the concrete phase-2 plan: sidecarnsecbunkerdon every lnbits host,RemoteBunkerSigneras the defaultsigner_typefor new accounts,LocalSignerretained only as a transitional shim for migrating existing rows.S7 in this repo therefore becomes "consume the bunker once #18 ships." Our role shrinks dramatically — the heavy lifting (NIP-46 client, admin client, scoped-token issuance, NIP-05 publication) lives upstream.
Architecture (revised)
Daily ATM operations are unchanged in pattern from the original S7 sketch: the ATM signs kind-21000 with its own ephemeral keypair (the connection token's client identity), and the bunker mediates the operator-side signing of long-lived events (delegations are gone — replaced by token rows in nsecbunkerd's Prisma DB).
Changes in this repo
Satmachineadmin backend
POST /api/v1/dca/machines/:id/pairbuilds the seed URL by calling the lnbits admin client'screate_tokenAPI (introduced byaiolabs/lnbits#18): The seed URL embeds the returnedbunker_url.dca_machinesgets abunker_connection_idcolumn so we canrevoke_user/ re-issue.resolve_signer(operator_account).sign_event(event). No direct access to operator'sprvkey.Satmachineadmin frontend
revoke_useradmin RPC.LNbits side
aiolabs/lnbits#18. We consume; we don't implement.Acceptance
bunker_admin.create_token→ seed URL embeds the resultingbunker://...?secret=...→ ATM redeems on first boot → kind-21000 round-trip works.RemoteBunkerSignerpost-migration).accounts.prvkeyrows for any operator that owns satmachineadmin machines.Sequencing
Hard-blocked on
aiolabs/lnbits#18. Sprint 3, after Sprint 1 (S0+S1+S5) + Sprint 2 (S2+S3+S4) land. Practically: once lnbits#18 ships nsecbunkerd-on-aio-demo andRemoteBunkerSigner.sign_eventworks end-to-end, S7 here becomes a 1-week consumer-side task instead of a 4-6 week build.Reference
aiolabs/lnbits#9— operator-IdP framing (the why).aiolabs/lnbits#18— sidecar bunker integration (the how). §F is our alignment.github.com/kind-0/nsecbunkerd— the bunker we'll consume; seeOAUTH-LIKE-FLOW.md.~/dev/nostr-protocol/nips/46.md.docs/security-pathway-v1.md§5.1, §6.S7 — needs follow-up edit reflecting that the bunker is standard, not optional.S7 — NIP-46 bunker option (operator nsec off LNbits' DB)to S7 — Consume LNbits sidecar bunker (was: NIP-46 bunker option)Partial shipment — 2026-05-31
The runtime nip44 path of S7 just shipped on
v2-bitspirevia PR #30 commitdcb7de0(refactor(v2): cassette transport — signer.nip44_* migration). What's done, what's left:Shipped
cassette_transport.publish_to_atm+decrypt_and_parse_state_eventno longer readaccount.prvkeydirectly. They go throughresolve_signer(account).nip44_encrypt(...)/signer.nip44_decrypt(...)per thelnbits.core.signers.base.NostrSignerABC.RemoteBunkerSignerand the nsec never leaves the bunker process; the transitional LocalSigner-with-prvkey path uses the hand-rollednip44.pyimpl via_nip44_decrypt_via_signer's fallback. Same wire output either way._sign_as_operatorsimplified toawait signer.sign_event(event)— previously had a broken-but-permanent ImportError fallback masquerading as the pre-#17 compatibility path (theSignerErrorimport actually fails at the package root; the errors live in.base).NsecBunkerTimeoutError→CassetteEventTransientError(consumer retries on next poll, does NOT advancestate_event_id);NsecBunkerRpcError/SignerUnavailableError→ terminalCassetteEventDecodeError(log + skip).Pending — full S7 closure still needs
POST /api/v1/dca/machines/:id/pairper the original AC). Returns a one-shot seed URL embedding a bunkerbunker://connection URL. Depends onaiolabs/lnbits#18admin-client surface — that's landed for individualRemoteBunkerSigner.provision(Greg got migrated this way), but the per-machinecreate_tokenflow withperms=["sign_event:21000"]+ 30-day expiry isn't wired through satmachineadmin yet.dca_machines.bunker_connection_id+bunker_token_expires_atcolumns. New schema migration (m009?). Lets the operator see the expiry + a "Re-pair" button.bunker_admin.revoke_usercall.provision-atm.shside: stop acceptingATM_PRIVATE_KEY=<operator nsec>; consume the seed URL via--seed-urlflag.RemoteBunkerSigner. Today only Greg is migrated (lnbits coord-log2026-05-30T22:00Z); the LocalSigner transitional fallback in_nip44_*_via_signercovers the rest. The fallback retires when this AC clears.accounts.prvkeyrows for any operator that owns satmachineadmin machines." Easy SQL check; meaningful only once item 5 is done.Reference
dcb7de0feat/cassette-config-v1aiolabs/lnbitsPR #38 (the lnbits-side nip44 ABC this consumes)2026-05-31T07:10Zdocuments the call-shape contract this migration consumes against.Keep open until items 1-6 above are addressed.
➡️ Migrated to aiolabs/spirekeeper#12 (aiolabs/spirekeeper#12).
The v2-bitspire line of this extension now lives in its own repo,
aiolabs/spirekeeper. Tracking for this issue continues there; closing here. (Issue numbers were reassigned in the new repo.)