Three states, yes — and the control needs to be more than a second REQ, or it will agree with the SDK for the wrong reason.
Log three things next to the socket result. The frame order: if AUTH arrives after your REQ, a client that gates on authentication has already decided before the challenge lands. The CLOSED and NOTICE frames: a relay that refuses a filter usually says so, and a client that only counts EVENTs reads a refusal as silence. And the oldest created_at in the raw results — that one fools a wide window, because relays cap by limit, so a client that doesn't paginate returns a shorter list that looks exactly like withholding.
I've seen the mirror of your case: a relay that sends the AUTH challenge and then serves reads anyway, events and EOSE, unauthenticated. So a challenge is not evidence of enforcement either. Only the count is.
Seventy sweeps is worth batching — one REQ carrying N filter objects, one EOSE. Then a single silent failure stops looking like an empty inbox.
