URD: Phân quyền
| Module | CORE-02 | Phiên bản | v0.6 |
|---|---|---|---|
| Trạng thái | Đã xây dựng · phân cấp Đang thực hiện | Ngày | 2026-06-04 |
Tài liệu nghiệp vụ. URD này là danh sách tính năng của Phân quyền - mỗi tính năng bên dưới là một Vùng Chức năng (
<AREA>). Cùng khóa<AREA>đó được dùng cho PRD của tính năng (PRD-<AREA>-NNN) và test (TC-<AREA>-NNN), và mỗi tính năng được liệt kê trong danh mục tính năng Delivery. Xem quy ước Feature Spine.
1. Mục đích
Định nghĩa cách kiểm soát truy cập vào tính năng và dữ liệu. Phân quyền cho phép quản trị viên gán vai trò cho người dùng, cấp quyền cho các vai trò đó, giới hạn vai trò trong phạm vi một tổ chức hoặc merchant cụ thể, và để mọi truy vấn được lọc tự động theo phạm vi mà người dùng yêu cầu được phép xem - được thực thi thông qua mô hình RBAC dựa trên độ ưu tiên của Casbin với phạm vi (domain) theo từng merchant.
2. Phạm vi
| Bao gồm | Loại trừ |
|---|---|
| Tám vai trò hệ thống cố định + phân cấp theo độ ưu tiên | Quyền dạng wildcard |
| Bỏ qua kiểm tra cho vai trò hệ thống (Super Admin / Admin / Operator) | Phân nhóm quyền / nhóm hiển thị trên UI |
| Lọc dữ liệu tự động theo vai trò | Quyền theo thời gian hoặc theo ca |
| Tạo vai trò tùy chỉnh với độ ưu tiên và phạm vi | Ghi log kiểm toán quyền |
| Danh mục quyền (tạo / cập nhật / xóa) | Mẫu / gói vai trò |
| Cấp / thu hồi quyền cho vai trò | Chuyển đổi vai trò đang hoạt động theo từng merchant |
| Cấp / thu hồi vai trò cho người dùng | Đặc tả kỹ thuật API (xem tài liệu lập trình viên) |
| Truy vấn quyền hiệu lực (trực tiếp + kế thừa) | |
| Giới hạn phạm vi theo từng tổ chức & từng merchant | |
| Bảo vệ chống leo thang đặc quyền |
3. Định nghĩa
| Thuật ngữ | Định nghĩa |
|---|---|
| Vai trò (Role) | Một mức truy cập có tên kèm độ ưu tiên dạng số. SYSTEM (cố định) hoặc CUSTOM (do người dùng tạo). |
| Quyền (Permission) | Một hành động có tên trên một tài nguyên, được định danh bằng một mã duy nhất toàn cục. |
| Cấp quyền (policy) | Một bản ghi cấp một quyền cho một vai trò hoặc trực tiếp cho một người dùng. |
| Thành viên (group) | Một bản ghi liên kết người dùng với vai trò, người dùng với org/merchant, hoặc vai trò với org/merchant. |
| Quyền hiệu lực | Tập hợp toàn bộ quyền mà một người dùng nắm giữ: cấp trực tiếp + quyền kế thừa qua vai trò. |
| Vai trò có phạm vi | Một vai trò tùy chỉnh được gắn vào một tổ chức hoặc merchant cụ thể, giới hạn nơi nó áp dụng. |
| Domain | Merchant mà một bản ghi cấp quyền áp dụng bên trong, được chọn theo từng request qua header merchant đang hoạt động. |
| Bỏ qua kiểm tra cho vai trò hệ thống | Super Admin, Admin, và Operator bỏ qua mọi việc lọc dữ liệu và nắm giữ mọi quyền. |
| Mở rộng HQ-owner | Một Owner tại merchant trụ sở tự động vươn tới mọi merchant cùng tổ chức của organizer đó. |
| Leo thang đặc quyền | Quản lý một vai trò ngang hoặc cao hơn độ ưu tiên của chính người thực hiện - luôn bị chặn. |
4. Mô hình khái niệm
Chỉ mang tính khái niệm - mô hình dữ liệu chính sách đầy đủ nằm trong tài liệu RBAC cho lập trình viên.
5. Danh mục tính năng
Danh sách tính năng của module này. Mỗi dòng là một tính năng (một Vùng Chức năng). Chi tiết ở §6. Được phản chiếu trong danh mục tính năng Delivery.
| Feature ID | Tính năng | Phase | Trạng thái | Ưu tiên |
|---|---|---|---|---|
ROLE | Vai trò cố định | P1 | Built | High |
CROLE | Vai trò tùy chỉnh | P2 | Built | High |
PERM | Danh mục quyền | P2 | Built | High |
GRANT | Cấp / Thu hồi | P2 | Built | High |
EFF | Quyền hiệu lực & Phạm vi | P2 | Built | High |
HIER | Phân cấp Tài nguyên, Hành động & Domain | P3 | In-progress | High |
DECL | Khai báo quyền | P3 | In-progress | High |
Trạng thái: live từ Plane nếu có map, còn lại do registry khai báo. Vocabulary đồng nhất với Plane (state-group / phase).
6. Các tính năng
Một mục con cho mỗi tính năng, theo thứ tự danh mục. Mỗi tính năng giữ phần mô tả, yêu cầu và tiêu chí chấp nhận cùng nhau. Độ ưu tiên = MoSCoW (Must / Should / Could / Won't).
ROLE - Vai trò cố định Built
Feature ID: permissions/ROLE · Phase: P1 · PRDs: - · Dev: @nx/identity
Lợi ích cho người dùng: tám vai trò hệ thống được seed sẵn với thứ tự độ ưu tiên cố định; ba vai trò cao nhất thấy toàn bộ dữ liệu, trong khi Owner, Cashier, và Employee tự động bị giới hạn trong tổ chức hoặc các merchant mà họ thuộc về.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-ROLE-001 | M | Cung cấp tám vai trò cố định được seed lúc khởi động: Super Admin, Admin, Operator, Owner, Cashier, Employee, Customer, Guest |
| URD-ROLE-002 | M | Vai trò cố định (SYSTEM) không thể chỉnh sửa hoặc xóa |
| URD-ROLE-003 | M | Mỗi vai trò có một độ ưu tiên dạng số xác định vị trí của nó trong phân cấp |
| URD-ROLE-004 | M | Super Admin, Admin, và Operator bỏ qua mọi việc lọc dữ liệu và nắm giữ mọi quyền |
| URD-ROLE-005 | M | Owner chỉ thấy tổ chức của chính mình và các merchant của nó |
| URD-ROLE-006 | M | Employee (và Cashier) chỉ thấy các merchant mà họ được gán vào |
| URD-ROLE-007 | M | Mọi thao tác liệt kê và đếm đều được lọc theo phạm vi của người dùng yêu cầu |
| URD-ROLE-008 | M | Việc lọc tự động không thể bị ghi đè bằng bộ lọc do người dùng cung cấp hoặc truy cập trực tiếp theo ID |
| URD-ROLE-009 | S | Một Owner tại merchant trụ sở vươn tới mọi merchant cùng tổ chức của organizer đó |
Tiêu chí chấp nhận
AC-ROLE-01: Lọc dữ liệu theo vai trò
| Given | When | Then |
|---|---|---|
| Người dùng có các vai trò khác nhau | Họ gọi cùng một endpoint | Super Admin/Admin/Operator thấy tất cả; Owner thấy org của mình; Employee/Cashier thấy các merchant được gán |
| Bất kỳ truy vấn liệt kê/đếm nào | Được chạy bởi một người dùng có phạm vi | Việc lọc là tự động và không thể bị ghi đè |
| Một người dùng có phạm vi cung cấp bộ lọc rộng hơn hoặc một ID ngoài phạm vi | Khi gửi request | Bộ lọc bị bỏ qua / truy cập bị từ chối |
AC-ROLE-02: Bảo vệ vai trò cố định
| Given | When | Then |
|---|---|---|
| Bất kỳ vai trò nào trong tám vai trò hệ thống | Người dùng cố chỉnh sửa hoặc xóa nó | Thao tác bị từ chối |
| Độ ưu tiên của một vai trò cố định | Người dùng cố thay đổi nó | Bị từ chối - độ ưu tiên là bất biến |
CROLE - Vai trò tùy chỉnh Built
Feature ID: permissions/CROLE · Phase: P2 · PRDs: - · Dev: @nx/identity
Lợi ích cho người dùng: quản trị viên và owner tạo các vai trò riêng với tên tùy chỉnh, độ ưu tiên, và phạm vi tổ chức/merchant tùy chọn - luôn thấp hơn độ ưu tiên của chính họ - và xóa chúng một cách an toàn khi không còn người dùng nào được gán.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-CROLE-001 | M | Người dùng được ủy quyền có thể tạo vai trò tùy chỉnh với tên i18n, độ ưu tiên, và phạm vi tùy chọn |
| URD-CROLE-002 | M | Định danh vai trò được tự động tạo từ độ ưu tiên + tên và là duy nhất trong phạm vi của nó |
| URD-CROLE-003 | M | Độ ưu tiên của vai trò mới phải thấp hơn nghiêm ngặt so với độ ưu tiên cao nhất của người tạo |
| URD-CROLE-004 | M | Vai trò tùy chỉnh có thể được giới hạn phạm vi vào một tổ chức hoặc merchant cụ thể |
| URD-CROLE-005 | M | Vai trò tùy chỉnh có thể được cập nhật (tên, mô tả, độ ưu tiên) |
| URD-CROLE-006 | M | Không thể xóa một vai trò khi vẫn còn người dùng được gán vào nó |
| URD-CROLE-007 | M | Xóa một vai trò sẽ xóa lan (cascade) các bản ghi cấp quyền và liên kết phạm vi của nó |
| URD-CROLE-008 | S | Một Owner chỉ có thể tạo các vai trò giới hạn phạm vi trong tổ chức hoặc các merchant của chính mình |
Tiêu chí chấp nhận
AC-CROLE-01: Tạo vai trò tùy chỉnh
| Given | When | Then |
|---|---|---|
| Admin hoặc Owner | Tạo một vai trò với độ ưu tiên + tên | Vai trò được tạo với type CUSTOM, định danh được tự động tạo |
| Độ ưu tiên ≥ của chính người tạo | Khi cố tạo | Bị từ chối (leo thang đặc quyền) |
| Có cung cấp phạm vi org/merchant | Khi tạo vai trò | Liên kết phạm vi được tạo |
| Cùng độ ưu tiên + tên trong cùng phạm vi | Khi cố tạo | Bị từ chối (trùng định danh) |
AC-CROLE-02: Xóa vai trò
| Given | When | Then |
|---|---|---|
| Vai trò tùy chỉnh không có người dùng | Admin xóa | Vai trò + bản ghi cấp quyền + liên kết phạm vi được soft-delete |
| Vai trò tùy chỉnh có người dùng được gán | Admin xóa | Bị chặn - phải gỡ gán người dùng trước |
| Vai trò hệ thống | Admin xóa | Bị từ chối - vai trò cố định là bất biến |
PERM - Danh mục quyền Built
Feature ID: permissions/PERM · Phase: P2 · PRDs: - · Dev: @nx/identity
Lợi ích cho người dùng: quản trị viên duy trì danh mục quyền - mỗi quyền là một hành động trên một tài nguyên được mã hóa duy nhất kèm tên và mô tả i18n - và không thể gỡ bỏ một quyền đang còn được sử dụng.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-PERM-001 | M | Admin có thể tạo quyền với mã, hành động, phạm vi, và đối tượng (subject) duy nhất |
| URD-PERM-002 | M | Mã quyền phải duy nhất toàn cục |
| URD-PERM-003 | M | Tên và mô tả quyền hỗ trợ i18n |
| URD-PERM-004 | M | Admin có thể cập nhật và xóa quyền |
| URD-PERM-005 | M | Một quyền có bản ghi cấp đang hoạt động thì không thể bị xóa |
Tiêu chí chấp nhận
AC-PERM-01: Tính toàn vẹn của danh mục quyền
| Given | When | Then |
|---|---|---|
| Admin định nghĩa một quyền | Cung cấp mã, hành động, phạm vi, và đối tượng duy nhất | Quyền được tạo |
| Một mã trùng lặp | Khi cố tạo | Bị từ chối - mã là duy nhất toàn cục |
| Một quyền có bản ghi cấp đang hoạt động | Admin xóa | Bị chặn - phải thu hồi các bản ghi cấp trước |
GRANT - Cấp / Thu hồi Built
Feature ID: permissions/GRANT · Phase: P2 · PRDs: - · Dev: @nx/identity
Lợi ích cho người dùng: quản trị viên gắn hoặc gỡ quyền trên một vai trò và gán hoặc gỡ gán vai trò cho người dùng; mọi thao tác đều bất biến (idempotent) và bị chặn khi nó chạm tới một vai trò ngang hoặc cao hơn độ ưu tiên của chính người thực hiện.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-GRANT-001 | M | Admin có thể cấp một hoặc nhiều quyền cho một vai trò |
| URD-GRANT-002 | M | Admin có thể thu hồi một hoặc nhiều quyền từ một vai trò |
| URD-GRANT-003 | M | Cấp một quyền đã được cấp là bất biến (bỏ qua, không trùng lặp) |
| URD-GRANT-004 | M | Admin có thể cấp và thu hồi vai trò cho/từ người dùng |
| URD-GRANT-005 | M | Bộ bảo vệ chống leo thang đặc quyền được thực thi trên mọi thao tác cấp/thu hồi |
| URD-GRANT-006 | M | Admin có thể xem mọi quyền đã cấp cho một vai trò |
| URD-GRANT-007 | M | Admin có thể xem mọi người dùng được gán vào một vai trò và mọi vai trò được gán cho một người dùng |
Tiêu chí chấp nhận
AC-GRANT-01: Cấp quyền
| Given | When | Then |
|---|---|---|
| ID vai trò + quyền | Admin cấp | Các bản ghi cấp được tạo, trả về số lượng |
| Quyền đã được cấp | Admin cấp lại | Bỏ qua (idempotent), trả về số lượng bỏ qua |
| Độ ưu tiên người thực hiện ≤ độ ưu tiên vai trò | Admin cấp | Bị từ chối (leo thang đặc quyền) |
EFF - Quyền hiệu lực & Phạm vi Built
Feature ID: permissions/EFF · Phase: P2 · PRDs: - · Dev: @nx/identity
Lợi ích cho người dùng: bất kỳ ai cũng có thể hỏi một người dùng thực sự được phép làm gì - hợp đã loại trùng của các bản ghi cấp trực tiếp và các bản ghi cấp kế thừa qua vai trò - và họ thuộc về những tổ chức và merchant nào, được phân giải trong domain merchant đang hoạt động.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-EFF-001 | M | Tính quyền hiệu lực là hợp của các bản ghi cấp trực tiếp + kế thừa qua vai trò (đã loại trùng) |
| URD-EFF-002 | S | Truy vấn hỗ trợ bộ lọc chế độ: direct, inherit, hoặc cả hai |
| URD-EFF-003 | M | Truy xuất mọi tổ chức và mọi merchant mà một người dùng thuộc về |
| URD-EFF-004 | M | Một bản ghi cấp chỉ được phân giải trong domain merchant đang hoạt động được chọn theo từng request |
Tiêu chí chấp nhận
AC-EFF-01: Quyền hiệu lực
| Given | When | Then |
|---|---|---|
| Người dùng có vai trò + cấp trực tiếp | Truy vấn hiệu lực | Hợp của trực tiếp + kế thừa, đã loại trùng |
| Chế độ = direct | Truy vấn | Chỉ trả về các bản ghi cấp trực tiếp |
| Chế độ = inherit | Truy vấn | Chỉ trả về các bản ghi cấp kế thừa qua vai trò |
HIER - Phân cấp Tài nguyên, Hành động & Domain In-progress
Feature ID: permissions/HIER · Phase: P3 · PRDs: PRD-HIER-001 · Map: Permission Hierarchy · Dev: @nx/identity
Lợi ích cho người dùng: các quyền tạo thành một cây tài nguyên × bậc thang hành động × cây domain, nên một bản ghi cấp thô (ví dụ Sale:manage) thay thế nhiều bản ghi cấp phẳng - bao phủ mọi đối tượng, thao tác, và merchant bên dưới nó.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-HIER-001 | M | Một bản ghi cấp CÓ THỂ nhắm vào một tài nguyên ở bất kỳ cấp nào - module, đối tượng, hoặc thao tác - và tự động bao phủ mọi hậu duệ |
| URD-HIER-002 | M | Tài nguyên thao tác lồng dưới đối tượng của nó theo mã có dấu chấm (SaleOrder.refund ⊂ SaleOrder) mà không cần cấu hình thêm |
| URD-HIER-003 | M | Một đối tượng CÓ THỂ gom lên một module để một bản ghi cấp cấp module bao phủ mọi đối tượng trong nó (cấp trên Sale ⇒ SaleOrder, SaleOrderItem, …) |
| URD-HIER-004 | S | Một thực thể con CÓ THỂ lồng dưới một thực thể cha bất kể cách đặt tên (SaleOrderItem ⊂ SaleOrder) để bản ghi cấp của cha bao phủ con |
| URD-HIER-005 | M | Hành động tạo thành một bậc thang - manage ⊃ {write, read, execute}, write ⊃ {create, update, delete} - một hành động được cấp rộng hơn thỏa mãn mọi yêu cầu hẹp hơn |
| URD-HIER-006 | M | Một route yêu cầu một hành động cơ bản (read/create/update/delete/execute); một bản ghi cấp CÓ THỂ dùng bất kỳ tầng nào kể cả manage/write |
| URD-HIER-007 | M | Một bản ghi cấp giới hạn phạm vi vào một Organizer áp dụng cho mọi merchant dưới nó; một bản ghi cấp giới hạn vào một Merchant chỉ áp dụng tại đó |
| URD-HIER-008 | M | Một vai trò trụ sở / quản lý vươn tới mọi merchant của organizer của nó thông qua một bản ghi cấp giới hạn phạm vi organizer - mà không cần một hàng thành viên theo từng merchant |
| URD-HIER-009 | S | Một bản ghi cấp CÓ THỂ ghim vào SYSTEM_WIDE (mọi nơi) hoặc ANY_MEMBER (mọi merchant đã tham gia) |
Tiêu chí chấp nhận
AC-HIER-01: Bản ghi cấp thô bao phủ hậu duệ (ví dụ manage)
| Given | When | Then |
|---|---|---|
Một vai trò được cấp (SaleOrder, manage) | Một request read SaleOrder.refund | Được phép - manage ⊃ read (bậc thang) và SaleOrder.refund ⊂ SaleOrder (dấu chấm) |
Một vai trò được cấp (Sale, manage) (module) | Bất kỳ thao tác nào trên SaleOrderItem | Được phép - SaleOrderItem ⊂ Sale (gom lên module) |
Một vai trò chỉ được cấp (SaleOrder, read) | Một request create SaleOrder | Bị từ chối - read không bao phủ create |
AC-HIER-02: Phạm vi domain (organizer vs merchant / HQ)
| Given | When | Then |
|---|---|---|
Một vai trò được cấp trên Organizer_9 | Một request trong bất kỳ Merchant nào dưới organizer 9 | Được phép qua g3 - không cần thành viên theo từng merchant |
Một vai trò chỉ được cấp trên Merchant_7 | Một request trong Merchant_8 | Bị từ chối - phạm vi là một merchant đơn lẻ |
| Một người dùng HQ/quản lý (bản ghi cấp giới hạn phạm vi organizer) | Hành động trên bất kỳ merchant cùng tổ chức nào | Được phép - vươn tới mọi merchant của organizer |
DECL - Khai báo quyền In-progress
Feature ID: permissions/DECL · Phase: P3 · PRDs: PRD-HIER-001 · Dev: @nx/identity
Lợi ích cho người dùng: các quyền, bậc thang hành động, và phân cấp tài nguyên/domain được khai báo trong code với boilerplate tối thiểu và được seed một cách bất biến, nên một controller mới chỉ cần một lệnh gọi helper và các mã đã gỡ bỏ được đối soát loại đi tự động.
Yêu cầu
| ID | P | Yêu cầu |
|---|---|---|
| URD-DECL-001 | M | Các quyền, bậc thang hành động, và các cạnh phân cấp tài nguyên/domain được khai báo trong code và seed một cách bất biến |
| URD-DECL-002 | M | Khai báo các thao tác + node tài nguyên + hành động cơ bản của một controller chỉ cần boilerplate tối thiểu (một lệnh gọi helper) |
| URD-DECL-003 | M | Gán vai trò→quyền được khai báo dưới dạng một ma trận nhỏ (ví dụ OWNER → Sale:manage), không phải liệt kê theo từng thao tác |
| URD-DECL-004 | M | Việc seed đối soát các mã đã gỡ bỏ một cách bất biến - không tích tụ quyền/bản ghi cấp cũ |
| URD-DECL-005 | C | Bộ công cụ được xây dựng trong nx-seller trước, với lộ trình rõ ràng để chuyển vào IGNIS sau này |
Tiêu chí chấp nhận
AC-DECL-01: Khai báo với boilerplate tối thiểu
| Given | When | Then |
|---|---|---|
| Một controller mới | Tác giả khai báo tài nguyên + các thao tác của nó trong một lệnh gọi helper | Các quyền + đặc tả authorize của route được tạo ra mà không cần liệt kê CRUD |
| Dàn hành động + các cạnh phân cấp | Migration chạy | Các cạnh g5/g4/g3 được seed bất biến; chạy lại không thay đổi gì |
| Một mã quyền bị gỡ khỏi khai báo | Migration chạy | Quyền cũ + các bản ghi cấp của nó được đối soát loại đi |
7. Ràng buộc & Phi mục tiêu
Ràng buộc
| ID | Ràng buộc |
|---|---|
| C-01 | Tám vai trò cố định được seed lúc khởi động và là bất biến |
| C-02 | Không ai có thể tạo hoặc quản lý một vai trò ngang hoặc cao hơn độ ưu tiên của chính mình |
| C-03 | Mã quyền là duy nhất toàn cục |
| C-04 | Các thao tác cấp quyền là bất biến (idempotent) |
| C-05 | Mọi bản ghi đều được soft-delete, không bao giờ bị xóa vật lý |
| C-06 | Session token là stateless - thay đổi vai trò/quyền có hiệu lực ở lần đăng nhập kế tiếp |
| C-07 | Mọi thao tác đều yêu cầu xác thực |
| C-08 | Một bản ghi cấp được phân giải trong một domain merchant đang hoạt động cho mỗi request |
Phi mục tiêu
- Quyền glob/regex tùy ý (ví dụ
sales.*) - truy cập thô đến từ cây tài nguyên + hành độngmanage(HIER), không phải glob - Quyền theo thời gian hoặc theo ca
- Log kiểm toán quyền
- Chuyển đổi vai trò đang hoạt động theo từng merchant
Được thay thế bởi
HIER: các phi mục tiêu trước đây "quyền dạng wildcard", "phân nhóm quyền / nhóm hiển thị trên UI" (nay là gom lên module), và "mẫu / gói vai trò" (nay là một ma trận vai trò→quyền thô) được thay thế bằng phân cấp tài nguyên/hành động/domain.
8. Lịch sử phiên bản
| Ngày | Tác giả | Mô tả | Ver |
|---|---|---|---|
| 2026-02-26 | P. Do - Product Owner | User story ban đầu | v0.1 |
| 2026-04-16 | Product | Cấu trúc lại theo định dạng URD | v0.3 |
| 2026-05-29 | Product | Chuyển sang quy ước module-docs; đối soát với RBAC Casbin theo từng merchant (8 vai trò, độ ưu tiên, domain); đặt lại khóa các vùng (ROLE/CROLE/PERM/GRANT/EFF) | v0.4 |
| 2026-06-04 | Product | Bổ sung vùng Phân cấp Tài nguyên/Hành động/Domain (HIER) + Khai báo quyền (DECL) cho increment resource-action-hierarchy (PRD-HIER-001); thay thế các phi mục tiêu wildcard/categories/bundles | v0.5 |
| 2026-06-04 | Claude (AI pair) | Tổ chức lại theo tính năng (Feature Spine); mỗi tính năng mang yêu cầu + tiêu chí chấp nhận của riêng nó | v0.6 |