From 439c47ceaec5407af0ef2545ab84d5117e35f127 Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 16 Jun 2026 17:42:56 +0200 Subject: [PATCH] docs: repoint migrated issue refs to spirekeeper numbers Follow-up to the satmachineadmin->spirekeeper issue migration. The 20 open issues were recreated on aiolabs/spirekeeper with reassigned numbers; this repoints in-repo references to the migrated issues at their new spirekeeper numbers (#3->#1, #4->#2, #8->#4, #9->#5, #10->#6, #17->#11, #21->#12, #28->#16, #44->#20). References to closed/non- migrated satmachineadmin issues (#20/#22/#26/#29/#32/#37/#38/#39) stay pointing at the original repo where they were resolved. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 2 +- distribution.py | 8 ++++---- docs/security-pathway-v1.md | 4 ++-- migrations.py | 2 +- models.py | 4 ++-- nip44.py | 2 +- templates/spirekeeper/index.html | 2 +- views_api.py | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 4750fd5..dbdb2d1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,5 @@ data/ # uv lockfile — pyproject.toml still uses [tool.poetry] syntax, so uv lock # produces a header-only file that pins nothing. Ignore until the -# PEP 621 migration lands (aiolabs/satmachineadmin#28). +# PEP 621 migration lands (aiolabs/spirekeeper#16). uv.lock diff --git a/distribution.py b/distribution.py index b4dfbeb..271494b 100644 --- a/distribution.py +++ b/distribution.py @@ -163,7 +163,7 @@ def _build_partial_dispense_memo( async def settle_lp_balance( client: DcaClient, machine: Machine, data: SettleBalanceData ) -> DcaPayment: - """Operator UX action — closes satmachineadmin#4. + """Operator UX action — closes spirekeeper#2. Settle an LP's remaining fiat balance from the operator's chosen funding wallet at the rate the operator specified. Records a leg_type='settlement' @@ -271,7 +271,7 @@ async def settle_lp_balance( async def apply_partial_dispense_and_redistribute( settlement_id: str, data: PartialDispenseData ) -> DcaSettlement: - """Operator UX action — closes satmachineadmin#3. + """Operator UX action — closes spirekeeper#1. When a bitSpire dispense fails mid-transaction (e.g., dispenser jam after 6 of 10 bills), the operator confirms the actual amount dispensed and we @@ -619,7 +619,7 @@ async def _pay_one_dca_leg( errors=errors, ) # Best-effort auto-forward to LP's external LN address (closes - # satmachineadmin#8). Skip if the DCA leg failed (nothing to forward). + # spirekeeper#4). Skip if the DCA leg failed (nothing to forward). # If autoforward fails, sats stay in the LP's LNbits wallet — the # explicit safety constraint. if ( @@ -643,7 +643,7 @@ async def _attempt_autoforward( settlement: DcaSettlement, amount_sats: int, ) -> None: - """LP auto-forward (best-effort) — closes satmachineadmin#8. + """LP auto-forward (best-effort) — closes spirekeeper#4. Resolves the LP's configured LN address, requests a bolt11 invoice for the DCA leg's sat amount, and pays it from the LP's LNbits wallet. Each diff --git a/docs/security-pathway-v1.md b/docs/security-pathway-v1.md index 5d57414..0a5699f 100644 --- a/docs/security-pathway-v1.md +++ b/docs/security-pathway-v1.md @@ -303,7 +303,7 @@ None of those need to change. The new layers slot in *above* them. | **S0 — Seed‑URL pairing + ATM keypair separation** | Provisioning script generates a fresh `nsec` for the ATM (already does — we just stop overwriting it with the operator's). Operator pastes a one‑shot QR/seed URL containing `{atm_npub, operator_npub, relay_list, signed_delegation_token}` at ATM first boot. | G3 (most of it), G9 | 1 week | None — purely on our side. Use existing NIP‑26 spec. | | **S1 — NIP‑40 expiration on all kind‑21000** | Every RPC carries `["expiration", now+5min]`. Handler refuses past‑expiration. ATM clock check on boot (warn if drift > 60s). | G4 | 1–2 days | Relay must support NIP‑40 (most do). | | **S2 — NIP‑26 delegation enforcement in nostr‑transport** | Handler parses `delegation` tag, validates sig over conditions, checks conditions match the event, looks up operator pubkey in roster. Reject events without a valid delegation. | G3 (rest), G7 (partially) | 1–2 weeks | LNbits PR upstream (or vendored fork on `aiolabs/lnbits` branch `nostr-transport-nip26`). | -| **S3 — NIP‑57‑style settlement receipts** | After LNbits internal payment legs complete, publish a signed receipt event per settlement (and per leg if we want leg‑level audit). ATM subscribes; operator dashboard renders receipts side‑by‑side with `dca_settlements`. | G2, G7 | 1–2 weeks | **Kind allocation — DO NOT USE `kind:21001`.** That kind is claimed by CLINK (Offers) — collision caught during the 2026‑06‑02 CLINK primer review. Rotation off 21001 is tracked at `aiolabs/satmachineadmin#44`; target is the aiolabs reserved band **`22000–22099`** per the workspace rule in `~/dev/CLAUDE.md` (§ "Nostr kind allocations — avoid the CLINK band"). The earlier 21001 lock across `aiolabs/lnbits#22`, `aiolabs/satmachineadmin#17`, and the satmachine ATM is **SUPERSEDED** — pick the new kind before any of those land. Reusing `kind:9735` (zap receipt) is also off the table: NIP‑57 semantics don't apply to bitSpire cash‑out settlements. | +| **S3 — NIP‑57‑style settlement receipts** | After LNbits internal payment legs complete, publish a signed receipt event per settlement (and per leg if we want leg‑level audit). ATM subscribes; operator dashboard renders receipts side‑by‑side with `dca_settlements`. | G2, G7 | 1–2 weeks | **Kind allocation — DO NOT USE `kind:21001`.** That kind is claimed by CLINK (Offers) — collision caught during the 2026‑06‑02 CLINK primer review. Rotation off 21001 is tracked at `aiolabs/spirekeeper#20`; target is the aiolabs reserved band **`22000–22099`** per the workspace rule in `~/dev/CLAUDE.md` (§ "Nostr kind allocations — avoid the CLINK band"). The earlier 21001 lock across `aiolabs/lnbits#22`, `aiolabs/spirekeeper#11`, and the satmachine ATM is **SUPERSEDED** — pick the new kind before any of those land. Reusing `kind:9735` (zap receipt) is also off the table: NIP‑57 semantics don't apply to bitSpire cash‑out settlements. | | **S4 — NIP‑78 per‑machine config + fleet roster** | Operator publishes `kind:30078` config + `kind:30000` fleet list. Handler cross‑checks ATM npub ∈ fleet; reads max‑withdraw/fee policy from config. | G1, G9 | 1 week | Define config schema; backwards‑compat path for pre‑NIP‑78 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 post‑write breaks the HMAC. | G2 (DB‑side), G5, G6 | 3–5 days | LNbits PR — fairly localised. | | **S6 — Rate limiting + roster‑gated auto‑account** | Auto‑account‑from‑npub only fires if the npub appears in some operator's NIP‑78 fleet OR if an explicit "open enrollment" flag is set. Relay/handler‑level rate limit per pubkey. | G8, G9 | 1 week | LNbits PR. | @@ -374,7 +374,7 @@ For an auditor or new contributor doing a walk‑through: | `~/dev/nostr-protocol/nips/57.md` | Lightning zaps & signed receipts. | Pattern source for S3. | | `~/dev/nostr-protocol/nips/78.md` | App‑specific replaceable events. | Source for S4. | -Existing Forgejo issues this report supersedes/consolidates: `aiolabs/satmachineadmin#9` (v2 epic), `#11` (security audit findings), `#12` (ATM pairing + bunker deep‑dive), `aiolabs/lamassu-next#44` (Payment.extra split). This document is the design that closes the security‑relevant subset of those. +Existing Forgejo issues this report supersedes/consolidates: `aiolabs/spirekeeper#5` (v2 epic), `#11` (security audit findings), `#12` (ATM pairing + bunker deep‑dive), `aiolabs/lamassu-next#44` (Payment.extra split). This document is the design that closes the security‑relevant subset of those. --- diff --git a/migrations.py b/migrations.py index 5cbe5be..b8e6ec0 100644 --- a/migrations.py +++ b/migrations.py @@ -45,7 +45,7 @@ async def m001_satmachine_v2_initial(db): concurrent process_settlement invocations. * notes on dca_settlements — append-only audit memo for partial- dispense recompute + operator-authored notes (see - aiolabs/satmachineadmin#10 for the future structured audit table). + aiolabs/spirekeeper#6 for the future structured audit table). """ # 1. Drop legacy v1 tables. IF EXISTS handles both fresh-install # paths (no-op) and migration from a v1 schema (cleans up). diff --git a/models.py b/models.py index f7f84e4..c158fba 100644 --- a/models.py +++ b/models.py @@ -478,7 +478,7 @@ class UpdateSuperConfigData(BaseModel): class PartialDispenseData(BaseModel): - """Resolves satmachineadmin#3 — operator confirms actual bills dispensed + """Resolves spirekeeper#1 — operator confirms actual bills dispensed when bitSpire reports an error mid-dispense. Either `dispensed_fraction` (0..1) for ratio-based recompute, or @@ -550,7 +550,7 @@ class AppendSettlementNoteData(BaseModel): class SettleBalanceData(BaseModel): - """Resolves satmachineadmin#4 — operator settles small remaining LP balance + """Resolves spirekeeper#2 — operator settles small remaining LP balance from their own wallet at a specified exchange rate. Use case: an LP has a small remaining fiat balance (e.g. 47 GTQ) that diff --git a/nip44.py b/nip44.py index 109860d..32ca7b7 100644 --- a/nip44.py +++ b/nip44.py @@ -18,7 +18,7 @@ back to the helpers in this module against the stored `account.prvkey`. This module's runtime export footprint is therefore: - `encrypt_for` / `decrypt_from` — called by the LocalSigner fallback in `cassette_transport` until every operator on the instance is bunker-backed - (S7 / aiolabs/satmachineadmin#21). Then those calls disappear too. + (S7 / aiolabs/spirekeeper#12). Then those calls disappear too. - Everything else (encrypt_with_conversation_key, decrypt_with_conversation_key, get_conversation_key, padding helpers, error classes) is **test-only**: referenced by `tests/test_nip44_v2.py` to validate the wire format against diff --git a/templates/spirekeeper/index.html b/templates/spirekeeper/index.html index 054bc77..b58714e 100644 --- a/templates/spirekeeper/index.html +++ b/templates/spirekeeper/index.html @@ -1427,7 +1427,7 @@ - + diff --git a/views_api.py b/views_api.py index a8ed965..079794d 100644 --- a/views_api.py +++ b/views_api.py @@ -458,7 +458,7 @@ async def api_settle_client_balance( data: SettleBalanceData, user: User = Depends(check_user_exists), ) -> DcaPayment: - """Operator UX — closes satmachineadmin#4. + """Operator UX — closes spirekeeper#2. Settle an LP's remaining fiat balance from the operator's chosen funding wallet at the specified exchange rate. The amount_fiat is capped at the @@ -692,7 +692,7 @@ async def api_partial_dispense( data: PartialDispenseData, user: User = Depends(check_user_exists), ) -> DcaSettlement: - """Operator UX — resolves satmachineadmin#3. + """Operator UX — resolves spirekeeper#1. Recompute the split for a settlement that didn't dispense the full amount (jam, mid-tx error). Provide one of dispensed_fraction (0..1)