feat(machine): consume get_machine_config over the transport (#70 P1 client) #74

Merged
padreug merged 1 commit from feat/machine-config-consumer into dev 2026-07-02 21:54:34 +00:00
Owner

Implements #71 (the client half of #70 P1). Server RPC: aiolabs/spirekeeper#41 (+ its PR).

Stacked PR. Based on feat/seed-driven-pairing (the P0 branch, PR #73) because it builds directly on the P0 operator-pubkey provenance + applyFeeConfig path. The diff here is only the P1 client. After #73 merges to dev, retarget this PR's base to dev.

What

Source the operator pubkey + fee config from LNbits via the get_machine_config kind-21000 RPC right after list_wallets, instead of the operator pubkey coming only from VITE_OPERATOR_PUBKEYS (env). A seed-only machine had an empty operator allowlist → the fees/operator-config services disabled themselves → permanent "awaiting configuration". Now it configures itself over the authenticated channel with zero per-machine provisioning.

How

  • LnbitsClient.getMachineConfig() → sendRpc('get_machine_config') + the MachineConfigResponse / FeeConfigWire types.
  • lightning.ts, only when VITE_OPERATOR_PUBKEYS is empty (env override still wins): set operatorPubkeys from operator_pubkey (re-enables the services), and persist fee_config via the existing applyFeeConfig IPC (mapping snake_case → the IPC's camelCase) so atm.ts's awaiting-fees gate clears immediately — robust to the replaceable kind-30078 not being fetchable from the relay. The live kind-30078 subscription still handles mid-run updates.
  • Soft-fail: older spirekeeper (no RPC) or a transport error falls back to the env/kind-30078 path. Nothing regresses.

Validated on hardware

A Sintra at "awaiting configuration" (P0 baseline, no provisioned operator pubkey), after this deploy:

Operator pubkey(s): (none — …#70 P1)          ← env has none
LNbits wallet: e4795193…                       ← seed-driven
Operator pubkey(s): <hex> (server-delivered, #70 P1)   ← get_machine_config
Server-delivered fee config: applied
State: idle                                    ← left "awaiting configuration"
[OperatorConfig] Subscribed · [Fees] Subscribed

Reached idle via the synchronous RPC ~2.5 min before the kind-30078 push arrived (which then also applied — dual-run intact).

lnbits + machine typecheck clean; lnbits suite 29 pass.

🤖 Generated with Claude Code

Implements #71 (the client half of #70 P1). Server RPC: aiolabs/spirekeeper#41 (+ its PR). > **Stacked PR.** Based on `feat/seed-driven-pairing` (the P0 branch, PR #73) because it builds directly on the P0 operator-pubkey provenance + `applyFeeConfig` path. The diff here is **only** the P1 client. After #73 merges to `dev`, retarget this PR's base to `dev`. ## What Source the **operator pubkey + fee config** from LNbits via the `get_machine_config` kind-21000 RPC right after `list_wallets`, instead of the operator pubkey coming only from `VITE_OPERATOR_PUBKEYS` (env). A seed-only machine had an empty operator allowlist → the fees/operator-config services disabled themselves → permanent "awaiting configuration". Now it configures itself over the authenticated channel with **zero per-machine provisioning**. ## How - `LnbitsClient.getMachineConfig()` → `sendRpc('get_machine_config')` + the `MachineConfigResponse` / `FeeConfigWire` types. - `lightning.ts`, **only when `VITE_OPERATOR_PUBKEYS` is empty** (env override still wins): set `operatorPubkeys` from `operator_pubkey` (re-enables the services), and persist `fee_config` via the existing `applyFeeConfig` IPC (mapping snake_case → the IPC's camelCase) so `atm.ts`'s awaiting-fees gate clears immediately — robust to the replaceable kind-30078 not being fetchable from the relay. The live kind-30078 subscription still handles mid-run updates. - **Soft-fail**: older spirekeeper (no RPC) or a transport error falls back to the env/kind-30078 path. Nothing regresses. ## Validated on hardware A Sintra at "awaiting configuration" (P0 baseline, no provisioned operator pubkey), after this deploy: ``` Operator pubkey(s): (none — …#70 P1) ← env has none LNbits wallet: e4795193… ← seed-driven Operator pubkey(s): <hex> (server-delivered, #70 P1) ← get_machine_config Server-delivered fee config: applied State: idle ← left "awaiting configuration" [OperatorConfig] Subscribed · [Fees] Subscribed ``` Reached `idle` via the synchronous RPC ~2.5 min before the kind-30078 push arrived (which then also applied — dual-run intact). lnbits + machine typecheck clean; lnbits suite 29 pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Source the operator pubkey + fee config from LNbits via the get_machine_config
kind-21000 RPC (spirekeeper#41) right after list_wallets, instead of the
operator pubkey coming only from VITE_OPERATOR_PUBKEYS (env). A seed-only
machine (blank .env) had an empty operator allowlist → the fees/operator-config
services disabled themselves → permanent "awaiting configuration". Now it pulls
its config over the already-authenticated channel and configures itself with
zero per-machine provisioning — closing bitspire#70 P1.

- LnbitsClient.getMachineConfig() → sendRpc('get_machine_config') + the
  MachineConfigResponse / FeeConfigWire types.
- lightning.ts, only when VITE_OPERATOR_PUBKEYS is empty (env override still
  wins): set CONFIG.operatorPubkeys from operator_pubkey (re-enables the
  services), and persist fee_config via the existing applyFeeConfig IPC (mapping
  snake_case → camelCase) so atm.ts's awaiting-fees gate clears immediately —
  robust to the replaceable kind-30078 not being fetchable from the relay. The
  live kind-30078 subscription still handles mid-run fee updates.
- Soft-fail: older spirekeeper (no RPC) or a transport error falls back to the
  env/kind-30078 path.

lnbits + machine typecheck clean; lnbits suite 29 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
padreug changed target branch from feat/seed-driven-pairing to dev 2026-07-02 21:54:11 +00:00
padreug force-pushed feat/machine-config-consumer from 9d0e8d8fea to fdb9a507c2 2026-07-02 21:54:21 +00:00 Compare
padreug deleted branch feat/machine-config-consumer 2026-07-02 21:54:34 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/bitspire!74
No description provided.