feat(pairing): POST /machines/{id}/pair endpoint (#9)
Some checks failed
ci.yml / feat(pairing): POST /machines/{id}/pair endpoint (#9) (pull_request) Failing after 0s
Some checks failed
ci.yml / feat(pairing): POST /machines/{id}/pair endpoint (#9) (pull_request) Failing after 0s
Wires the pairing service into the operator API. api_pair_machine:
- _machine_owned_by ownership guard (404 on miss)
- opens NsecBunkerAdminClient.from_settings() and runs pair_spire
- maps bunker failures: not-configured -> 503, PairingError/NsecBunkerError
-> 502 (nothing persisted on failure)
- runs _assert_no_pubkey_collision on the bunker-minted hex, then
set_machine_pairing persists machine_npub (= minted spire identity, so
path-B roster routes it), bunker_spire_key_name, paired_at.
Re-pair supported; revoke/expiry gated on aiolabs/lnbits#54.
Adds Create... PairMachineData {relays} body, set_machine_pairing CRUD,
and 3 endpoint wiring tests (persist+collision, empty-relays 400, failure
502). 203 tests green. Pre-existing black/ruff debt in crud/views_api left
untouched (version-drift churn avoided); new code is lint-clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a77f5bcb5c
commit
761f078053
4 changed files with 213 additions and 0 deletions
31
crud.py
31
crud.py
|
|
@ -202,6 +202,37 @@ async def update_machine(machine_id: str, data: UpdateMachineData) -> Machine |
|
|||
return await get_machine(machine_id)
|
||||
|
||||
|
||||
async def set_machine_pairing(
|
||||
machine_id: str,
|
||||
*,
|
||||
machine_npub: str,
|
||||
bunker_spire_key_name: str,
|
||||
paired_at: datetime,
|
||||
) -> Machine | None:
|
||||
"""Persist the result of a (re-)pair: the bunker-minted spire identity
|
||||
becomes the machine's npub (so lnbits' path-B roster routes it), and we
|
||||
record the bunker key name + pair time. Stored as lowercase hex — the
|
||||
roster + collision guard normalise either form, hex is canonical."""
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE spirekeeper.dca_machines
|
||||
SET machine_npub = :npub,
|
||||
bunker_spire_key_name = :key_name,
|
||||
paired_at = :paired_at,
|
||||
updated_at = :updated_at
|
||||
WHERE id = :id
|
||||
""",
|
||||
{
|
||||
"npub": machine_npub.lower(),
|
||||
"key_name": bunker_spire_key_name,
|
||||
"paired_at": paired_at,
|
||||
"updated_at": datetime.now(),
|
||||
"id": machine_id,
|
||||
},
|
||||
)
|
||||
return await get_machine(machine_id)
|
||||
|
||||
|
||||
async def delete_machine(machine_id: str) -> None:
|
||||
await db.execute(
|
||||
"DELETE FROM spirekeeper.dca_machines WHERE id = :id",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue