docs: update functional identifier refs to spirekeeper
Some checks failed
ci.yml / docs: update functional identifier refs to spirekeeper (push) Failing after 0s

Runbook SQL (spirekeeper.dca_*), ext URL paths, code-location paths,
and the DB-schema name in docs/CLAUDE/README move to the new identity.
Rewrites the placeholder description.md with a real one. Historical
aiolabs/satmachineadmin#N issue/repo links stay pointing at the
original repo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-13 22:31:21 +02:00
commit 4ac640a499
6 changed files with 142 additions and 143 deletions

View file

@ -7,7 +7,7 @@
## 0 · Why this document exists
Today the satoshimachine code lives at `~/dev/shared/extensions/satmachineadmin` on branch `v2-bitspire`. v2 swapped the legacy Lamassu SSH/PostgreSQL polling model for a Nostrnative one: bitSpire publishes invoices over kind21000 NIP44 v2 events, LNbits pays them, and our extension hooks the resulting `Payment` object.
Today the satoshimachine code lives at `~/dev/shared/extensions/spirekeeper` on branch `v2-bitspire`. v2 swapped the legacy Lamassu SSH/PostgreSQL polling model for a Nostrnative one: bitSpire publishes invoices over kind21000 NIP44 v2 events, LNbits pays them, and our extension hooks the resulting `Payment` object.
The hard truth: the *settlement* itself uses Lightning (so it can't be forged once a preimage lands), but everything *around* the settlement — who the ATM is, what operator it belongs to, what the principal/commission split was, and what fiat was dispensed — currently rides on **mutable, unauthenticated metadata** (`Payment.extra`) plus a **stopgap that has the ATM hold the operator's own Nostr private key**. The latter means physical possession of the ATM = total compromise of the operator's LNbits account.
@ -66,7 +66,7 @@ Lamassu's old answer here was TLS cert pinning. We have a richer toolbox — Nos
register_invoice_listener fires
satmachineadmin/tasks.py:_handle_payment
spirekeeper/tasks.py:_handle_payment
┌─────────────────────────────────┴────────────────────────────┐
▼ ▼
@ -144,7 +144,7 @@ T3, T5, T6 are the ones that keep the hardware honest. T3 + T6 are *the* reason
## 4 · Audit findings — current state inventory
Pulled from the two recent codelevel audits of `~/dev/shared/extensions/satmachineadmin` (operatorscoping inventory) and `~/dev/lnbits/nostr-transport` (transport primitives).
Pulled from the two recent codelevel audits of `~/dev/shared/extensions/spirekeeper` (operatorscoping inventory) and `~/dev/lnbits/nostr-transport` (transport primitives).
### 4.1 What's already strong
@ -307,7 +307,7 @@ None of those need to change. The new layers slot in *above* them.
| **S4 — NIP78 permachine config + fleet roster** | Operator publishes `kind:30078` config + `kind:30000` fleet list. Handler crosschecks ATM npub ∈ fleet; reads maxwithdraw/fee policy from config. | G1, G9 | 1 week | Define config schema; backwardscompat path for preNIP78 machines. |
| **S5 — `sender_pubkey` persistence + signed metadata in Payment.extra** | When the dispatcher writes a Payment row, it stamps `Payment.extra.sender_pubkey`, `delegation_root`, and an HMAC over the key fields keyed by the LNbits server's own secret. Mutation postwrite breaks the HMAC. | G2 (DBside), G5, G6 | 35 days | LNbits PR — fairly localised. |
| **S6 — Rate limiting + rostergated autoaccount** | Autoaccountfromnpub only fires if the npub appears in some operator's NIP78 fleet OR if an explicit "open enrollment" flag is set. Relay/handlerlevel rate limit per pubkey. | G8, G9 | 1 week | LNbits PR. |
| **S7 — NIP46 bunker option** | Operator can pair satmachineadmin with a Bunker (Amber, Nunchuk Custody, etc.). Operator's nsec leaves LNbits' DB; LNbits stores only the bunker connection. | G6, partial G5 | 46 weeks | Largest. Defer until S0S5 land. |
| **S7 — NIP46 bunker option** | Operator can pair spirekeeper with a Bunker (Amber, Nunchuk Custody, etc.). Operator's nsec leaves LNbits' DB; LNbits stores only the bunker connection. | G6, partial G5 | 46 weeks | Largest. Defer until S0S5 land. |
| **S8 — Cashin path** | Wire `is_out=True` cashin handling: LNURLwithdraw with expiration matching the kind21000 invoice TTL, attestation receipt on settle, refund queue for stale links. | G10 | 2 weeks | Out of scope for this security doc but tracked here for completeness. |
Recommended sequencing for the *next sprint*: **S0 + S1 + S5**. They give us the biggest security delta with no upstream LNbits dependency for S0/S1 and a small, wellscoped LNbits patch for S5. S2/S3/S4 are the proper Nostrnative layer and should land in the sprint after.
@ -359,12 +359,12 @@ For an auditor or new contributor doing a walkthrough:
| File | Role | Note |
|---|---|---|
| `~/dev/shared/extensions/satmachineadmin/tasks.py` | LNbits invoice listener. Entry point for all settlements today. | `_handle_payment:56-95` — loadbearing routing. |
| `~/dev/shared/extensions/satmachineadmin/bitspire.py` | Parses Payment.extra. The trust boundary. | `parse_settlement:68-92` — happy vs fallback path. |
| `~/dev/shared/extensions/satmachineadmin/distribution.py` | Threeleg distribution chain. | `process_settlement` — uses claim pattern. |
| `~/dev/shared/extensions/satmachineadmin/crud.py` | Operatorscoped DB layer. | `claim_settlement_for_processing`, `_machine_owned_by`. |
| `~/dev/shared/extensions/satmachineadmin/views_api.py` | 33 routes, all `check_user_exists` except superconfig PUT. | `_assert_wallet_owned_by` is the walletIDOR fix. |
| `~/dev/shared/extensions/satmachineadmin/migrations.py` | Schema. | `dca_settlements` is the audit row; `dca_payments` is the leg row. |
| `~/dev/shared/extensions/spirekeeper/tasks.py` | LNbits invoice listener. Entry point for all settlements today. | `_handle_payment:56-95` — loadbearing routing. |
| `~/dev/shared/extensions/spirekeeper/bitspire.py` | Parses Payment.extra. The trust boundary. | `parse_settlement:68-92` — happy vs fallback path. |
| `~/dev/shared/extensions/spirekeeper/distribution.py` | Threeleg distribution chain. | `process_settlement` — uses claim pattern. |
| `~/dev/shared/extensions/spirekeeper/crud.py` | Operatorscoped DB layer. | `claim_settlement_for_processing`, `_machine_owned_by`. |
| `~/dev/shared/extensions/spirekeeper/views_api.py` | 33 routes, all `check_user_exists` except superconfig PUT. | `_assert_wallet_owned_by` is the walletIDOR fix. |
| `~/dev/shared/extensions/spirekeeper/migrations.py` | Schema. | `dca_settlements` is the audit row; `dca_payments` is the leg row. |
| `~/dev/shocknet/lamassu-next/deploy/nixos/provision-atm.sh` | Where keys land on the ATM today. | `:81-99``VITE_ATM_PRIVATE_KEY` and the Option1 stopgap. |
| `~/dev/lnbits/nostr-transport/lnbits/core/services/nostr_transport/` | LNbits transport handler (upstream we depend on). | NIP44 v2 crypto here; G5/G6/G7 fixes will live here. |
| `~/dev/nostr-protocol/nips/26.md` | Delegation. | Source for S2. |
@ -397,7 +397,7 @@ How we'd test the proposed design endtoend, once S0S5 land:
Once approved:
1. The PDF for printing will be generated postplanmode (requires shell exec). Recommended path: render the markdown via `pandoc` to `~/dev/shared/extensions/satmachineadmin/docs/security-pathway-v1.pdf`; the markdown source will live at `~/dev/shared/extensions/satmachineadmin/docs/security-pathway-v1.md` so future contributors edit it inrepo.
1. The PDF for printing will be generated postplanmode (requires shell exec). Recommended path: render the markdown via `pandoc` to `~/dev/shared/extensions/spirekeeper/docs/security-pathway-v1.pdf`; the markdown source will live at `~/dev/shared/extensions/spirekeeper/docs/security-pathway-v1.md` so future contributors edit it inrepo.
2. Open Forgejo epics on `aiolabs/satmachineadmin` linking back to existing `#9/#11/#12` and adding a new one for "Security pathway hardening (S0S7)."
3. Open a tracking issue on `aiolabs/lnbits` against the `nostr-transport` branch for the LNbitsside primitives (S2, S5, S6).
4. Sequence sprint: **S0 + S1 + S5 first** (highest ratio of security delta to upstream coupling). S2/S3/S4 in the following sprint.