Super Admin System Device Inventory Design

Date: 2026-05-02
Status: Approved (conversation-level), pending file review gate

1) Goal

Thiết kế một module system device inventory riêng cho Super Admin để quản lý tài sản IoT ở cấp toàn hệ thống.

Module này phải cho phép Super Admin:

  • tạo device ở cấp hệ thống
  • xem danh sách device toàn hệ thống
  • xem chi tiết device
  • chỉnh sửa device
  • xóa device theo rule an toàn
  • assign device vào organization
  • unassign device khỏi organization
  • đổi trạng thái inventory như in_inventory, assigned, maintenance, retired

Spec này không bao gồm luồng Admin mua/claim device. Đó là một bài toán khác và phải được đặc tả riêng.

2) Current State

  • UI hiện tại chỉ có một màn frontend/src/pages/devices/DeviceList.tsx dùng chung cho device management.
  • Backend device hiện đang bị mô hình hóa như tenant resource:
    • organizationId được gán lên device
    • DevicesService.create() yêu cầu currentUser.organizationId phải có
    • device trong resource-scope-map chưa hỗ trợ system scope
  • Điều này mâu thuẫn với định hướng product docs hiện có, nơi device được mô tả là tài sản do Super Admin tạo và quản lý ở cấp hệ thống trước khi assign cho organization.
  • Vì vậy hiện trạng code chưa phản ánh đúng mô hình inventory hệ thống.

3) Options Considered

Option A: Reuse /devices for all scopes

Giữ một route /devices cho cả Super Admin và organization users, rồi thay đổi behavior theo role.

Pros

  • Ít route mới
  • Có thể tận dụng UI hiện tại

Cons

  • Dễ trộn lẫn system scope và tenant scope
  • Backend và frontend phải chứa nhiều branch theo role
  • Khó giữ ranh giới rõ giữa inventory toàn hệ thống và device usage trong organization

Option B: Separate UI route, reuse current backend tenant contract

Tạo /system/devices cho Super Admin nhưng cố dùng lại phần lớn backend tenant-scoped hiện tại.

Pros

  • Tách UX khỏi /devices
  • Ít churn hơn full redesign

Cons

  • Backend contract vẫn lệch với nghiệp vụ
  • organizationId = null và inventory lifecycle vẫn là ngoại lệ gắn thêm, không phải mô hình gốc

Option C (selected): Dedicated system inventory slice

Tạo một vertical slice riêng cho system device inventory của Super Admin: route riêng, permission riêng, query riêng, inventory lifecycle riêng, đồng thời tiếp tục dùng chung Device entity làm nguồn dữ liệu gốc và mở rộng entity này cho inventory scope.

Pros

  • Tách ranh giới system scope và tenant scope rõ ràng
  • Phù hợp với lifecycle thật của device
  • Mở đường sạch cho spec khác về Admin claim/mua device

Cons

  • Cần thay đổi backend scope model
  • Cần route và UI mới cho Super Admin

4) Selected Design

Chọn Option C: xây một module system device inventory riêng cho Super Admin, tách khỏi device management ở cấp organization.

4.1 Route and ownership model

  • Tạo route riêng: /system/devices
  • Route này chỉ dành cho Super Admin
  • /devices về lâu dài dành cho organization-level device management
  • Hai route này không dùng cùng UX contract

Ý nghĩa nghiệp vụ:

  • /system/devices: quản lý tài sản IoT toàn nền tảng
  • /devices: quản lý device đã thuộc về một organization và đang đi vào vận hành

4.2 Device ownership lifecycle

Spec này định nghĩa device lifecycle ở cấp inventory như sau:

Created -> In Inventory -> Assigned -> Maintenance -> Retired

Giải thích:

  • Created
    • trạng thái logic ngay khi Super Admin tạo bản ghi
  • In Inventory
    • device thuộc hệ thống, chưa gán cho organization nào
  • Assigned
    • device đã được gán cho một organization
  • Maintenance
    • device bị giữ lại để xử lý kỹ thuật, không sẵn sàng để assign mới
  • Retired
    • device ngừng sử dụng và không thể assign lại

4.3 Data model changes

Spec này yêu cầu tách rõ hai lớp trạng thái:

  • inventoryStatus
    • phản ánh trạng thái lifecycle inventory
  • operationalStatus
    • phản ánh tình trạng vận hành kỹ thuật như online, offline, error

inventoryStatus đề xuất enum:

  • in_inventory
  • assigned
  • maintenance
  • retired

Model ownership:

  • organizationId: string | null
  • organizationId = null
    • device đang ở system inventory
  • organizationId != null
    • device đã được assign cho organization

Metadata nên có:

  • assignedAt: Date | null
  • retiredAt: Date | null

Spec này không bắt buộc bổ sung audit/history detail trong cùng scope.

4.4 Permission model

Spec này yêu cầu device hỗ trợ system scope cho các action inventory của Super Admin.

Super Admin:

  • device:create:system
  • device:read:system
  • device:update:system
  • device:delete:system
  • device:assign:system

Admin:

  • không truy cập /system/devices
  • không được tạo device từ module inventory hệ thống
  • chỉ quản lý device đã thuộc organization của họ ở module khác

Owner / Staff / Technical:

  • ngoài scope của spec này

Hệ quả implementation:

  • resource-scope-map của device phải hỗ trợ system scope
  • các API system inventory không được buộc organizationId tồn tại khi actor là Super Admin
  • logic filter theo organization chỉ áp dụng cho organization-level flows, không áp dụng cho /system/devices

4.5 System inventory page

Màn /system/devices là một inventory page riêng cho Super Admin, không phải bản sao của trang /devices hiện tại.

Danh sách nên hỗ trợ:

  • search theo tên hoặc serial
  • filter theo loại thiết bị
  • filter theo inventoryStatus
  • filter theo operationalStatus
  • filter theo organization đã assign hoặc chưa assign

Action chính trên page:

  • Thêm thiết bị
  • Chỉnh sửa
  • Xóa
  • Assign organization
  • Unassign
  • Chuyển maintenance
  • Retire

4.6 Create flow in system inventory

Luồng tạo device của Super Admin trong /system/devices dùng quick-create flow:

  • Loại thiết bị đứng đầu form
  • hệ thống generate Tên thiết bịMã serial
  • Mô hình là optional

Sau khi tạo xong:

  • organizationId = null
  • inventoryStatus = in_inventory

Spec này giữ nguyên triết lý generate identity đã chốt ở spec quick-create trước đó, nhưng đổi scope tạo device từ tenant-level sang system-level.

4.7 Assign and unassign behavior

Assign organization:

  • chỉ khả dụng khi device chưa retired
  • không cho assign mới nếu device đang maintenance
  • khi assign thành công:
    • organizationId được set
    • inventoryStatus = assigned
    • assignedAt được cập nhật

Unassign:

  • đưa device trở về inventory hệ thống
  • khi unassign thành công:
    • organizationId = null
    • inventoryStatus = in_inventory

Spec này coi assign/unassign là action chủ động của Super Admin, không phải self-service của Admin.

4.8 Maintenance and retire behavior

Maintenance:

  • dùng để giữ thiết bị lại ở inventory kỹ thuật
  • device trong maintenance không sẵn sàng cho assign mới

Retire:

  • đánh dấu ngừng sử dụng
  • device retired không thể assign lại
  • không nên biến thành xóa cứng mặc định

4.9 Delete behavior

Spec này không khuyến nghị hard-delete tự do cho device đã từng đi vào vận hành.

Rule đề xuất:

  • chỉ cho delete khi device chưa có telemetry thực tế và chưa đi qua lifecycle vận hành quan trọng
  • nếu device đã từng được dùng thật, ưu tiên retired hơn delete

Delete trong spec này được chốt là:

  • hard-delete chỉ cho phép khi device chưa từng được assign và chưa có telemetry
  • nếu device đã từng được assign hoặc đã có telemetry thì delete bị từ chối và phải dùng retired

5) File-Level Scope

Expected scope ở mức thiết kế:

  • Backend:
    • route/controller riêng hoặc contract riêng cho /system/devices
    • service/query logic riêng cho system inventory
    • mở rộng permission/scope model cho device:...:system
    • bổ sung trường inventoryStatus và metadata inventory cần thiết
  • Frontend:
    • page mới cho /system/devices
    • form create/edit dành cho system inventory
    • list filters và action menu riêng cho Super Admin
  • Navigation/RBAC:
    • menu riêng cho Super Admin
    • guard chỉ cho phép Super Admin truy cập

6) Acceptance Criteria

  1. Super Admin có route riêng /system/devices.
  2. Chỉ Super Admin truy cập được route này.
  3. Super Admin xem được toàn bộ device toàn hệ thống, kể cả device chưa thuộc organization nào.
  4. Super Admin tạo device mới ở cấp hệ thống mà không cần organizationId.
  5. Device mới tạo mặc định có organizationId = nullinventoryStatus = in_inventory.
  6. Super Admin có thể chỉnh sửa device trong system inventory.
  7. Super Admin có thể assign một device cho organization.
  8. Super Admin có thể unassign device khỏi organization để đưa về inventory hệ thống.
  9. Super Admin có thể đổi inventoryStatus sang maintenance hoặc retired.
  10. Device retired không thể assign lại.
  11. Device đang maintenance không thể được assign mới.
  12. Admin không thể tạo device từ system inventory module.
  13. /system/devices/devices là hai scope khác nhau, không dùng cùng UX contract.
  14. inventoryStatus được tách riêng khỏi operationalStatus.

7) Out of Scope

  • Luồng Admin mua/claim device
  • Billing hoặc order flow khi customer mua device
  • Audit log chi tiết cho mọi thao tác inventory
  • Thiết kế lại module /devices ở cấp organization
  • Firmware management hoặc bulk device provisioning
  • Ticket/maintenance workflow chi tiết cho Technical

8) Risks and Mitigations

  • Risk: Trộn lẫn system scope và tenant scope trong cùng service/controller
    Mitigation: Tách contract, route, và query logic riêng cho /system/devices.

  • Risk: Device đã có telemetry hoặc lịch sử vận hành bị xóa sai
    Mitigation: Giới hạn delete, ưu tiên retired cho thiết bị đã từng dùng thực tế.

  • Risk: inventoryStatusoperationalStatus bị nhập nhằng
    Mitigation: Tách hai trường riêng, không trộn trạng thái ownership với trạng thái kết nối kỹ thuật.

  • Risk: Product docs và codebase tiếp tục lệch nhau về ownership model
    Mitigation: Xem spec này là nguồn quyết định mới để điều chỉnh permission model, route model, và create flow về cùng một hướng.