PRD: Phân cấp Resource, Action & Domain
| Module | Quyền hạn (CORE-02) | PRD ID | PRD-HIER-001 |
| Status | Draft | Owner | Phat Nguyen |
| Date | 2026-06-04 | Version | v0.1 |
| Packages | @nx/core · @nx/identity | URD | HIER · DECL |
TL;DR
Mô hình hoá permission thành cây resource × bậc thang action × cây domain để một grant thô duy nhất -
Sale:managetrên một organizer - thay thế hàng trăm dòng phẳng theo từng method, bao mọi subject, operation và merchant bên dưới. Với chủ sở hữu nền tảng và kỹ sư, điều này biến những role cồng kềnh, dễ vỡ thành vài grant dễ đọc và rút việc khai báo permission cho một controller xuống chỉ một lời gọi helper.
1. Context & Problem
Engine scoped-RBAC (ignis CASBIN_RBAC_DOMAIN_SCOPED_MODEL) cung cấp ba trục kế thừa mà KICKO chưa khai thác: trục action (g5, manage ⊃ read), trục resource (g4 + objectMatch dạng dotted, Order ⊃ Order.refund, Order ⊃ OrderItem), và trục domain (g3, Organizer ⊃ Merchant).
Hiện tại permission đang ở dạng phẳng: ~950 code Subject.method, mỗi cái cấp riêng lẻ. OWNER mang ~950 dòng grant; "HQ thấy tất cả" liên merchant được giả lập bằng cách ghi một membership join_domain cho từng merchant. Không có super-action manage/write và không có cơ chế khai báo thuận tiện - mỗi package tự viết tay createPermission. Hệ quả là role trở nên cồng kềnh, dễ vỡ, tải chậm và khó suy luận. Mô hình hoá permission thành cây × bậc thang × cây-domain cho phép một role gộp lại còn vài grant thô trong khi role chi tiết vẫn chính xác, và biến việc khai báo permission thành một lời gọi helper.
2. Goals & Non-Goals
Mục tiêu
- Gộp grant của role - OWNER trở thành
(Sale, manage)thay vì mọi dòngSaleOrder.*. - Một bậc thang action ba bậc:
manage ⊃ {write, read, execute},write ⊃ {create, update, delete}. - Một phân cấp resource không đổi tên code - subject giữ nguyên code; nhóm theo module cộng với lồng liên-thực-thể qua
g4, và lồng operation tự do quaobjectMatchdạng dotted. - Một phân cấp domain
Merchant ⊂ Organizerquag3- role HQ/quản lý vươn tới mọi merchant của một organizer qua một grant theo scope organizer, loại bỏ việc backfill membership cho từng merchant. - Một bộ công cụ khai báo tối giản boilerplate (
defineResource/crudPermissions/ ma trận role→grant / seeder cạnh cấu trúc idempotent), xây trong nx-seller trước.
Ngoài phạm vi
- Đưa bộ công cụ vào IGNIS - hoãn sang đợt sau (nx-seller trước, chuyển sau).
- Permission glob/regex tuỳ ý (
sales.*) - độ thô đến từ phân cấp, không phải glob. - Thay đổi tập role hay ngữ nghĩa priority - một mối quan tâm riêng.
- Permission theo thời gian/ca và log audit permission.
3. Success Metrics
| Metric | Mục tiêu / tín hiệu |
|---|---|
| Nén grant | Số dòng grant mỗi role giảm từ ~950 xuống vài chục |
| DX khai báo | Thêm controller mới chỉ cần một lời gọi khai báo (không liệt kê CRUD) |
| Idempotency của seed | migrate:dev chạy lại không thay đổi gì; code đã gỡ được reconcile away |
| Tương đương phân quyền | Launchpad + mọi route được bảo vệ giữ nguyên kết quả cho phép/từ chối (đã kiểm thử hồi quy) |
| Tầm với HQ | Role HQ/quản lý vươn tới mọi merchant của organizer mà không cần dòng membership cho từng merchant |
4. Personas & Use Cases
| Persona | Mục tiêu trong tính năng này |
|---|---|
| Chủ sở hữu / admin nền tảng | Gán role thô, dễ đọc (Sale:manage) thay vì sửa hàng trăm dòng grant |
| Owner (HQ) | Vươn tới mọi merchant của organizer qua một grant theo scope organizer |
| Kỹ sư | Khai báo permission + resource node + base action của một controller trong một lời gọi helper |
| Operator | Tin rằng việc seed lại là idempotent và code cũ được reconcile away |
Core scenarios: khai báo resource và operation của một controller trong một lời gọi → seed bậc thang action, roll-up resource và cạnh domain một cách idempotent → gán role dưới dạng ma trận thô nhỏ gọn → một request giải độ phủ qua bậc thang action, cây resource và cây domain mà không cần liệt kê phẳng nào.
5. User Stories
- Là một admin, tôi muốn cấp
(Sale, manage)cho OWNER, để role bao mọi sale subject và operation mà không phải liệt kê từng cái. - Là một HQ owner, tôi muốn một grant theo scope organizer vươn tới mọi merchant của organizer, để không còn phụ thuộc vào dòng membership cho từng merchant.
- Là một kỹ sư, tôi muốn khai báo resource node, operation và base action của một controller trong một lời gọi helper, để thêm route không đồng nghĩa với viết tay permission CRUD.
- Là một operator, tôi muốn việc seed reconcile các code đã gỡ một cách idempotent, để permission và grant cũ không bao giờ tích tụ.
- Là một người thiết kế role, tôi muốn một action rộng hơn (
manage/write) đáp ứng mọi request hẹp hơn, để tôi cấp theo ý định thay vì từng động từ CRUD.
6. Functional Requirements
| # | Yêu cầu | URD ref |
|---|---|---|
| FR-1 | Một grant CÓ THỂ nhắm tới resource ở bất kỳ cấp nào - module, subject hay operation - và bao mọi hậu duệ | URD-HIER-001 |
| FR-2 | Resource operation lồng dưới subject của nó theo code dạng dotted (SaleOrder.refund ⊂ SaleOrder) không cần cấu hình thêm | URD-HIER-002 |
| FR-3 | Một subject CÓ THỂ roll up lên một module để một grant cấp module bao mọi subject trong đó | URD-HIER-003 |
| FR-4 | Một thực thể con CÓ THỂ lồng dưới cha xuyên cách đặt tên (SaleOrderItem ⊂ SaleOrder) qua g4 | URD-HIER-004 |
| FR-5 | Action tạo thành bậc thang - manage ⊃ {write, read, execute}, write ⊃ {create, update, delete} - rộng hơn đáp ứng hẹp hơn | URD-HIER-005 |
| FR-6 | Một route yêu cầu một base action (read/create/update/delete/execute); một grant CÓ THỂ dùng bất kỳ bậc nào kể cả manage/write | URD-HIER-006 |
| FR-7 | Một grant theo scope organizer áp dụng cho mọi merchant bên dưới; một grant theo scope merchant chỉ áp dụng tại đó | URD-HIER-007 |
| FR-8 | Một role HQ / quản lý vươn tới mọi merchant của organizer qua một grant theo scope organizer - không cần dòng membership cho từng merchant | URD-HIER-008 |
| FR-9 | Một grant CÓ THỂ ghim vào SYSTEM_WIDE (mọi nơi) hoặc ANY_MEMBER (mọi merchant đã tham gia) | URD-HIER-009 |
| FR-10 | Permission, bậc thang action và các cạnh phân cấp resource/domain được khai báo trong code và seed một cách idempotent | URD-DECL-001 |
| FR-11 | Khai báo operation + resource node + base action của một controller chỉ tốn một lời gọi helper | URD-DECL-002 |
| FR-12 | Gán role→grant được khai báo dưới dạng ma trận nhỏ gọn (OWNER → Sale:manage), không liệt kê theo từng operation | URD-DECL-003 |
| FR-13 | Việc seed reconcile các code đã gỡ một cách idempotent - không tích tụ permission/grant cũ | URD-DECL-004 |
| FR-14 | Bộ công cụ được xây trong nx-seller trước, với lộ trình rõ ràng để chuyển vào IGNIS sau | URD-DECL-005 |
Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong URD Quyền hạn. PRD này tham chiếu chúng thay vì lặp lại.
7. Non-Functional Requirements
| Khía cạnh | Yêu cầu |
|---|---|
| Tương đương phân quyền | Giải độ phủ qua objectMatch/g4 (resource), g5 (action), g3 (domain) giữ nguyên kết quả cho phép/từ chối so với mô hình phẳng |
| Idempotency của seed | Các cạnh cấu trúc (g3/g4/g5) và permission code seed một cách idempotent; chạy lại là no-op; code đã gỡ được reconcile away |
| Tenancy & authz | Một grant giải trong một domain merchant đang hoạt động cho mỗi request (x-merchant-id); scope organizer mở rộng qua g3, không qua dòng cho từng merchant |
| Hiệu năng / quy mô | Số dòng grant mỗi role gộp từ ~950 xuống vài chục, thu nhỏ tải policy và chi phí enforcement mỗi request |
| Khả năng bảo trì | Một helper khai báo cho mỗi controller; không còn createPermission viết tay theo từng package |
| i18n | Tên/mô tả permission hiển thị cho người dùng vẫn song ngữ ({ en, vi }) |
8. UX & Flows
Đợt này là hạ tầng phân quyền - không có màn hình người dùng cuối. Nó thể hiện qua UI quản trị permission/role hiện có (trang Permission Matrix và các view role-grant), nơi các grant thô giờ hiển thị thành vài dòng thay vì ~950. Xem bản đồ Phân cấp Permission.
9. Data & Domain
| Thực thể | Vai trò |
|---|---|
| Permission (resource code) | Danh mục module + subject + operation tuỳ chỉnh - không phải ~950 dòng method |
Bậc thang action (g5) | Các cạnh kế thừa manage/write/read/execute/create/update/delete |
Cạnh resource (g4 + objectMatch dotted) | Roll-up module⊃subject và lồng liên-thực-thể / operation |
Cạnh domain (g3) | Organizer ⊃ Merchant để grant theo scope organizer vươn tới mọi merchant |
| Grant (policy) | (Role|User, resourceCode, action, domain, effect) |
| Ma trận role→grant | Gán thô theo kiểu khai báo (OWNER → Sale:manage) |
Chỉ ở mức khái niệm - toàn bộ schema và Casbin model nằm trong tài liệu developer RBAC và Casbin Authorization.
10. Dependencies & Assumptions
Phụ thuộc vào
- Engine scoped-RBAC (ignis
CASBIN_RBAC_DOMAIN_SCOPED_MODEL) - cung cấp các trụcg3/g4/g5vàobjectMatch. - Vai trò cố định & tùy chỉnh (URD-ROLE · URD-CROLE) - role là chủ thể của grant.
- Danh mục permission & grant/revoke (URD-PERM · URD-GRANT) - danh mục mà phân cấp này định hình lại.
- Effective permissions & scope (URD-EFF) - việc giải vẫn nằm trong domain merchant đang hoạt động.
@nx/core(Casbin model + adapter + enforcer) và@nx/identity(role, permission, grant).
Giả định
- Code subject ổn định - phân cấp mang tính bổ sung (không đổi tên code).
- Quan hệ organizer→merchant sẵn có để seed các cạnh
g3. - Một bộ kiểm thử hồi quy bao launchpad và mọi route được bảo vệ cho tương đương cho phép/từ chối.
11. Risks & Open Questions
| Rủi ro / câu hỏi | Giảm thiểu / trạng thái |
|---|---|
| Việc giải độ phủ lệch khỏi mô hình phẳng | Kiểm thử hồi quy launchpad + mọi route được bảo vệ cho kết quả cho phép/từ chối giống hệt |
Danh sách seed nhóm-module g4 chính xác (subject nào roll up vào module nào) | Mở - sẽ liệt kê trong plan |
execute cho operation tuỳ chỉnh cấp theo từng operation hay chỉ gộp vào manage | Mở - quyết định trước khi seed bậc thang action |
| Di chuyển membership owner theo từng merchant hiện có → grant theo scope organizer | Mở - định nghĩa hình dạng data migration |
| Seed lại có thể làm rớt code đang dùng | Việc reconcile là idempotent và do code điều khiển; chạy lại là no-op |
12. Release Plan & Launch Criteria
| Khía cạnh | Kế hoạch |
|---|---|
| Phase | P3 - xem danh mục feature URD (HIER + DECL) |
| Rollout | Theo giai đoạn: (1) toolkit + bậc thang action (g5) + gộp grant OWNER/EMPLOYEE/CASHIER về dòng thô trong nx-seller; (2) cây domain (g3) + loại bỏ backfill membership theo merchant + grant quản lý theo scope organizer; (3) chuyển toolkit sang IGNIS (PRD riêng) |
| Migration | Data migration: membership owner theo từng merchant hiện có → grant theo scope organizer; seed cạnh cấu trúc chạy qua migrate:dev |
| Launch criteria | Số dòng grant mỗi role gộp xuống vài chục; migrate:dev idempotent; launchpad + mọi route được bảo vệ giữ nguyên kết quả cho phép/từ chối |
| Monitoring | Số dòng grant mỗi role, kiểm tra idempotency của seed, bộ kiểm thử hồi quy cho phép/từ chối phân quyền |
13. FAQ
Việc này có cần đổi tên code subject không? Không. Phân cấp mang tính bổ sung - subject giữ nguyên code; việc nhóm và lồng diễn ra qua các cạnh g4 và objectMatch dạng dotted.
Sale:manage khác glob như sales.* ở chỗ nào? Độ thô đến từ cây resource cộng với action manage, không phải regex glob. Không có permission wildcard.
Giờ một HQ owner vươn tới mọi merchant bằng cách nào? Qua một grant theo scope organizer được giải qua g3 - việc backfill membership join_domain cho từng merchant được loại bỏ.
Một action rộng hơn có bao các action hẹp hơn không? Có. manage ⊃ {write, read, execute} và write ⊃ {create, update, delete}, nên một grant manage đáp ứng mọi request hẹp hơn.
Bộ công cụ có vào IGNIS không? Không trong đợt này - nó được xây trong nx-seller trước, với lộ trình rõ ràng để chuyển vào IGNIS ở một PRD sau.
Điều gì xảy ra với một permission code bị gỡ khỏi khai báo? Việc seed reconcile nó away một cách idempotent, cùng với các grant của nó - không tích tụ dòng cũ.
References
- URD: Quyền hạn - Phân cấp Resource, Action & Domain · Permission Declaration
- Dựa trên: Vai trò cố định · Vai trò tùy chỉnh · Danh mục Permission · Grant / Revoke · Effective Permissions & Scope
- Bản đồ: Phân cấp Permission · Permission Matrix
- Module: Quyền hạn - tổng quan + truy vết
- Developer: @nx/identity · RBAC · Casbin Authorization