fix(relayauth): exclude event author from NOTIFY_INBOX counterparties

A pending non-gift-wrap event's `p` tags are the people it notifies, but
some events self-p-tag the author. Drop the author's own key so the auth
reason and follow-trust check reflect who is actually being notified, not
the sender. (Own-relay over-attribution is already handled upstream by the
isInMyRelayList allow.) Adds a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZjmYpgHP4pf79Sav5QT8a
This commit is contained in:
Claude
2026-07-10 22:40:10 +00:00
parent 39dc053bf7
commit b1b7a4e7c3
2 changed files with 13 additions and 1 deletions
@@ -49,7 +49,9 @@ object RelayAuthPurposeDeriver {
if (event.kind == GiftWrapEvent.KIND) {
dmRecipients.addAll(pTags)
} else {
notifyRecipients.addAll(pTags)
// We're notifying the people the event references, not its author — drop the
// author's own key so a self-p-tag doesn't read as "notify yourself".
notifyRecipients.addAll(pTags - event.pubKey)
}
}
@@ -63,6 +63,16 @@ class RelayAuthPurposeDeriverTest {
assertEquals(setOf(alice, bob), purposes[0].counterparties)
}
@Test
fun notifyExcludesTheEventsOwnAuthor() {
val author = "11".repeat(32) // matches event()'s pubKey
val purposes = RelayAuthPurposeDeriver.derive(listOf(event(1, listOf(author, alice))), emptyMap())
assertEquals(1, purposes.size)
assertEquals(AuthPurposeKind.NOTIFY_INBOX, purposes[0].kind)
assertEquals(setOf(alice), purposes[0].counterparties)
}
@Test
fun subscriptionAuthorsBecomeReadOutbox() {
val purposes = RelayAuthPurposeDeriver.derive(emptyList(), mapOf("sub1" to listOf(Filter(authors = listOf(alice, bob)))))