Assembly Module — SSOT
Assembly Module — SSOT
v1.0 | 2026-03-05 S104 Tài liệu NỀN TẢNG cho MỌI quyết định UI/component/module.
search_knowledge("assembly module SSOT")ĐỌC TRƯỚC: Operating Rules §0 + §II
I. TRIẾT LÝ
Hệ thống là ASSEMBLY ENGINE, không phải web app.
Schema (Directus) → Config (module) → Render (Nuxt UI) → UI xuất hiện
UI mới = khai báo schema + config. KHÔNG CODE.
II. KIẾN TRÚC 3 TẦNG
Tầng 1: Nuxt UI v2.22.3 (KHÔNG SỬA)
UTable, UTimeline, UStepper, UModal, UCheckbox, UTabs, UBadge,
UTooltip, UPopover, USkeleton, UPagination, UAccordion, UInput,
UTextarea, USelect, UForm, USlideover, UDropdown, UAvatar,
UBreadcrumb, UProgress, UNavigationMenu...
Tầng 2: Wrappers (viết 1 lần, dùng mãi mãi)
DirectusTable = UTable + Directus SDK + insert marks + proposals
DirectusTimeline = UTimeline + workflow_steps data + checkboxes
DirectusForm = UForm + Directus schema auto-fields (tương lai)
Tầng 3: Page config (DUY NHẤT viết khi cần UI mới)
<DirectusTable collection="workflows" :fields="[...]" />
Tối đa 20 dòng. Không code.
Scale: Thay đổi Tầng 2 → tất cả trang đổi theo. Tầng 3 không sửa.
III. NUXT UI INVENTORY (S104 — từ Assembly Step 1)
Đang dùng: 23 components (UButton 48x, UTable 8x, UBadge 7x...) Chưa dùng nhưng CÓ SẴN: UTimeline, UStepper, UPopover, UTabs, UBreadcrumb, USkeleton, UCheckbox, UProgress, UDivider, URadio, UToggle, UChip, UMeter, URange
Gap = USAGE, không phải availability. Không cần cài thêm gì.
Two-world problem: Portal layer dùng Nuxt UI. Knowledge/Workflow modules dùng custom HTML. Assembly = thống nhất tất cả sang Nuxt UI.
IV. WRAPPERS REGISTRY
| Wrapper | Wrap | Trạng thái | SSOT |
|---|---|---|---|
| DirectusTable | UTable + Directus SDK | 🔄 ĐANG XÂY (Step 3) | search_knowledge("table module SSOT") |
| DirectusTimeline | UTimeline/UStepper + workflow data | 📋 SAU Step 3 | — |
| DirectusForm | UForm + Directus schema | 📋 Tương lai | — |
V. ASSEMBLY GATE — 5 CÂU HỎI BẮT BUỘC
Mọi agent PHẢI trả lời TRƯỚC KHI code:
1. Nuxt UI đã có component? (UTable? UTimeline? UModal?...)
2. Codebase đã có wrapper/component tương tự? (grep)
3. CÓ → dùng NGUYÊN hoặc WRAP. KHÔNG viết lại.
4. KHÔNG CÓ → ghi rõ đã tìm ở đâu, tại sao không có.
5. Code mới đăng ký custom-code-registry.md chưa?
Vi phạm = reject PR.
VI. CUSTOM CODE ĐANG TỒN TẠI (cần migrate)
P1 — Tables (~939 dòng custom):
| File | Dòng | Thay bằng | Trạng thái |
|---|---|---|---|
| DirectusDataTable.vue | 639 | DirectusTable (UTable wrapper) | 🔄 Step 3 đang làm |
| ProcessRegistryView.vue | 389 | DirectusTable | 📋 Step 4 |
| current-tasks/index.vue | 217 | DirectusTable | 📋 Step 4 |
| approval-desk/index.vue | 333 | DirectusTable | 📋 Step 4 |
P2 — Popups (~400 dòng):
| File | Thay bằng | Trạng thái |
|---|---|---|
| ProposalPopup.vue | UPopover/UModal | 📋 Step 4 |
| InlineWcrPopup.vue | UPopover | 📋 Step 4 |
| Column desc popover | UTooltip | 📋 Step 4 |
P3 — Timeline (317 dòng):
| File | Thay bằng | Trạng thái |
|---|---|---|
| StepsTimeline.vue | DirectusTimeline (UTimeline wrapper) | 📋 Sau Step 4 |
P4 — Form elements (~15 files):
Raw <input>, <select>, <textarea>, <input type="checkbox"> → UInput, USelect, UTextarea, UCheckbox
VII. LỘ TRÌNH
| Bước | Mục tiêu | Trạng thái |
|---|---|---|
| 1 | Điều tra inventory | ✅ DONE |
| 2 | Cài thêm (nếu cần) | ✅ SKIP |
| 3 | DirectusTable wrap UTable | 🔄 ĐANG LÀM |
| 4 | Migrate TẤT CẢ custom tables + popups | 📋 SAU Step 3 |
| 5 | DirectusTimeline wrap UTimeline | 📋 SAU Step 4 |
| 6 | Migrate forms → Nuxt UI | 📋 SAU Step 5 |
| 7 | CI Guards enforce (TD-069) | 📋 SAU Step 6 |
Chi tiết: search_knowledge("assembly roadmap")
VIII. BÀI HỌC ĐAU THƯƠNG
S104: 4 vòng fix custom table thất bại (PR #437→#440). Nguyên nhân: viết 639 dòng custom <table> thay vì dùng UTable đã có (8 lần trong portal). Lãng phí 5+ phiên, hàng ngàn dòng code vứt đi.
Quy tắc rút ra: KHÔNG BAO GIỜ code component mà Nuxt UI đã có. Kiểm tra Nuxt UI TRƯỚC. Wrap nếu cần thêm tính năng. KHÔNG viết lại.
v1.0 | S104 | Assembly = Scale. Config = Code. Nuxt UI = Foundation.