Skip to content

feat: add buyer-vendor messaging plugin#829

Open
kjedras wants to merge 3 commits into
mainfrom
002-buyer-vendor-messaging
Open

feat: add buyer-vendor messaging plugin#829
kjedras wants to merge 3 commits into
mainfrom
002-buyer-vendor-messaging

Conversation

@kjedras
Copy link
Copy Markdown
Collaborator

@kjedras kjedras commented Mar 30, 2026

Summary

  • Buyer-vendor messaging — customers and sellers can exchange messages through store/vendor API routes with real-time SSE delivery
  • Content filtering — built-in regex rules (email, phone, URL) plus admin-managed exact/contains filters to prevent contact info sharing
  • Chat blocking — admins can block/unblock customers with reason, enforced across all endpoints
  • Admin oversight — conversation search with name/date/context filters, blocked message log, and filter rule CRUD
  • Rate limiting — 20 messages/minute and 5 new conversations/hour per sender via Redis sliding window
  • GDPR compliance — anonymize workflows for buyer/vendor deletion with compensation steps and batched processing
  • Full UI — admin and vendor dashboard pages for conversations, message detail, filters, and blocked messages
  • 95 files in the registry block with documentation (DOCUMENTATION.md, IMPLEMENTATION.md), unit tests, and integration tests

Test plan

  • 88/88 manual endpoint tests pass (auth, CRUD, unread tracking, context linking, validation, ownership, content filtering, filter CRUD, chat blocking/unblocking, admin oversight, pagination, rate limiting, SSE, edge cases)
  • Unit tests pass: rate limiting, content filter evaluation, cursor encoding, unread counters, chat blocking
  • Registry.json file list matches actual files on disk (95 files)
  • Documentation accurate and up to date with implementation

🤖 Generated with Claude Code

kjedras and others added 3 commits March 27, 2026 21:05
Complete messaging plugin with security hardening from code review:
- Atomic SSE token consumption (GETDEL instead of GET+DEL)
- Atomic rate limiting via Lua script (INCR+EXPIRE in single call)
- SSE frame injection prevention (sanitize last_event_id)
- Transaction safety for message creation and read marking
- LIKE pattern escaping in admin search
- ReDoS protection for admin-supplied regex filters
- Anonymization pagination loop for GDPR compliance
- Reconcile job rewritten with single SQL aggregation (eliminates N+1)
- Vendor orders scoped to seller (prevents cross-seller data leak)
- Frontend SSE hooks rewritten with refs (fixes timer leak + re-render loop)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bump

Addresses ~40 issues from code review:
- Security: XSS sanitization, crypto.randomUUID for IDs, admin auth fix
- Chat blocking: block/unblock customers with reason, admin/vendor visibility
- Rate limit: 10 → 20 messages/minute for better UX
- Bug fixes: unblock SDK path (kebabCase mangling), NULLS LAST ordering
- Architecture: compensation steps, batch processing, DB indexes
- UI: shared layout hook, SSE backoff, pagination support
- Registry: 3 missing files added, documentation updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kjedras kjedras requested review from Si3r4dz and vholik March 30, 2026 10:54
@kjedras kjedras self-assigned this Mar 30, 2026
// Check message rate limit: 20 per minute
const msgResult = await redisService.checkRateLimit(
`ratelimit:msg:${input.sender_id}`,
20,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should this not be configurable in the module's specs in medusa-config.ts?

import { MESSAGING_REDIS_MODULE } from "../../../../modules/messaging-redis"
import type MessagingRedisModuleService from "../../../../modules/messaging-redis/service"

export const GET = async (
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SSE is fine for simple plugin, but I don't see this scaling well for a production-ready marketplace solution, due to SSE limitations, e.g.:

  • most browsers only support around 6 SSE connections, so if some users open few windows each with different chat, it will break
  • it's one way communication server -> customer, not a real-time chat

I'd consider switching to full websocket implementation using Socket.io. Unless for larger marketplaces we'll use custom integrations, like TalkJS/Sendbird?

Something to think about, in the end it's better to have something than nothing

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.

3 participants