Skip to content

PRD: Activity notifications & websocket push

ModuleNền tảng (CORE-16)PRD IDPRD-ACT-001
StatusShippedOwnerPlatform / Signal squad
Date2026-06-15Versionv1.0
Packages@nx/signal · @nx/coreURDACT · WSS

TL;DR

Biến một hoạt động nghiệp vụ đáng chú ý thành thông báo đến đúng người, tức thì. Một activity event (ví dụ thanh toán thành công) rơi vào luồng hoạt động của nền tảng; một worker phân giải ai cần được biết - tất cả trong một tổ chức, tất cả trong một merchant, hoặc một danh sách user cụ thể - render một thông điệp bản địa hóa, lưu một bản ghi thông báo cho mỗi recipient, rồi đẩy từng bản ghi trực tiếp tới chủ sở hữu qua WebSocket được xác thực và mã hóa đầu-cuối. Mỗi user đọc, đếm và xóa chỉ thông báo của riêng mình qua một API tự-giới-hạn; nếu kênh real-time tạm thời không khả dụng thì các bản ghi vẫn được lưu, nên không mất gì. Người vận hành có một nhóm điều khiển transport tinh gọn để kiểm tra và điều phối các kết nối live.

1. Bối cảnh & Vấn đề

KICKO tạo ra một dòng liên tục các khoảnh khắc đáng chú ý - một thanh toán hoàn tất, một đơn hàng xong - nhưng cho đến nay những khoảnh khắc đó vẫn bị chôn trong service đã tạo ra chúng. Không có cách nào ở tầm nền tảng để biến một hoạt động thành một thông báo bền vững theo từng người, quyết định ai cần thấy, và đưa nó lên một màn hình live ngay khi nó xảy ra. Nhân viên phải refresh và truy vấn lại để biết có chuyện gì đã xảy ra.

Cái còn thiếu là một backbone duy nhất tách rời việc tạo ra một hoạt động với việc gửi nó: một seam sự kiện mà bất kỳ service nào cũng phát lên được, một worker fan-out một hoạt động tới đúng recipient trong đúng phạm vi tenant, một bản ghi bền vững để thông báo sống sót qua mất kết nối, và một transport live đẩy nó tới chủ sở hữu - và chỉ chủ sở hữu - theo thời gian thực.

Increment này cung cấp backbone đó như một năng lực nền tảng hạng nhất: pipeline activity-notification (ACT) và luồng WebSocket real-time (WSS) mà nó vận hành trên đó, kèm read API tự-giới-hạn và một hợp đồng gửi mã hóa, ổn định.

2. Mục tiêu & Không-mục-tiêu

Mục tiêu

  • Một pipeline hướng sự kiện: tiêu thụ activity event → phân giải recipient → render nội dung → lưu một bản ghi cho mỗi recipient → đẩy live.
  • Phân giải recipient theo phạm vi - fan một hoạt động ra một tổ chức, một merchant, hoặc một danh sách user, fallback về actor khi không có audience nào.
  • Một read API tự-giới-hạn bền vững - mỗi user list, đếm (kể cả chưa đọc), đánh dấu-đọc-một và đánh dấu-đọc-tất-cả chỉ thông báo của riêng mình.
  • Một push WebSocket live, được xác thực và mã hóa đầu-cuối tới kênh riêng của từng recipient, theo hợp đồng room/topic cố định.
  • Khả năng phục hồi - lưu trữ luôn thành công; kênh real-time thiếu hoặc lỗi không bao giờ làm hỏng pipeline và không bao giờ chặn các recipient khác.
  • Các điều khiển transport quản trị tinh gọn - trạng thái kết nối, liệt kê client, gửi có đích, broadcast và ngắt kết nối, sau permission.

Không-mục-tiêu

  • Kênh email / SMS / push-notification - increment này chỉ cung cấp kênh real-time trong ứng dụng.
  • Mô hình tùy chọn / tắt / đăng ký thông báo theo từng user.
  • Logic của chính các service tạo sự kiện - phát activity event là trách nhiệm của producer; năng lực này tiêu thụ nó.
  • Tăng cường ủy quyền room chống xuyên-tenant trên transport (một follow-up đã biết, xem §11).
  • Tạo kiểu UI chuông / activity-feed phía tiêu thụ - PRD này đặc tả API và hợp đồng gửi mà client render.

3. Chỉ số thành công

Chỉ sốMục tiêu / tín hiệu
Độ trễ gửiActivity event → push live tới recipient gần như tức thời (dưới một giây ở tải bình thường)
Độ chính xác recipientMột thông báo đến đúng các user trong phạm vi của hoạt động; không rò rỉ xuyên-tenant
Độ bềnMỗi recipient có một bản ghi được lưu kể cả khi socket của họ chết; read-state sống sót qua reconnect
Tự-giới-hạnMột user chỉ có thể đọc hoặc thay đổi thông báo của chính mình
Khả năng phục hồiMột sự cố real-time hoặc một push lỗi đơn lẻ tụt xuống chế độ chỉ-lưu, với zero pipeline lỗi

4. Personas & Use Cases

PersonaMục tiêu trong tính năng này
Chủ / Quản lýThấy hoạt động của tổ chức hoặc merchant hiện live, không cần refresh
Nhân viên / Thu ngânNhận các thông báo gửi tới mình và xóa chúng khi đã đọc
Client kết nối (web / POS)Giữ một socket live và phản ánh thông báo mới + read-state tức thì
Người vận hành nền tảngKiểm tra các kết nối live và điều phối hoặc cắt một phiên khi cần

Kịch bản cốt lõi: một thanh toán thành công và service thanh toán phát một hoạt động PAYMENT_SUCCESS mang theo actor và subject của đơn. Worker phân giải recipient cho phạm vi của hoạt động đó, render một thông điệp dễ đọc, và ghi một thông báo cho mỗi recipient. Mỗi recipient đang giữ một socket live thấy thông báo xuất hiện tức thì trên kênh riêng của mình; một recipient đang offline sẽ thấy nó chờ sẵn ở lần list thông báo tiếp theo. Recipient nào cũng đánh dấu đã đọc - hoặc xóa tất cả trong một thao tác - và read-state giữ nguyên qua các phiên của họ.

5. User Stories

  • Là một chủ, tôi muốn hoạt động xuất hiện ngay khi nó xảy ra, để tôi theo dõi việc kinh doanh mà không refresh.
  • nhân viên, tôi chỉ muốn các thông báo gửi cho tôi, để feed của tôi liên quan và không bao giờ hiện hoạt động của người khác.
  • Là một client kết nối, tôi muốn thông báo qua một socket live, được mã hóa, để cập nhật tức thì và riêng tư khi truyền.
  • Là một user, tôi muốn đếm thông báo chưa đọc và đánh dấu đã đọc - một hoặc tất cả, để feed phản ánh những gì tôi đã thấy.
  • nền tảng, tôi muốn một thông báo sống sót qua một kết nối bị rớt, để một user offline không bao giờ bỏ lỡ nó.
  • Là một người vận hành, tôi muốn thấy và điều phối các kết nối live, để chẩn đoán hoặc cắt một phiên.

6. Yêu cầu chức năng

#Yêu cầuURD ref
FR-1Một activity event trên luồng nền tảng được tiêu thụ và biến thành một thông báo cho mỗi recipient được phân giảiURD-ACT-001
FR-2Recipient được phân giải theo phạm vi - cả tổ chức, cả merchant, hoặc một danh sách user cụ thể - fallback về actor khi không có aiURD-ACT-002
FR-3Mỗi thông báo lưu recipient, type, organizer, nội dung text + HTML đã render, action URL tùy chọn, dữ liệu có cấu trúc (kể cả actor), và cờ đọc + timestampURD-ACT-003
FR-4Nội dung được render từ event type thành một thông điệp bản địa hóa, dễ đọc; chỉ các event type được nhận diện mới tạo thông báo, type lạ bị bỏ qua không lỗiURD-ACT-004 · URD-ACT-005
FR-5Một user đã đăng nhập list thông báo của riêng mình (phân trang / lọc) với tổng số và số chưa đọcURD-ACT-006
FR-6Một user có thể đếm thông báo của mình (ví dụ chưa đọc) và đánh dấu đọc một hoặc đọc tất cả, mỗi cái mang một timestamp đọcURD-ACT-007 · URD-ACT-008
FR-7Mọi đọc và ghi đều giới hạn theo recipient đã xác thực - một user không bao giờ thấy hoặc thay đổi thông báo của người khácURD-ACT-009
FR-8Khi tạo, mỗi thông báo được đẩy live tới kênh riêng của recipient qua WebSocketURD-WSS-001
FR-9Client kết nối qua một socket được xác thực (JWT bearer) với handshake ECDH; payload sau handshake được mã hóa đầu-cuốiURD-WSS-002
FR-10Gửi dùng một hợp đồng room/topic cố định và fan-out giữa các instance; kênh thiếu hoặc một push lỗi tụt xuống chế độ chỉ-lưu mà không chặn các recipient khácURD-WSS-003 · URD-WSS-004 · URD-WSS-005
FR-11Các điều khiển transport quản trị - trạng thái, list client, get client, broadcast, send-to-room, send-to-client, disconnect - có sẵn sau permissionURD-WSS-006

Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong Platform URD - ACTWSS. PRD này tham chiếu chúng thay vì lặp lại.

7. Yêu cầu phi chức năng

Lĩnh vựcYêu cầu
Tenancy & cô lậpPhân giải recipient giới hạn theo tổ chức / merchant; read API của user giới hạn theo user ID của chính họ - không rò rỉ xuyên-tenant hay xuyên-user
Độ bềnMỗi push được hậu thuẫn bởi một bản ghi đã lưu; read-state truy được sau reconnect
Tách rời & quy môSeam sự kiện tách producer khỏi fan-out; một worker hấp thụ các đợt bùng mà không chặn producer
Khả năng phục hồiLưu trữ độc lập với kênh real-time; push theo từng recipient được settle độc lập nên một lỗi không bao giờ chặn phần còn lại
Bảo mậtKênh live được xác thực (JWT) và mã hóa đầu-cuối (AES dẫn xuất từ ECDH) sau handshake
Ổn định transportĐặt tên room (theo từng recipient) và topic (observation.signal.notification.created) cố định để client đăng ký theo một hợp đồng ổn định
Gửi xuyên-instanceFan-out hậu thuẫn bởi Redis gửi tới một recipient bất kể socket của họ kết nối ở đâu
i18nNội dung thông báo hướng người dùng được render theo ngôn ngữ của user

8. UX & Luồng

Client giữ một socket được xác thực, được mã hóa và đăng ký kênh-theo-từng-recipient của riêng mình; trên observation.signal.notification.created nó hiện thông báo mới ở chuông hoạt động. Một recipient đang offline lúc emit sẽ thấy thông báo chờ sẵn qua read API ở lần tải tiếp theo. Đánh dấu một - hoặc tất cả - đã đọc làm số chưa đọc nhất quán qua các phiên.

9. Dữ liệu & Miền

Thực thểVai trò
ActivityNotificationBản ghi theo từng recipient được lưu - recipient, type, organizer, nội dung (text + HTML), action URL, dữ liệu có cấu trúc, cờ đọc + timestamp
Activity eventThông điệp đầu vào trên luồng hoạt động - event type, recipient scope, actor, organizer / merchant, recipient cụ thể tùy chọn, payload
Phân giải recipientTra cứu các user ID trong phạm vi tổ chức hoặc merchant của hoạt động; danh sách cụ thể và actor-fallback được tôn trọng
Kênh + topic theo từng recipientRoom WebSocket riêng của recipient và topic notification-created - hợp đồng gửi live

Chỉ mang tính khái niệm - schema và bất biến đầy đủ nằm trong developer domain model.

10. Phụ thuộc & Giả định

Phụ thuộc vào

  • @nx/core - sở hữu schema / model / repository của ActivityNotification, registry event-type được nhận diện, topic + message types của luồng hoạt động, và phân giải recipient qua policy/membership repository.
  • Activity stream (Kafka) - seam ingest giữa producer hoạt động và notification worker.
  • WebSocket transport + Redis - kênh gửi live được xác thực, mã hóa, xuyên-instance.
  • Các service tạo sự kiện - phát activity event (ví dụ luồng thanh toán phát PAYMENT_SUCCESS).

Giả định

  • Producer phát các activity event đúng định dạng lên topic luồng đã thỏa thuận.
  • Dữ liệu membership tổ chức / merchant có sẵn cho phân giải recipient.
  • Client duy trì một kết nối WebSocket và đăng ký kênh-theo-từng-recipient của riêng mình.

11. Rủi ro & Câu hỏi mở

Rủi ro / câu hỏiGiảm thiểu / trạng thái
Một recipient đang offline khi hoạt động phátBản ghi vẫn được lưu bất kể; client đọc lại nó qua API tự-giới-hạn ở lần tải tiếp theo
Kênh real-time không khả dụng hoặc một push lỗiPipeline tụt xuống chỉ-lưu; push theo từng recipient được settle độc lập nên một lỗi không bao giờ chặn phần khác
Rò rỉ xuyên-user trong read APIMọi đọc / ghi giới hạn theo user ID đã xác thực - một user không thể chạm tới thông báo của người khác
Đăng ký room xuyên-tenant trên transportFollow-up tăng cường đã biết - ủy quyền room hiện đang dễ dãi; room admin / global không được emit tới
Trôi tên room / topic giữa producer và clientCố định theo room-theo-từng-recipient và topic observation.signal.notification.created như một hợp đồng ổn định
Hôm nay chỉ một event type live (PAYMENT_SUCCESS)Pipeline hướng-type và tái dùng được; event type mới chỉ thêm một renderer mà không làm lại backbone

12. Kế hoạch phát hành & Tiêu chí ra mắt

Khía cạnhKế hoạch
PhaseP2 - ACTWSS trong URD feature catalog
Triển khaiTất cả merchant; không feature flag
Di trúThực thể ActivityNotification mới; không di trú dữ liệu
Tiêu chí ra mắtActivity event → phân giải recipient → bản ghi đã lưu → push live được kiểm chứng end-to-end; list / count / mark-read / mark-all-read tự-giới-hạn hoạt động; một sự cố real-time tụt xuống chỉ-lưu; điều khiển transport quản trị bị permission gate
Giám sátLượng thông báo, độ trễ gửi, sức khỏe kết nối WebSocket, độ đúng phân giải recipient, tỷ lệ push lỗi

13. FAQ

Audience cho một thông báo được chọn thế nào? Theo recipient scope của hoạt động - cả tổ chức, cả merchant, hoặc một danh sách user cụ thể. Nếu không cái nào phân giải ra ai, thì actor của hoạt động nhận nó.

Điều gì xảy ra nếu recipient offline? Thông báo vẫn được lưu. Client thấy nó qua read API tự-giới-hạn ở lần tải tiếp theo, và read-state giữ nguyên qua các phiên.

Kênh live có an toàn không? Có - client xác thực bằng JWT bearer qua socket và hoàn tất một trao đổi khóa ECDH; tất cả payload sau handshake được mã hóa đầu-cuối.

Một user có thể thấy thông báo của người khác không? Không - mọi list, count và mark-read giới hạn theo user đã xác thực; read API không bao giờ trả về bản ghi của user khác.

Nếu push real-time lỗi thì sao? Việc gửi tụt xuống chỉ-lưu một cách mượt mà - bản ghi đã được ghi rồi, và một lỗi cho một recipient không bao giờ chặn các recipient khác.

Hôm nay chỉ thanh toán? Pipeline hướng event-type. PAYMENT_SUCCESS là type live đầu tiên; các loại hoạt động mới cắm vào một content renderer và tái dùng toàn bộ backbone.

Tham khảo

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.