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) <noreply@anthropic.com>
This commit is contained in:
parent
40639ee437
commit
439c47ceae
8 changed files with 14 additions and 14 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -10,5 +10,5 @@ data/
|
||||||
|
|
||||||
# uv lockfile — pyproject.toml still uses [tool.poetry] syntax, so uv lock
|
# uv lockfile — pyproject.toml still uses [tool.poetry] syntax, so uv lock
|
||||||
# produces a header-only file that pins nothing. Ignore until the
|
# 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
|
uv.lock
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ def _build_partial_dispense_memo(
|
||||||
async def settle_lp_balance(
|
async def settle_lp_balance(
|
||||||
client: DcaClient, machine: Machine, data: SettleBalanceData
|
client: DcaClient, machine: Machine, data: SettleBalanceData
|
||||||
) -> DcaPayment:
|
) -> 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
|
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'
|
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(
|
async def apply_partial_dispense_and_redistribute(
|
||||||
settlement_id: str, data: PartialDispenseData
|
settlement_id: str, data: PartialDispenseData
|
||||||
) -> DcaSettlement:
|
) -> 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
|
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
|
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,
|
errors=errors,
|
||||||
)
|
)
|
||||||
# Best-effort auto-forward to LP's external LN address (closes
|
# 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
|
# If autoforward fails, sats stay in the LP's LNbits wallet — the
|
||||||
# explicit safety constraint.
|
# explicit safety constraint.
|
||||||
if (
|
if (
|
||||||
|
|
@ -643,7 +643,7 @@ async def _attempt_autoforward(
|
||||||
settlement: DcaSettlement,
|
settlement: DcaSettlement,
|
||||||
amount_sats: int,
|
amount_sats: int,
|
||||||
) -> None:
|
) -> 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
|
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
|
the DCA leg's sat amount, and pays it from the LP's LNbits wallet. Each
|
||||||
|
|
|
||||||
|
|
@ -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. |
|
| **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). |
|
| **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`). |
|
| **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. |
|
| **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. |
|
| **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. |
|
| **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/57.md` | Lightning zaps & signed receipts. | Pattern source for S3. |
|
||||||
| `~/dev/nostr-protocol/nips/78.md` | App‑specific replaceable events. | Source for S4. |
|
| `~/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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ async def m001_satmachine_v2_initial(db):
|
||||||
concurrent process_settlement invocations.
|
concurrent process_settlement invocations.
|
||||||
* notes on dca_settlements — append-only audit memo for partial-
|
* notes on dca_settlements — append-only audit memo for partial-
|
||||||
dispense recompute + operator-authored notes (see
|
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
|
# 1. Drop legacy v1 tables. IF EXISTS handles both fresh-install
|
||||||
# paths (no-op) and migration from a v1 schema (cleans up).
|
# paths (no-op) and migration from a v1 schema (cleans up).
|
||||||
|
|
|
||||||
|
|
@ -478,7 +478,7 @@ class UpdateSuperConfigData(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class PartialDispenseData(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.
|
when bitSpire reports an error mid-dispense.
|
||||||
|
|
||||||
Either `dispensed_fraction` (0..1) for ratio-based recompute, or
|
Either `dispensed_fraction` (0..1) for ratio-based recompute, or
|
||||||
|
|
@ -550,7 +550,7 @@ class AppendSettlementNoteData(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class SettleBalanceData(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.
|
from their own wallet at a specified exchange rate.
|
||||||
|
|
||||||
Use case: an LP has a small remaining fiat balance (e.g. 47 GTQ) that
|
Use case: an LP has a small remaining fiat balance (e.g. 47 GTQ) that
|
||||||
|
|
|
||||||
2
nip44.py
2
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:
|
This module's runtime export footprint is therefore:
|
||||||
- `encrypt_for` / `decrypt_from` — called by the LocalSigner fallback in
|
- `encrypt_for` / `decrypt_from` — called by the LocalSigner fallback in
|
||||||
`cassette_transport` until every operator on the instance is bunker-backed
|
`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,
|
- Everything else (encrypt_with_conversation_key, decrypt_with_conversation_key,
|
||||||
get_conversation_key, padding helpers, error classes) is **test-only**:
|
get_conversation_key, padding helpers, error classes) is **test-only**:
|
||||||
referenced by `tests/test_nip44_v2.py` to validate the wire format against
|
referenced by `tests/test_nip44_v2.py` to validate the wire format against
|
||||||
|
|
|
||||||
|
|
@ -1427,7 +1427,7 @@
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<!-- =============================================================== -->
|
<!-- =============================================================== -->
|
||||||
<!-- SETTLE BALANCE DIALOG (closes satmachineadmin#4) -->
|
<!-- SETTLE BALANCE DIALOG (closes spirekeeper#2) -->
|
||||||
<!-- =============================================================== -->
|
<!-- =============================================================== -->
|
||||||
<q-dialog v-model="settleBalanceDialog.show" persistent>
|
<q-dialog v-model="settleBalanceDialog.show" persistent>
|
||||||
<q-card :style="{minWidth: '480px', maxWidth: '95vw'}">
|
<q-card :style="{minWidth: '480px', maxWidth: '95vw'}">
|
||||||
|
|
|
||||||
|
|
@ -458,7 +458,7 @@ async def api_settle_client_balance(
|
||||||
data: SettleBalanceData,
|
data: SettleBalanceData,
|
||||||
user: User = Depends(check_user_exists),
|
user: User = Depends(check_user_exists),
|
||||||
) -> DcaPayment:
|
) -> DcaPayment:
|
||||||
"""Operator UX — closes satmachineadmin#4.
|
"""Operator UX — closes spirekeeper#2.
|
||||||
|
|
||||||
Settle an LP's remaining fiat balance from the operator's chosen funding
|
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
|
wallet at the specified exchange rate. The amount_fiat is capped at the
|
||||||
|
|
@ -692,7 +692,7 @@ async def api_partial_dispense(
|
||||||
data: PartialDispenseData,
|
data: PartialDispenseData,
|
||||||
user: User = Depends(check_user_exists),
|
user: User = Depends(check_user_exists),
|
||||||
) -> DcaSettlement:
|
) -> DcaSettlement:
|
||||||
"""Operator UX — resolves satmachineadmin#3.
|
"""Operator UX — resolves spirekeeper#1.
|
||||||
|
|
||||||
Recompute the split for a settlement that didn't dispense the full
|
Recompute the split for a settlement that didn't dispense the full
|
||||||
amount (jam, mid-tx error). Provide one of dispensed_fraction (0..1)
|
amount (jam, mid-tx error). Provide one of dispensed_fraction (0..1)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue