nostr_dict() returned every model field except relay_id and publisher,
so the size column added for storage accounting leaked into every
EVENT sent to clients. Emit the seven NIP-01 fields explicitly instead.
Caught by the client-flow test ported from upstream.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
A kind-5 request could only name events by `e` tag. Worse, one that
carried `a` tags and no `e` tags built a filter with an empty id list,
which matched every event by that author and marked them all deleted.
Handle `a` tags per NIP-09: parse `kind:pubkey:d` (the `d` value may
contain ':'), require the pubkey to be the request author and the kind
to be replaceable or addressable, and remove only versions up to the
request's `created_at` so a later re-publication survives. An empty
`d` addresses a replaceable kind.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
(cherry picked from commit e695f9c66881d3d520d40f0cd3e9c95d9435938c)
test_alice_and_bob paused for fixed 0.1-0.5 s between wiring events
and asserting on the replies. On a slow runner the replies were not
there yet; on a fast one the next step ran before the previous event
was stored. Both show up as spurious failures (CI on #45, 2026-09-13).
Give the mock socket a wait_for_messages(count) helper and wait for
the expected number of messages at each step instead. Exact-count
assertions stay, so extra messages still fail.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
(cherry picked from commit deb6510193b68f343c2f7845c615634beb020911)
_handle_request dropped the subscription's existing filters before
adding each filter of a REQ, so a REQ carrying several filters ended
up with only its last one registered. Remove the old filters once per
REQ instead, before the loop, since a REQ replaces the subscription as
a whole.
Also invert _can_add_filter so its name matches what it returns. The
old version returned "limit exceeded" and the caller tested for that,
so behaviour is unchanged; the tests pin it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
(cherry picked from commit 37331b14847cfb5d43f8e97b36a6f52d9b86abae)