Skip to content

Conversation

@ricardogarim
Copy link
Contributor

@ricardogarim ricardogarim commented Oct 1, 2025

Summary by CodeRabbit

  • Bug Fixes

    • More reliable redactions by validating targets and ensuring required fields are present.
  • Refactor

    • Redaction flow simplified: sender ID no longer required externally; derived automatically.
    • Redaction payload aligned with spec: target reference moved to event top level.
  • New Features

    • Local user joins now emit a membership event so downstream consumers are notified.
  • Tests

    • Tests updated for the new redaction payload and behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 1, 2025

Walkthrough

Redaction events now carry redacts as a top-level event field instead of inside content. Type guards, schemas, factory signature, services, controller, DTO, staging emission, and tests were updated; MessageService derives sender from the redacted event rather than accepting it as an argument.

Changes

Cohort / File(s) Summary
Core redaction typing & factory
packages/core/src/events/eventBase.ts, packages/core/src/events/m.room.redaction.ts, packages/room/src/types/v3-11.ts
Type guard isRedactedEvent tightened to require top-level redacts; redactionEvent now takes redacts: EventID as a top-level parameter; removed content.redacts from redaction content schema.
Federation SDK services
packages/federation-sdk/src/services/message.service.ts, packages/federation-sdk/src/services/staging-area.service.ts
MessageService.redactMessage signature dropped senderUserId and now retrieves sender from the target event; staging emission reads event.event.redacts (top-level) instead of content.redacts.
Homeserver integration
packages/homeserver/src/controllers/internal/message.controller.ts, packages/homeserver/src/dtos/internal/message.dto.ts
Controller call updated to redactMessage(roomId, messageId) without senderUserId; InternalRedactMessageBodyDto no longer includes senderUserId.
Tests
packages/core/src/events/m.room.redaction.spec.ts
Tests updated to expect redacts at the event top level (moved from content.redacts) and to validate preserved reason and behavior.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client as Internal Caller
  participant C as MessageController
  participant S as MessageService
  participant ES as EventStore
  participant EB as RedactionFactory
  participant SA as StagingArea
  participant Fed as Federation

  Client->>C: POST /internal/messages/:id/redact
  C->>S: redactMessage(roomId, eventIdToRedact)
  S->>ES: getEvent(eventIdToRedact)
  ES-->>S: event { sender, ... }
  Note over S,ES: Sender is derived from the target event
  S->>EB: create redaction(redacts: eventIdToRedact, reason?)
  EB-->>S: redaction PDU { type: m.room.redaction, redacts, content{reason?}, ... }
  S->>SA: stage(redaction PDU)
  SA->>Fed: emit m.room.redaction (reads event.redacts)
  Fed-->>SA: ack
  SA-->>S: staged id
  S-->>C: redaction event id
  C-->>Client: 200 OK
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • rodrigok

Poem

I nibble code and shift the tracks,
Lift redacts up from nested sacks.
No sender passed — I seek its name,
The target event whispers the same.
A tidy hop, a tidy patch, happy warren, perfect game. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title “fix: delete message” is too generic to convey the primary work in this changeset, which refactors redaction events by relocating the redacts field to the top level and updates the delete‐message/redaction flow across multiple services; it does not summarize the main changes or clarify the specific components affected. Please revise the title to clearly reflect the core changes, for example: “refactor(events): move redacts to top‐level in redaction events and update delete message flow,” so teammates immediately understand the scope and intent.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/delete-message

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link

codecov-commenter commented Oct 1, 2025

Codecov Report

❌ Patch coverage is 75.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 81.86%. Comparing base (9f32b43) to head (e9b7aae).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
packages/core/src/events/eventBase.ts 50.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #240   +/-   ##
=======================================
  Coverage   81.86%   81.86%           
=======================================
  Files          63       63           
  Lines        4709     4709           
=======================================
  Hits         3855     3855           
  Misses        854      854           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ricardogarim ricardogarim marked this pull request as ready for review October 1, 2025 18:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/core/src/events/m.room.redaction.ts (1)

37-88: Refactor correctly moves redacts to top-level parameter.

The change properly relocates redacts from the content object to a top-level function parameter, aligning with the event structure where redacts is a top-level property.

The comment at lines 62-63 is now misleading:

// Extract redacts from content - it must be at top level only
const { reason } = content;

This comment suggests redacts is being extracted from content, but it's now a top-level parameter. Consider updating or removing this comment:

-	// Extract redacts from content - it must be at top level only
+	// Extract reason from content (redacts is now a top-level parameter)
 	const { reason } = content;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9f32b43 and f684355.

📒 Files selected for processing (8)
  • packages/core/src/events/eventBase.ts (1 hunks)
  • packages/core/src/events/m.room.redaction.spec.ts (1 hunks)
  • packages/core/src/events/m.room.redaction.ts (2 hunks)
  • packages/federation-sdk/src/services/message.service.ts (2 hunks)
  • packages/federation-sdk/src/services/staging-area.service.ts (1 hunks)
  • packages/homeserver/src/controllers/internal/message.controller.ts (1 hunks)
  • packages/homeserver/src/dtos/internal/message.dto.ts (0 hunks)
  • packages/room/src/types/v3-11.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • packages/room/src/types/v3-11.ts
  • packages/homeserver/src/dtos/internal/message.dto.ts
🧰 Additional context used
🧬 Code graph analysis (4)
packages/federation-sdk/src/services/staging-area.service.ts (1)
packages/room/src/manager/event-wrapper.ts (1)
  • event (108-117)
packages/core/src/events/m.room.redaction.ts (2)
packages/federation-sdk/src/index.ts (1)
  • EventID (23-23)
packages/room/src/types/_common.ts (1)
  • EventID (8-8)
packages/core/src/events/eventBase.ts (2)
packages/room/src/manager/event-wrapper.ts (1)
  • event (108-117)
packages/room/src/types/_common.ts (2)
  • PduForType (14-14)
  • EventID (8-8)
packages/federation-sdk/src/services/message.service.ts (1)
packages/core/src/events/m.room.redaction.ts (1)
  • redactionEvent (37-88)
🔇 Additional comments (3)
packages/federation-sdk/src/services/staging-area.service.ts (1)

226-237: LGTM! Redaction payload correctly reads from top-level redacts.

The change aligns with the PR's refactor to move redacts from content to the top-level event property. The isRedactedEvent type guard ensures the redacts field exists before this code executes.

packages/core/src/events/m.room.redaction.spec.ts (1)

57-94: LGTM! Test fixture updated to reflect top-level redacts.

The test correctly validates that redacts is present as a top-level property of the redaction event (line 81-82). The reordering of the redacts field in the fixture aligns with the new event structure.

packages/homeserver/src/controllers/internal/message.controller.ts (1)

149-179: Approve simplified redactMessage controller update

Controller now calls redactMessage(roomId, messageId), matching the updated service signature in MessageService. The service internally derives the sender via eventService.getEventById, so no senderUserId needs to be passed. LGTM.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/federation-sdk/src/services/message.service.ts (1)

422-425: Pass redactingUserId to redactMessage in the homeserver controller
In packages/homeserver/src/controllers/internal/message.controller.ts (line 156), the call

await messageService.redactMessage(roomId, params.messageId as EventID)

must include the ID of the user performing the deletion as the third argument.

♻️ Duplicate comments (2)
packages/core/src/events/eventBase.ts (1)

43-43: Test coverage needed for runtime check.

The new runtime check 'redacts' in event is missing test coverage, as indicated by Codecov (50% patch coverage) and a previous review comment.

packages/federation-sdk/src/services/message.service.ts (1)

436-439: CRITICAL: Redaction sender must be the acting user, not the message author.

Lines 436-439 fetch the event being redacted and extract its sender, which is then used as the redaction sender (line 454). This violates the Matrix specification and creates several critical problems:

  1. Spec violation: The redaction sender must be the user performing the redaction, not the author of the original message.
  2. Breaks admin deletions: An admin cannot delete another user's message because the redaction would be signed by the original author.
  3. Cross-domain failure: Cannot redact events authored on foreign domains (you cannot legitimately sign PDUs as @alice:remote.net from your homeserver).

The redactMessage function must accept a redactingUserId parameter representing the user performing the deletion. Fetch the target event only for validation, then use the redacting user as the sender:

 	async redactMessage(
 		roomId: string,
 		eventIdToRedact: EventID,
+		redactingUserId: string,
 	): Promise<string> {
 		const isTombstoned = await this.roomService.isRoomTombstoned(roomId);
 		if (isTombstoned) {
 			this.logger.warn(
 				`Attempted to delete a message in a tombstoned room: ${roomId}`,
 			);
 			throw new ForbiddenError('Cannot delete a message in a tombstoned room');
 		}
 
 		const roomInfo = await this.stateService.getRoomInformation(roomId);
 
-		const senderUserId = await this.eventService.getEventById(eventIdToRedact);
-		if (!senderUserId?.event.sender) {
-			throw new Error(`Sender user ID not found for event ${eventIdToRedact}`);
-		}
+		const eventToRedact = await this.eventService.getEventById(eventIdToRedact);
+		if (!eventToRedact?.event) {
+			throw new Error(`Event not found: ${eventIdToRedact}`);
+		}
 
 		const redactionEvent =
 			await this.stateService.buildEvent<'m.room.redaction'>(
 				{
 					type: 'm.room.redaction',
 					content: {
 						reason: `Deleting message: ${eventIdToRedact}`,
 					},
 					redacts: eventIdToRedact,
 					room_id: roomId,
 					auth_events: [],
 					depth: 0,
 					prev_events: [],
 					origin_server_ts: Date.now(),
-					sender: senderUserId.event.sender,
+					sender: redactingUserId,
 				},
 				roomInfo.room_version,
 			);
🧹 Nitpick comments (1)
packages/core/src/events/m.room.redaction.ts (1)

62-63: Update misleading comment.

The comment states "Extract redacts from content" but the code no longer extracts redacts from content. Instead, redacts is now a top-level parameter.

Apply this diff to clarify the comment:

-	// Extract redacts from content - it must be at top level only
-	const { reason } = content;
+	// Extract reason from content (redacts is handled as a top-level parameter)
+	const { reason } = content;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f684355 and 512b3bb.

📒 Files selected for processing (6)
  • packages/core/src/events/eventBase.ts (1 hunks)
  • packages/core/src/events/m.room.redaction.spec.ts (1 hunks)
  • packages/core/src/events/m.room.redaction.ts (2 hunks)
  • packages/federation-sdk/src/services/message.service.ts (2 hunks)
  • packages/federation-sdk/src/services/staging-area.service.ts (1 hunks)
  • packages/room/src/types/v3-11.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/room/src/types/v3-11.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/core/src/events/m.room.redaction.spec.ts
  • packages/federation-sdk/src/services/staging-area.service.ts
🧰 Additional context used
🧬 Code graph analysis (3)
packages/core/src/events/m.room.redaction.ts (2)
packages/federation-sdk/src/index.ts (1)
  • EventID (23-23)
packages/room/src/types/_common.ts (1)
  • EventID (8-8)
packages/core/src/events/eventBase.ts (2)
packages/room/src/manager/event-wrapper.ts (1)
  • event (108-117)
packages/room/src/types/_common.ts (1)
  • PduForType (14-14)
packages/federation-sdk/src/services/message.service.ts (1)
packages/core/src/events/m.room.redaction.ts (1)
  • redactionEvent (37-88)
🔇 Additional comments (2)
packages/core/src/events/m.room.redaction.ts (1)

37-61: LGTM! Function signature correctly reflects top-level redacts.

The redactionEvent function signature has been correctly updated to accept redacts as a top-level parameter rather than within content. This aligns with the Matrix specification and the PR's objective.

packages/federation-sdk/src/services/message.service.ts (1)

352-375: LGTM! Correct top-level redacts field in unsetReaction.

The addition of redacts: eventIdReactedTo as a top-level field (line 359) correctly aligns with the PR's objective to move redacts out of content.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/federation-sdk/src/services/room.service.ts (1)

930-936: Use logger utility instead of console.log.

This debug output uses console.log rather than the structured logger utility used elsewhere in the codebase.

Apply this diff to use the logger:

 				if (!authEvent) {
 					for (const stateEvent of eventMap.keys()) {
-						console.log(
+						logger.debug(
 							`${stateEvent} -> ${JSON.stringify(
 								eventMap.get(stateEvent)?.event,
 								null,
 								2,
 							)}`,
 						);
 					}
 					throw new Error(`Auth event ${authEventId} not found`);
 				}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 512b3bb and e9b7aae.

📒 Files selected for processing (3)
  • packages/federation-sdk/src/services/room.service.ts (9 hunks)
  • packages/federation-sdk/src/services/staging-area.service.ts (1 hunks)
  • packages/room/src/types/v3-11.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/federation-sdk/src/services/staging-area.service.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/room/src/types/v3-11.ts (1)
packages/room/src/types/_common.ts (1)
  • eventIdSchema (6-6)
packages/federation-sdk/src/services/room.service.ts (2)
packages/federation-sdk/src/index.ts (1)
  • EventEmitterService (69-69)
packages/room/src/manager/event-wrapper.ts (2)
  • roomId (78-80)
  • event (108-117)
🔇 Additional comments (9)
packages/room/src/types/v3-11.ts (2)

198-200: Correct removal of redacts from content schema.

The PduRoomRedactionContentSchema now correctly contains only reason, with redacts moved to the top-level event structure (line 694). This aligns with the Matrix specification where redaction events carry redacts as a top-level field rather than within content.


694-694: Approve redacts top‐level and refine its description

In packages/room/src/types/v3-11.ts at line 694, update to:

-   redacts: eventIdSchema.describe('event id'),
+   redacts: eventIdSchema.describe('The ID of the event being redacted'),

Legacy content.redacts usages remain intentional for migration and test coverage—no further consumer updates required.

Likely an incorrect or invalid review comment.

packages/federation-sdk/src/services/room.service.ts (7)

42-42: LGTM!

The import of EventEmitterService is correct and aligns with the new functionality added to emit membership events.


48-57: LGTM!

The EventEmitterService dependency injection is correctly implemented and follows the established pattern for constructor injection in this service.


474-478: LGTM!

The multi-line formatting improves readability of the error log message. The logic remains unchanged and properly handles missing auth events.


626-628: LGTM!

The multi-line formatting improves readability of the kick action log message.


707-709: LGTM!

The multi-line formatting improves readability of the ban action log message.


962-964: LGTM!

The multi-line formatting improves readability of the log message.


1007-1010: LGTM!

The multi-line formatting improves readability of the state logging message.

@ggazzo ggazzo merged commit 721d0c5 into main Oct 1, 2025
3 checks passed
@ggazzo ggazzo deleted the fix/delete-message branch October 1, 2025 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants