KB-6019 rev 11
Table Module — SSOT v4
6 min read Revision 11
ssottable-moduleM-003assemblyregistry
Table Module — SSOT v4
v4.1 | Cập nhật: 2026-03-08 S107 — table_registry 16 records (thêm entity_dependencies). Selftest tools verify Lớp 2 data. Registry Wiring Rule: tạo collection → PHẢI tạo table_registry. MỌI AGENT đọc file này trước khi làm việc liên quan đến bảng dữ liệu.
search_knowledge("table module SSOT")
I. NGUYÊN TẮC — TABLE MODULE LÀ SSOT THỰC SỰ
Mỗi bảng trong UI = 1 record trong table_registry (Directus). Có ID duy nhất.
Không có record trong registry = bảng đó KHÔNG ĐƯỢC PHÉP TỒN TẠI.
table_registry (Directus) ← SSOT: config tất cả bảng
↓
DirectusTable (component) ← CỔNG DUY NHẤT: render bảng
↓
UTable (Nuxt UI) ← ENGINE: sort/filter/pagination
3 quy tắc cứng:
- MỌI bảng PHẢI có record trong
table_registryvớitable_idduy nhất - MỌI nơi hiển thị bảng PHẢI dùng
<DirectusTable tableId="xxx" />— KHÔNG UTable trực tiếp, KHÔNG custom table - Thêm bảng mới = thêm record registry + 1 dòng
<DirectusTable tableId="xxx" />— KHÔNG code logic
Vi phạm = reject PR.
II. KIẾN TRÚC 3 LỚP
Lớp 1: ĐĂNG KÝ — table_registry (Directus collection)
Mỗi bảng UI = 1 record. Chứa: collection, fields, sort, filter, flags.
Thêm bảng = thêm record. Sửa cột = sửa record. KHÔNG SỬA CODE.
Lớp 2: RENDER — DirectusTable.vue (component duy nhất)
Props: tableId (string) — fetch config từ table_registry → render UTable.
Bên trong: UTable + insert marks + proposals + search + pagination.
KHÔNG AI dùng UTable trực tiếp ngoài file này.
Lớp 3: KIỂM SOÁT — CI Guard + Auto Tester
CI: cấm UTable trực tiếp + cấm custom <table> HTML.
Auto Tester: so sánh tableId trong code vs registry → lệch = cảnh báo.
III. SCHEMA: table_registry
| Field | Type | Mô tả | Bắt buộc |
|---|---|---|---|
| id | PK auto | — | auto |
| table_id | string unique | ID duy nhất: tbl_workflow_list |
✅ |
| name | string | Tên hiển thị: "Danh sách quy trình" | ✅ |
| collection | string | Directus collection: workflows |
✅ |
| fields | json | [{"key":"process_code","label":"Mã QT"}, ...] |
✅ |
| default_sort | string | -date_created hoặc sort_order |
|
| default_filter | json | {"status":{"_eq":"active"}} |
|
| page_url | string | /knowledge/workflows |
✅ |
| enable_insert_marks | boolean | default: true | |
| enable_proposals | boolean | default: true | |
| enable_search | boolean | default: true | |
| enable_pagination | boolean | default: true | |
| rows_per_page | integer | default: 50 | |
| status | string | active / draft / archived | default: active |
| module | string | M-002, M-003, Core... | |
| description | text | Mô tả bảng dùng làm gì | |
| date_created | timestamp | auto | auto |
| date_updated | timestamp | auto | auto |
IV. CÁCH DÙNG
Tạo bảng mới:
- Thêm record
table_registry(Directus admin hoặc DOT tool) - Trong Vue:
<DirectusTable tableId="tbl_xxx" /> - XONG.
Sửa cột/filter/sort:
- Sửa record trong
table_registry - UI tự cập nhật. KHÔNG SỬA CODE.
DirectusTable logic:
mounted → GET /items/table_registry?filter[table_id][_eq]={props.tableId}
→ nhận config (collection, fields, sort, filter, flags)
→ GET /items/{collection}?fields=...&sort=...&filter=...
→ render <UTable> với config
→ insert marks, proposals, search, pagination theo flags
V. REGISTRY — TẤT CẢ BẢNG (cập nhật 2026-03-05)
| table_id | name | collection | page_url | module | status |
|---|---|---|---|---|---|
| tbl_workflow_list | Danh sách quy trình | workflows | /knowledge/workflows | M-002 | active |
| tbl_workflow_steps | Bảng bước (Trình tự) | workflow_steps | /workflows/[id]?tab=matrix | M-002 | active |
| tbl_workflow_timeline | Trình tự rút gọn (Tiến trình) | workflow_steps | /workflows/[id]?tab=diagram | M-002 | active |
| tbl_wcr_list | Đề xuất thay đổi | workflow_change_requests | /workflows/[id]?tab=wcr | M-002 | active |
| tbl_modules_list | Danh sách modules | modules (custom) | /knowledge/modules | M-003 | active |
| tbl_tasks_list | Task Manager | tasks | /knowledge/current-tasks | Core | active |
| tbl_proposals_list | Đề xuất bảng | table_proposals | (chưa có trang) | M-003 | draft |
Tổng: 7 bảng.
VI. CI GUARD
enforce-table-module.yml (MỚI — thay enforce-table-rule.yml)
Kiểm tra 1: grep "<UTable" trong .vue files, LOẠI TRỪ DirectusTable.vue
→ > 0 = FAIL (bypass: <!-- TABLE-DIRECT-OK: lý do -->)
Kiểm tra 2: grep "<table|<thead|<tr|<td" trong .vue files, LOẠI TRỪ DirectusTable.vue
→ > 0 = FAIL (bypass: <!-- TABLE-EXCEPTION: lý do -->)
VII. AUTO TESTER — Table Compliance
Test 1: Registry vs Code
grep -rn 'tableId=' web/ → danh sách tableId trong code
GET /items/table_registry?filter[status][_eq]=active → danh sách trong Directus
So sánh → thiếu/thừa = FAIL
Test 2: UTable bypass
grep "<UTable" ngoài DirectusTable.vue → > 0 = FAIL
Test 3: Custom table HTML
grep "<table|<thead|<tr" ngoài DirectusTable.vue → > 0 = FAIL
Test 4: Page alive
Mỗi record registry có page_url → curl → 200 = PASS
Kết quả → upload reports/ + tạo task Directus nếu FAIL
VIII. NỢ KỸ THUẬT
| ID | Mô tả | Trạng thái |
|---|---|---|
| TT-020 | Tạo table_registry collection + seed 7 records | 🔴 CẦN LÀM |
| TT-021 | DirectusTable nhận tableId, fetch config từ registry | 🔴 CẦN LÀM |
| TT-022 | Migrate tất cả trang sang tableId (bỏ props cứng) | 🔴 CẦN LÀM |
| TT-023 | Fix diagram tab: UTable trực tiếp → DirectusTable | 🔴 CẦN LÀM |
| TT-024 | CI guard enforce-table-module.yml | 🔴 CẦN LÀM |
| TT-025 | Auto Tester Table Compliance | 🟡 SAU |
| TT-026 | Fix 403 workflow_steps permission | 🔴 CẦN LÀM |
v4.0 | S105 | Registry = SSOT. DirectusTable = cổng duy nhất. tableId = quản lý. CI + Tester = enforcement.