Skip to content

PRD: Activity notifications & realtime push

ModuleNền tảng (CORE-16)PRD IDPRD-ACT-001
StatusShippedOwnerPhát Nguyễn
Date2026-06-15Versionv1.0
Năng lựcThông báo · gửi real-timeURDACT · WSS

TL;DR

Một hoạt động nghiệp vụ đáng chú ý lập tức trở thành thông báo gửi đến đúng người: nền tảng phát một hoạt động tới đúng đối tượng - cả một organizer, cả một merchant, hay một danh sách user cụ thể - lưu một bản ghi cho mỗi người nhận và đẩy từng thông báo qua kênh real-time đã xác thực, mã hóa đầu cuối. Mỗi user chỉ đọc và xóa thông báo của riêng mình; kênh có rớt thì bản ghi vẫn còn nên không mất gì, và người vận hành có một bộ điều khiển tinh gọn để theo dõi và điều phối các kết nối đang mở.

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

BANA liên tục tạo ra những khoảnh khắc đáng chú ý - một thanh toán hoàn tất, một đơn hàng xong - nhưng mỗi sự kiện đều mắc kẹt trong service đã sinh ra nó. Chưa có cách nào ở tầm nền tảng biến một hoạt động thành thông báo bền vững theo từng người rồi đưa lên màn hình ngay lúc nó xảy ra; nhân viên phải refresh và truy vấn lại mới biết có gì thay đổi.

Cái còn thiếu là một backbone tách việc sinh ra hoạt động khỏi việc gửi nó đi: một seam sự kiện mà service nào cũng phát lên được, một worker phân phát một hoạt động tới đúng người nhận trong đúng phạm vi tenant, một bản ghi bền vững sống sót qua sự cố mất kết nối, và một transport live đẩy mỗi thông báo tới đúng chủ của nó - và chỉ chủ của nó.

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

2. Mục tiêu & Ngoài mục tiêu

Mục tiêu

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

Ngoài mục tiêu

  • Kênh email / SMS / push-notification - increment này chỉ làm 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 producer - phát hoạt động là việc của producer; năng lực này tiêu thụ nó.
  • Siết ủy quyền kênh để chống truy cập chéo tenant trên transport (follow-up đã biết, xem §11).
  • Thiết kế giao diện chuông / activity-feed - PRD này đặc tả API và hợp đồng gửi để 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ỉ chéo tenant
Độ bềnMỗi recipient có một bản ghi được lưu kể cả khi kết nối của họ đứt; read-state vẫn còn sau khi kết nối lại
Giới hạn theo người dùngMộ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, không gây lỗi pipeline nào

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 organizer 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 kết nối 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, service thanh toán phát một hoạt động thanh toán thành công kèm actor và đơn hàng. Worker phân giải người nhận cho phạm vi đó, render một thông điệp dễ đọc, và ghi mỗi người một thông báo. Người nhận đang giữ kết nối live thấy nó hiện tức thì trên kênh riêng; người đang offline thấy nó chờ sẵn ở lần tải sau. Người dùng có thể đánh dấu đã đọc - hoặc xóa tất cả một lần - và read-state giữ nguyên qua các phiên.

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 luôn 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 nhận thông báo qua một kênh live đã 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ả organizer, cả merchant, hoặc một danh sách user cụ thể - quay về actor khi không có aiURD-ACT-002
FR-3Mỗi thông báo lưu recipient, type, organizer, nội dung văn bản thuần + văn bản định dạng đã render, một liên kết hành động tùy chọn, dữ liệu có cấu trúc (kể cả actor), và một cờ đọc kèm timestampURD-ACT-003
FR-4Nội dung được render từ event type thành một thông điệp dễ đọc (một chuỗi văn bản thuần + văn bản định dạng đã render cho mỗi thông báo, giống nhau cho mọi recipient); 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ỗi. Hiện tại type live duy nhất render một chuỗi tiếng Việt cố định - bản địa hóa theo ngôn ngữ từng user chưa được hiện thựcURD-ACT-004 · URD-ACT-005
FR-5Một user đã đăng nhập liệt kê thông báo của riêng mình (phân trang / lọc) kèm 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 tất cả, mỗi cái mang một timestamp đọcURD-ACT-007 · URD-ACT-008
FR-7Mọi thao tác đọ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 transport real-timeURD-WSS-001
FR-9Client kết nối qua một kênh đã xác thực và hoàn tất một handshake trao đổi khóa mã hóa; payload sau handshake được mã hóa đầu cuốiURD-WSS-002
FR-10Việc gửi dùng một hợp đồng kênh/topic cố định và fan-out giữa các instance; kênh thiếu hoặc một push lỗi sẽ 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 kết nối cho quản trị - trạng thái, list client, get client, broadcast, send-to-channel, send-to-client, disconnect - có sẵn sau lớp 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 organizer / merchant; read API của user giới hạn trong chính tài khoản của họ - không rò rỉ chéo tenant hay chéo user
Độ bềnMỗi push đều dựa trên một bản ghi đã lưu; read-state truy được sau khi kết nối lại
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 tải 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 tới từng recipient được xử lý độ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 và mã hóa đầu cuối sau một handshake trao đổi khóa mã hóa
Hợp đồng đăng ký ổn địnhMột kênh riêng cố định cho từng recipient và một topic thông báo cố định, để client đăng ký theo một hợp đồng ổn định
Gửi liên instanceMột fan-out liên instance gửi tới một recipient bất kể kết nối của họ được thiết lập ở đâu
i18nBản ghi thông báo lưu một chuỗi văn bản thuần + văn bản định dạng đã render; seam nội dung được điều khiển theo event type nên về sau một renderer có thể bản địa hóa, nhưng type live duy nhất hiện phát ra một chuỗi tiếng Việt cố định chứ không phải nội dung theo ngôn ngữ từng recipient

8. UX & Luồng

Client giữ một kết nối đã xác thực, đã mã hóa và đăng ký kênh riêng của mình; trên topic thông báo, chuông hoạt động được thiết kế để hiện mỗi thông báo mới. Người nhận offline thấy nó chờ sẵn qua read API ở lần tải sau, và việc đánh dấu một - hoặc tất cả - là đã đọc giúp số chưa đọc nhất quán qua các phiên.

Trạng thái phía client: pipeline backend, read API và hợp đồng gửi real-time đều đã chạy, nhưng chuông thông báo trong ứng dụng ở footer client hiện đang tắt - chưa hiển thị cho user merchant. Thành phần này đã có sẵn (một chuông ở góc footer bên trái, mở ra notification sheet) nhưng được ship ở trạng thái tắt, nên người dùng cuối hôm nay chưa thấy thông báo trong ứng dụng; surface dành cho merchant là một follow-up sẽ dùng lại backbone đã ship sẵn này.

9. Dữ liệu & Miền

Thực thểVai trò
Bản ghi thông báoBản ghi theo từng recipient được lưu - recipient, type, organizer, nội dung (văn bản thuần + định dạng), liên kết hành động, 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 trong phạm vi organizer hoặc merchant của hoạt động; danh sách chỉ định cụ thể và fallback về actor đều được tôn trọng
Kênh + topic theo từng recipientKênh real-time 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

  • Lõi nền tảng - sở hữu định nghĩa bản ghi thông báo, registry event-type được nhận diện, topic + hợp đồng thông điệp của luồng hoạt động, và việc phân giải recipient từ dữ liệu membership.
  • Luồng sự kiện hoạt động - seam ingest giữa producer hoạt động và notification worker.
  • Transport real-time + fan-out liên instance - kênh gửi live được xác thực, mã hóa và chạy liên instance.
  • Các service tạo sự kiện - phát activity event (ví dụ luồng thanh toán phát một hoạt động thanh toán thành công).

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 organizer / merchant có sẵn cho việc phân giải recipient.
  • Client duy trì một kết nối live và đăng ký kênh riêng của từng recipient.

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 read API giới hạn theo người dùng ở 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ế độ chỉ lưu; push tới từng recipient được xử lý độc lập nên một lỗi không bao giờ chặn các push khác
Rò rỉ chéo user trong read APIMọi thao tác đọc / ghi giới hạn theo user đã 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ý kênh chéo tenant trên transportFollow-up tăng cường đã biết - ủy quyền kênh hiện còn dễ dãi; kênh admin / global không được phát tới
Trôi tên kênh / topic giữa producer và clientCố định một kênh riêng cho từng recipient và một topic thông báo cố định, xem như một hợp đồng ổn định
Hiện chỉ có một event type live (một thanh toán thành công)Pipeline được điều khiển theo type và tái dùng được; event type mới chỉ cần thêm một renderer mà không phải làm lại backbone
Surface client trong ứng dụng chưa liveChuông thông báo ở footer được ship ở trạng thái tắt - backbone (gửi, lưu trữ, read API) đã ship, nhưng user merchant chưa thấy thông báo trong ứng dụng cho tới khi surface client được bật ở một follow-up

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úKho bản ghi thông báo mới; không cần 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 giới hạn theo người dùng hoạt động đúng; một sự cố real-time tụt xuống chế độ chỉ lưu; điều khiển kết nối quản trị được permission bảo vệ
Giám sátLượng thông báo, độ trễ gửi, sức khỏe kết nối live, độ đúng của việc phân giải recipient, tỷ lệ push lỗi

13. FAQ

Đối tượng của một thông báo được chọn thế nào? Theo phạm vi người nhận của hoạt động - cả organizer, cả merchant, hay một danh sách user cụ thể. Nếu không phân giải ra ai, actor của hoạt động sẽ nhận nó.

Người nhận offline thì sao? Thông báo vẫn được lưu; client đọc lại nó qua read API giới hạn theo người dùng ở lần tải sau, 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 lúc kết nối và hoàn tất một lần trao đổi khóa mã hóa; mọi payload sau handshake đều mã hóa đầu cuối.

Một user có thấy thông báo của người khác không? Không - mọi thao tác list, count, mark-read đều giới hạn theo user đã xác thực.

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

Hiện chỉ có thanh toán? Pipeline được điều khiển theo event type. Một thanh toán thành công là type live đầu tiên; loại mới chỉ cần cắm thêm 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.