PRD: Phân quyền theo phạm vi từng merchant
| Module | Phân quyền | PRD ID | PRD-EFF-001 |
| Trạng thái | Sẵn sàng dev | FEAT | EFF · BANA-1436 |
| Epic | — | Plane | BANA-1548 |
| Ngày | 2026-06-04 | Phiên bản | v1.0 |
| Gói | @nx/identity | URD | EFF |
| Surface | Backend | ||
| Phụ trách | Phát Nguyễn | ||
Phân quyền theo phạm vi từng merchant là gì
Tập trung phân quyền lên một policy engine theo merchant, để mọi verifier service enforce các grant trong merchant đang hoạt động được chọn theo từng request, và giải quyết những merchant/organizer mà người dùng tiếp cận được từ kho policy phân quyền thay vì lọc theo request context rải rác. Kết quả: "người dùng này thấy và làm được gì ở đây" trở thành một câu trả lời nhất quán, dựa trên policy, xuyên suốt commerce, finance và inventory - với cô lập theo merchant và tôn trọng soft-delete.
Vì sao cần tập trung lại
Phân quyền trong BANA ban đầu được điều khiển bằng lọc theo request context: mỗi service tự suy ra những organization và merchant mà người dùng tiếp cận được từ request rồi lọc thủ công các truy vấn của mình. Điều này khiến "người dùng này thấy được gì" trở nên ngầm định, lặp lại khắp các service, và không thể suy luận tại một nơi duy nhất - đồng thời không có chỗ chung nào để giải quyết một grant trong merchant đang hoạt động mà request đang hoạt động trên đó.
Một engine scoped-RBAC tập trung trên mọi verifier service lấp khoảng trống này: phân quyền cấp route được enforce theo cùng một cách ở mọi nơi qua policy engine, và tầm với merchant của HQ được mở rộng từ membership organizer/merchant thay vì phỏng đoán theo từng request. Vì BANA cần nạp policy tôn trọng soft-delete và theo từng merchant, platform core cung cấp hợp đồng entity, cờ soft-delete và domain resolver theo merchant cho scoped Casbin adapter của framework - không phải sửa framework. Inventory là bề mặt thí điểm đầu tiên; các coarse role grant nay đã được seed trên mọi module/verifier service.
Chỗ dễ sai nhất
Merchant đang hoạt động quyết định phạm vi, không phải quyền của người dùng
Quyền của một người dùng (họ được làm gì) và merchant đang hoạt động của request (họ đang thao tác ở đâu) là hai câu hỏi khác nhau. Một quyền được cấp trên một merchant chỉ có hiệu lực khi người dùng đang thao tác đúng merchant đang hoạt động của request đó - chuyển sang merchant khác, quyền đó không tự áp dụng theo dù người dùng không đổi.
Đây cũng là lý do một Owner sở hữu nhiều merchant vẫn phải đổi merchant đang hoạt động trên giao diện để thao tác ở merchant khác, thay vì thấy gộp dữ liệu của mọi merchant cùng lúc.
1. Mục tiêu & Loại trừ
Mục tiêu
- Enforce phân quyền trên mọi verifier service, giải quyết các grant trong merchant đang hoạt động được chọn theo từng request.
- Điều khiển phân quyền cấp route qua kho policy; giải quyết merchant đang hoạt động theo từng request (dùng cho lọc dữ liệu cấp dòng) từ header active-store, và mở rộng tầm với HQ từ membership organizer/merchant, thay vì tự phân tích request theo từng service (commerce, finance, core).
- Cấu hình scoped Casbin adapter của framework từ platform core - cung cấp hợp đồng entity tôn trọng soft-delete và theo merchant cùng domain resolver - không cần sửa framework.
- Triển khai enforcement theo merchant bắt đầu từ inventory và nay trên mọi verifier service: seed coarse role permission theo từng module và cấp cho owner membership merchant khi tạo merchant.
- Giữ engine đồng bộ với scoped RBAC model của nền tảng (đúng đắn của scoped model, policy loader theo phạm vi, vô hiệu hoá cache policy khi refresh token).
Loại trừ
- Permission wildcard / regex - ngoài phạm vi (xem Loại trừ trong URD).
- Permission categories / nhóm UI, và role template / bundle.
- Permission theo thời gian hoặc theo ca, và ghi log audit permission.
- Bộ công cụ phân cấp resource / action / domain và khai báo - thuộc về PRD-HIER-001 (
HIER,DECL).
2. Thước đo thành công
| Thước đo | Mục tiêu / tín hiệu |
|---|---|
| Enforcement tập trung | 100% quyết định phân quyền của verifier service đi qua engine tập trung, không phải lọc request tuỳ tiện |
| Đúng đắn của scope | Độ tiếp cận merchant/organizer giải quyết từ policy khớp với grant thực tế của người dùng; không rò rỉ dữ liệu merchant lạ |
| Cô lập tenant | Các dòng policy/membership không bao giờ vượt ranh giới một merchant |
| Trung thực soft-delete | Grant đã thu hồi (soft-delete) không bao giờ được enforce như đang hiệu lực |
| Ổn định thí điểm | Inventory vận hành hoàn toàn dưới phân quyền theo merchant mà không hồi quy ở việc giải quyết merchant được phép |
3. Persona & Tình huống
| Persona | Mục tiêu trong tính năng này |
|---|---|
| Owner | Chỉ tiếp cận organizer của chính mình và các merchant của nó - giải quyết nhất quán từ policy |
| Employee / Cashier | Chỉ thao tác trong các merchant được giao, enforce theo merchant đang hoạt động |
| Quản trị nền tảng | Tin cậy một đường enforcement tập trung duy nhất xuyên mọi verifier service |
| Service (verifier) | Giải quyết các merchant ID được phép từ policy thay vì lọc tuỳ biến theo từng request |
Core scenarios: một request đến và chọn một merchant đang hoạt động → verifier enforce grant trong merchant đó qua engine tập trung → các merchant/organizer tiếp cận được giải quyết từ kho policy → các grant đã soft-delete bị loại trừ và các dòng tenant giữ nguyên cô lập theo merchant.
4. User Stories
| # | Là một | Tôi muốn | Để |
|---|---|---|---|
| 01 | quản trị nền tảng | phân quyền được enforce tập trung trong verifier | mọi service trả lời "người dùng này làm được điều này ở đây không" theo cùng một cách |
| 02 | owner | các merchant tiếp cận được của mình giải quyết từ policy | tôi thấy đúng các merchant của organizer mình và không thấy gì lạ |
| 03 | employee | grant được enforce trong merchant đang hoạt động | truy cập của tôi giới hạn ở merchant tôi đang thao tác |
| 04 | lập trình viên service | giải quyết các merchant ID được phép từ kho policy | tôi ngừng lọc thủ công các truy vấn từ request context |
| 05 | quản trị nền tảng | grant đã thu hồi ngừng áp dụng ngay lập tức (không enforce dòng đã soft-delete) | việc thu hồi truy cập đáng tin cậy |
| 06 | quản trị nền tảng | token được refresh xoá cache policy | thay đổi role/permission có hiệu lực gọn gàng |
5. Yêu cầu chức năng
| # | Yêu cầu | Trạng thái | URD ref |
|---|---|---|---|
FR-001 | Mọi khu vực nghiệp vụ của hệ thống (bán hàng, tồn kho, tài chính, quản trị nền tảng...) áp dụng cùng một luật phân quyền tập trung. Không khu vực nào tự đặt luật kiểm tra quyền riêng. | 🚧 | URD-EFF-004 |
FR-002 | Một quyền được cấp trên một merchant chỉ có hiệu lực khi người dùng đang thao tác đúng merchant đang hoạt động của request đó. Chuyển sang thao tác ở merchant khác, quyền đó không tự áp dụng theo. | ✅ | URD-EFF-004 · URD-ROLE-005..006 |
FR-003 | Quyền hiệu lực của một người dùng là quyền cấp trực tiếp cộng với quyền kế thừa qua vai trò, gộp lại và loại bỏ trùng lặp. Khi tra cứu có thể lọc riêng phần trực tiếp, riêng phần kế thừa, hoặc xem cả hai. | ✅ | URD-EFF-001..002 |
FR-004 | Quyền truy cập một chức năng của hệ thống được xác định nhất quán từ cùng một nơi cho mọi request, không tùy biến riêng theo từng khu vực nghiệp vụ. Merchant đang hoạt động dùng để lọc dữ liệu theo dòng được lấy từ merchant người dùng đang chọn trên giao diện. | ✅ | URD-EFF-003 |
FR-005 | Cấp hoặc thu hồi một quyền có thể lặp lại nhiều lần mà không sinh dòng trùng hay báo lỗi. Một người dùng không thể tự cấp cho mình hoặc cho người khác quyền cao hơn quyền mình đang có. | 🔶 | URD-GRANT-001..007 |
FR-006 | Một quyền hoặc một thành viên (membership) đã bị gỡ không bao giờ được tính là đang còn hiệu lực. Bản ghi vẫn được giữ lại để tra cứu lịch sử. | ✅ | URD-EFF-004 |
FR-007 | Một thành viên (membership) chỉ được tra theo đúng loại phạm vi của nó (theo organizer hoặc theo merchant). Không loại nào lẫn sang loại khác hay lẫn sang merchant khác. | ✅ | URD-ROLE-007..008 |
FR-008 | Một Owner được gán ở merchant trụ sở của một organizer tự động vươn tới mọi merchant anh em thuộc organizer đó. Không cần được cấp quyền riêng cho từng merchant. | ✅ | URD-ROLE-009 |
FR-009 | Khi một merchant mới được tạo, chủ merchant (Owner) được cấp sẵn quyền quản lý theo vai trò trên mọi khu vực nghiệp vụ ngay lập tức. Không cần cấp tay từng quyền. | ✅ | URD-EFF-003..004 |
FR-010 | Sau khi vai trò hoặc quyền của một người dùng thay đổi, lần đăng nhập lại hoặc làm mới phiên kế tiếp của người đó áp dụng ngay thay đổi mới. Không cần chờ hay thao tác thêm. | ✅ | URD-EFF-004 |
5.1 Tiêu chí nghiệm thu
- Thao tác bị từ chối vì thiếu quyền ở module bán hàng, thử thao tác tương ứng ở module tồn kho hoặc tài chính với cùng lý do thiếu quyền → cũng bị từ chối theo đúng luật giống nhau.
- Một nhân viên được cấp quyền thao tác ở merchant A, thử thao tác tương tự khi đang ở merchant B chưa được cấp → bị từ chối; quay lại đúng merchant A → thao tác thành công.
- Một tài khoản vừa được gán vai trò có kèm quyền vừa được cấp thêm quyền riêng lẻ, tra cứu quyền hiệu lực → thấy cả hai loại, không dòng nào lặp lại; lọc chỉ xem phần cấp trực tiếp → chỉ thấy quyền cấp riêng; lọc chỉ xem phần kế thừa → chỉ thấy quyền từ vai trò.
- Chọn một merchant khác trên giao diện (đổi merchant đang hoạt động) → dữ liệu hiển thị đổi theo đúng merchant vừa chọn, không lẫn dữ liệu của merchant khác.
- Bấm cấp một quyền đã được cấp trước đó thêm lần nữa → không sinh dòng cấp quyền trùng, không báo lỗi; thu hồi một quyền đã thu hồi trước đó → không lỗi, quyền vẫn ở trạng thái đã thu hồi.
- Một người dùng không có quyền quản lý phân quyền thử tự cấp cho mình một quyền cao hơn quyền hiện có → bị từ chối.
- Thu hồi một quyền của một người dùng → ngay sau đó người này thao tác lại bị từ chối, dù bản ghi cấp quyền cũ vẫn còn trong lịch sử.
- Tra thành viên (membership) theo organizer của một người dùng → không lẫn với danh sách thành viên theo merchant của người khác, và ngược lại.
- Một Owner được gán ở merchant trụ sở của một organizer có nhiều merchant anh em → thấy và thao tác được ở mọi merchant anh em đó, dù chưa từng được cấp quyền riêng cho từng merchant.
- Tạo một merchant mới → chủ merchant (Owner) thấy ngay quyền quản lý mặc định trên mọi khu vực nghiệp vụ mà không cần ai cấp tay.
- Vai trò hoặc quyền của một người dùng bị đổi, người đó đăng nhập lại hoặc làm mới phiên → thao tác ngay theo quyền mới, không cần chờ hay thao tác gì thêm.
6. Yêu cầu phi chức năng
| Khía cạnh | Yêu cầu |
|---|---|
| Enforcement tập trung | Mọi quyết định phân quyền trong verifier service đi qua một engine tập trung; không còn lọc tuỳ tiện theo từng service làm nguồn sự thật |
| Tenancy & authz | Mỗi grant giải quyết trong một merchant đang hoạt động mỗi request; các dòng policy/membership được cô lập theo merchant |
| Trung thực soft-delete | Policy loader theo phạm vi loại trừ các dòng policy/membership đã soft-delete; việc thu hồi được tôn trọng mà không xoá vật lý |
| Nhất quán | Vô hiệu hoá cache khi refresh token giữ enforcement đồng bộ với policy hiện hành |
| Đồng bộ framework | Việc cấu hình scoped Casbin adapter của framework không cần sửa framework và bám theo scoped RBAC model của nền tảng |
| i18n | Nhãn role/permission hiển thị cho người dùng vẫn song ngữ (Anh & Việt) |
7. UX & Luồng
Các bề mặt chính thuộc backend: enforcement tập trung nằm trong platform core; commerce/finance/core giải quyết scope từ policy; inventory là service thí điểm. Không có màn hình người dùng cuối riêng - increment này là nền tảng phân quyền mà các module khác dựa vào.
8. Dữ liệu & Miền nghiệp vụ
| Khái niệm | Vai trò |
|---|---|
| Policy grant | Một grant: subject, resource, action, scoped tới một merchant |
| Membership | User→role, user→org/merchant, role→org/merchant; cô lập tenant theo loại |
| Scoped Casbin adapter (framework, do core cấu hình) | Nạp các dòng policy/membership tôn trọng soft-delete và theo merchant |
| Merchant đang hoạt động | Merchant mà một request hoạt động trên đó, chọn theo từng request |
| Scoped RBAC model | Định nghĩa cách grant giải quyết trong một merchant |
Chỉ mang tính khái niệm - toàn bộ schema policy và hợp đồng loader nằm trong tài liệu Casbin Authorization cho developer và tài liệu RBAC.
9. Phụ thuộc & Giả định
Phụ thuộc vào
| # | Feature | Phụ thuộc điều gì |
|---|---|---|
| 01 | Role cố định & tùy chỉnh + grant (URD-ROLE · URD-GRANT) | các dòng policy mà engine enforce. |
| 02 | Commerce | organization và merchant là các scope mà grant gắn vào. |
| 03 | Identity | token đăng nhập mang context role; refresh token kích hoạt vô hiệu hoá cache. |
| 04 | Framework nền tảng | scoped RBAC model và scoped Casbin adapter mà platform core cấu hình. |
Giả định
| # | Giả định | Sai thì sao |
|---|---|---|
| 01 | Request mang một merchant đang hoạt động để chọn scope. | Không có merchant đang hoạt động thì engine không biết giải quyết grant trong merchant nào - mọi quyết định phân quyền mất domain để bám vào. |
| 02 | Các dòng policy/membership của một merchant tồn tại dưới cô lập theo merchant. | Nếu cô lập sai, dữ liệu hoặc quyền của một merchant có thể rò rỉ sang merchant khác. |
| 03 | Các role owner được backfill và permission của role inventory được seed cho thí điểm. | Thiếu backfill hoặc seed thì thí điểm inventory không enforce đúng - chủ merchant không có sẵn quyền quản lý mặc định ngay khi merchant được tạo. |
10. Kế hoạch phát hành & Tiêu chí
| Khía cạnh | Kế hoạch |
|---|---|
| Phase | P2 (EFF + GRANT, Built) - xem catalog tính năng URD |
| Rollout | Thí điểm inventory trước; coarse role grant nay đã seed trên mọi verifier service |
| Migration | Seed coarse role permission theo từng module; cấp cho owner membership merchant khi tạo merchant |
| Tiêu chí ra mắt | Enforcement tập trung được xác nhận trong verifier; scope giải quyết từ policy khớp grant; soft-delete và cô lập theo merchant được xác nhận; giải quyết merchant được phép của inventory đúng end-to-end |
| Theo dõi | Độ phủ đường quyết định phân quyền, các nỗ lực truy cập merchant lạ, vô hiệu hoá cache khi refresh token, tỉ lệ lỗi thí điểm |
Tham chiếu
- URD: Quyền hạn - Effective Permissions & Scope · Grant / Revoke · Role cố định
- PRD liên quan: Phân cấp Resource, Action & Domain
- Module: Quyền hạn - URD
- Developer: @nx/core · @nx/identity · Casbin Authorization
Rủi ro & Câu hỏi mở
| # | Rủi ro / câu hỏi | Giảm thiểu / trạng thái |
|---|---|---|
| 01 | Policy loader của framework bỏ qua soft-delete | Platform core cấu hình scoped adapter của framework với hợp đồng entity tôn trọng soft-delete; không sửa framework |
| 02 | Rò rỉ policy liên merchant | Việc tra cứu membership ràng buộc loại; các dòng cô lập theo merchant |
| 03 | Một số đường đọc danh sách (chọn merchant/organizer trước khi vào ngữ cảnh, một vài màn tra cứu) đang tự lọc phạm vi riêng thay vì đi qua engine trung tâm | Mở - hợp nhất các đường này về engine trung tâm là việc còn tồn đọng (FR-001) |
| 04 | Chặn leo thang đặc quyền hiện chỉ áp trên đường cấp qua vai trò; đường cấp quyền trực tiếp cho một người dùng chưa so trần của người cấp | Mở - đường trực tiếp chỉ mở cho tài khoản hệ thống nên rủi ro thực tế thấp, cần bổ sung so trần (FR-005) |
| 05 | Merchant đang hoạt động (active-store context) được tin cậy nguyên trạng | Mở - việc xác minh quyền sở hữu merchant theo từng request hiện đang bị comment trong code; cô lập dựa vào header đúng đắn. Bật lại kiểm tra quyền sở hữu là việc còn tồn đọng |
| 06 | Enforcement cũ sau khi đổi role/permission | Cache policy xoá khi refresh token |
| 07 | RBAC model của framework lệch khỏi kỳ vọng ứng dụng | Bám theo scoped model; migrate khi scoped adapter upstream thay đổi |
| 08 | Domain cascade theo merchant chưa được xây | Coarse role grant đã seed trên mọi module, nhưng kế thừa domain organizer→merchant vẫn còn tồn đọng - xem PRD-HIER-001 |
Câu hỏi thường gặp
| # | Câu hỏi | Trả lời |
|---|---|---|
| 01 | Hiện phân quyền được enforce ở đâu? | Tập trung - mọi verifier service enforce qua cùng một engine thay vì lọc thủ công từ request context. |
| 02 | "Merchant nào" được quyết định ra sao? | Theo từng request, qua merchant đang hoạt động được chọn cho request đó; một grant chỉ giải quyết trong merchant đó. |
| 03 | Vì sao cấu hình scoped adapter của framework thay vì sửa framework? | Core cung cấp hợp đồng entity tôn trọng soft-delete và theo merchant cùng domain resolver cho scoped Casbin adapter của framework, đạt được cả soft-delete lẫn cô lập theo merchant mà không sửa framework. |
| 04 | Thu hồi một grant có hiệu lực ngay không? | Thu hồi sẽ soft-delete dòng policy, vốn bị scoped adapter loại trừ; một lần refresh token xoá cache policy để thay đổi áp dụng gọn gàng. |
| 05 | Vì sao thí điểm trên inventory trước? | Nó đã xác nhận enforcement theo merchant end-to-end trước khi coarse role grant được seed trên mọi module. |
| 06 | Permission wildcard / phân cấp có thuộc phần này không? | Không - grant thô qua phân cấp resource/action/domain thuộc về PRD-HIER-001. |