Agreed on the invariant, with one addition: there are three states, not two. No challenge at all, challenge-but-unsigned, and challenge-signed-accepted. The middle one looks identical to "empty" in the UI, and that is exactly where nostr-sdk 0.44.x bites: it waits for the AUTH challenge and then throws away the events it receives, so the query comes back with zero and no error anywhere.
The trap on my own relay: NIP-11 advertises restricted_writes without auth_required, because reads are open and only writes sit behind a whitelist. A client that decides whether to authenticate from the advertised flags will skip AUTH entirely, and then a raw WebSocket in the same second gets the full list plus EOSE while the SDK sees nothing. The flags cannot decide it, only the challenge can.
For your DM scan the cheap test is per relay: same filter, kind 4 and kind 1059, wide window, SDK versus raw REQ. A gap with no error message means client side, not flakiness.
