fix: guard every machine_npub deref against unpaired machines (500 + cassette-consumer crash) #33
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/unpaired-machine-npub-guards"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The bug (found on the demo after the v0.1.1 upgrade)
machine_npubbecame nullable in #29/m011 (register-unpaired flow), but several consumers still assumed it's non-Noneand crashednormalize_public_key(None)withAttributeError: 'NoneType' object has no attribute 'startswith'.On
lnbits.demo.aiolabs.dev(which has an unpaired machine), this surfaced as:api_update_super_config), andcassette consumer loop error … 'NoneType' … startswithevery 2s (non-functional).The #29 create/pair paths were guarded; these five sites were missed:
views_api.api_update_super_configrepublish loopcassette_transport.build_state_d_tags_for_machinescrud.get_machine_by_atm_pubkey_hexexcept (ValueError, AssertionError)didn't catch theAttributeError; skip unpaired before normalizebitspire.assert_nostr_attributionSettlementAttributionErrorviews_apicassettes/publish endpointpublish_to_atmVerification
On the dev stack, inserted an unpaired active machine (mirroring the demo): before — cassette consumer crashed with the same
AttributeError; after — it "(re)registered … with 1 d-tag(s)" (skipping the unpaired one) and runs clean.py_compile+ruffclean on the changed lines.Deploy
This is a hotfix for the broken demo. After merge I'll tag v0.1.2 + bump the catalog so the demo can upgrade off the broken v0.1.1.
🤖 Generated with Claude Code
102c8eac918dad72a00dMade it complete, not just whack-a-mole
Did a full sweep of every
machine_npubderef. Findings:assert_nostr_attribution,_atm_hex_pubkeyvia fee + cassette transports,get_machine_by_atm_pubkey_hex) — all guarded._record_rejected(tasks.py) logsmachine_npub[:12], and myassert_nostr_attributionguard now routes an unpaired machine there →None[:12]TypeError. Fixed (fall back tomachine.id).assert_nostr_attribution(which now rejects unpaired) for a paired machine, so the downstreamdistribution.py/bitspireparse-path / "landed settlement" log derefs can't observeNone. The collision-loop display already uses(m.machine_npub or m.id).Regression test
Added
tests/test_unpaired_machine_guards.py—assert_nostr_attributionrejects an unpaired machine with the domainSettlementAttributionError(notAttributeError), andbuild_state_d_tagsskips it. Full suite: 211 passed; the only reds are 2 pre-existingtest_pair_endpointfailures (#29 drift — filed separately, out of scope here).