From 277a1ef31fa17f017e0cab49bbca4c783d8b0941 Mon Sep 17 00:00:00 2001 From: Jaehong Kang Date: Wed, 15 Apr 2026 23:05:36 +0900 Subject: [PATCH] fix(backend): handle relay-delivered Announce activities correctly (#17308) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backend): handle relay-delivered Announce activities correctly Relay Announce activities now use the target note URI instead of the Announce URI for federation allowlist checks, dedup locking, and existence lookups. Notes delivered via relay are published directly to the notes stream without creating a renote. Closes #11056 * Update packages/backend/src/core/RelayService.ts Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --------- Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + packages/backend/src/core/RelayService.ts | 20 ++++++++++++++++--- .../src/core/activitypub/ApInboxService.ts | 14 +++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f948d696e4..e1efd9f1e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Fix: ローカルに存在しないリモートアカウントに対するアカウント削除リクエストを受信した際に、そのユーザーを新規作成して削除する挙動を修正 - Fix: Inboxでの特定のエラーによる失敗はDelayedにしない - Fix: ID生成アルゴリズムにULIDを使用している場合にMisskeyが正しく動作しない問題を修正 +- Fix: リレー経由で届いたノートがリノートとして表示される問題を修正 - Fix: robots.txtの内容を調整 ## 2026.3.2 diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts index 9120de1f9f..d96d6c70d0 100644 --- a/packages/backend/src/core/RelayService.ts +++ b/packages/backend/src/core/RelayService.ts @@ -91,13 +91,27 @@ export class RelayService { return JSON.stringify(result); } + @bindThis + private getAcceptedRelays(): Promise { + return this.relaysCache.fetch(() => this.relaysRepository.findBy({ + status: 'accepted', + })); + } + + @bindThis + public async isRelayActor(actor: { inbox: string | null; sharedInbox: string | null }): Promise { + const relays = await this.getAcceptedRelays(); + return relays.some(relay => + (actor.inbox != null && relay.inbox === actor.inbox) + || (actor.sharedInbox != null && relay.inbox === actor.sharedInbox), + ); + } + @bindThis public async deliverToRelays(user: { id: MiUser['id']; host: null; }, activity: any): Promise { if (activity == null) return; - const relays = await this.relaysCache.fetch(() => this.relaysRepository.findBy({ - status: 'accepted', - })); + const relays = await this.getAcceptedRelays(); if (relays.length === 0) return; const copy = deepClone(activity); diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index ff47ca930d..4f926b99d4 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -302,12 +302,14 @@ export class ApInboxService { @bindThis private async announceNote(actor: MiRemoteUser, activity: IAnnounce, target: IPost, resolver?: Resolver): Promise { - const uri = getApId(activity); - if (actor.isSuspended) { return; } + // リレーからのAnnounceかチェック + const fromRelay = await this.relayService.isRelayActor(actor); + const uri = getApId(fromRelay ? target : activity); + // アナウンス先が許可されているかチェック if (!this.utilityService.isFederationAllowedUri(uri)) return; @@ -336,6 +338,14 @@ export class ApInboxService { throw err; } + // リレーからのAnnounceはリノートを作成せず、ノートを直接公開する + if (fromRelay) { + this.logger.info(`Publishing relay-delivered note: ${uri}`); + const noteObj = await this.noteEntityService.pack(renote, null, { skipHide: true, withReactionAndUserPairCache: true }); + this.globalEventService.publishNotesStream(noteObj); + return; + } + if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) { return 'skip: invalid actor for this activity'; }