Harden unwrapGift for the receive side: verify the seal's BIP-340 signature
and recomputed id, enforce that the rumor's author matches the seal signer
(NIP-59 anti-spoofing), and check the rumor id against its contents. The
rumor is unsigned by design, so sender authentication rests on the seal.
Add UnwrapDirectMessage to NostrDmActor, returning the authenticated sender,
content, timestamp, and tags. Cover both with tests: an unwrap round-trip and
a rejection of a wrap whose inner rumor spoofs a different author.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add outbound NIP-17 private messaging: build the kind-14 rumor -> kind-13
seal -> kind-1059 gift wrap chain on the existing NIP-44 primitives, wrapped
in NostrDmActor (WrapDirectMessage/GiftWrapped). Publishing is left to
NostrPublishActor.
Extract nostrEventId() from signNostrEvent so the unsigned rumor can compute
its id without a signature. Export the new actor and nip17 helpers. Add a
round-trip test (wrap -> unwrap) and a negative decryption test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>