feat(pairing): optional token TTL + revoke endpoint (#9/#12, #22)
Some checks failed
ci.yml / feat(pairing): optional token TTL + revoke endpoint (#9/#12, #22) (pull_request) Failing after 0s
Some checks failed
ci.yml / feat(pairing): optional token TTL + revoke endpoint (#9/#12, #22) (pull_request) Failing after 0s
Builds on the seed-URL pairing in #21 (stacked). (b) TTL — PairMachineData.duration_hours (validated > 0) threads through pair_spire -> create_new_token (lnbits#55). None = non-expiring. (c) Revoke — POST /machines/{id}/revoke -> revoke_spire -> admin_client.revoke_key_user(spire-<id>). Per spirekeeper#22, revoke MUST go through KeyUser.revokedAt (revoke_key_user), NOT token revoke: lnbits eager-binds (redeems) the connect token at provision, so nsecbunkerd has materialised the policy into per-KeyUser grants its ACL checks BEFORE the Token.revokedAt filter -> token revoke is a silent no-op. Returns RevokeResult{revoked_count}: >=1 = cut, 0 = never bound. set_machine_unpaired clears paired_at (keeps npub + bunker_spire_key_name for audit / re-pair). 7 new tests (duration threading + default-None; revoke routes to revoke_key_user and never token-revoke + error mapping; endpoint wiring revoke happy/zero/502). 210 green; new code black/ruff-clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9c5f07c72e
commit
a5efdf22a1
6 changed files with 223 additions and 10 deletions
10
models.py
10
models.py
|
|
@ -85,9 +85,17 @@ class PairMachineData(BaseModel):
|
|||
"""Body for POST /machines/{id}/pair (S0 / #9). `relays` are the relays
|
||||
the spire will use for its own events (kind-21000/30078) — typically the
|
||||
operator's nostrrelay; the bunker connection relay is added separately
|
||||
from the lnbits bunker settings."""
|
||||
from the lnbits bunker settings. `duration_hours` optionally time-bounds
|
||||
the spire's connect token (None = non-expiring)."""
|
||||
|
||||
relays: list[str]
|
||||
duration_hours: int | None = None
|
||||
|
||||
@validator("duration_hours")
|
||||
def _positive_duration(cls, v):
|
||||
if v is not None and v <= 0:
|
||||
raise ValueError("duration_hours must be positive when set")
|
||||
return v
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue