@fui-org/fui-cli 1.3.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +21 -3
  2. package/dist/fui-cx180e19.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +3 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/skills/fui-target/.claude-plugin/plugin.json +6 -0
  63. package/skills/fui-target/hooks/hooks.json +1 -0
  64. package/skills/fui-target/hooks/register.tsx +71 -0
  65. package/skills/fui-target/types/index.d.ts +7 -0
  66. package/dist/fui-y8an39cn.js +0 -420
  67. package/skills/fui-skill/README.md +0 -112
  68. package/skills/fui-skill/metadata.json +0 -75
  69. package/skills/fui-skill-cli/SKILL.md +0 -139
  70. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  71. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  72. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  73. package/skills/fui-skill-cli/references/component-design.md +0 -448
  74. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  75. package/skills/fui-skill-cli/references/component-table.md +0 -248
  76. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  77. package/skills/fui-skill-cli/references/components-display.md +0 -141
  78. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  79. package/skills/fui-skill-cli/references/components-input.md +0 -335
  80. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  81. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  82. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  83. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  84. package/skills/fui-skill-cli/references/default-function.md +0 -425
  85. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  86. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  87. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  88. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  89. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  90. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  91. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  92. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  93. package/skills/fui-skill-cli/references/new-session.md +0 -85
  94. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  95. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  96. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  97. package/skills/fui-skill-cli/references/project-config.md +0 -303
  98. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  99. package/skills/fui-skill-cli/references/script-map.md +0 -262
  100. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  101. package/skills/fui-skill-cli/references/system-design.md +0 -89
  102. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  103. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  104. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  105. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  106. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  107. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  108. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  109. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  110. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  111. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  112. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  113. package/skills/fui-skill-cli/references/verification.md +0 -236
  114. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  115. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,460 +1,84 @@
1
- # FUI MCP Tools — Safety Registry
2
-
3
- > File này sở hữu: **phân loại rủi ro từng tool, quy tắc publish "sửa file nào gọi tool đó",
4
- > bí danh tiếng Việt → tool, guard DB enforce ở code, tool SSE-only**. Quy trình DB/SP chi tiết xem
5
- > [db-workflow.md](db-workflow.md); checklist nghiệm thu xem [verification.md](verification.md).
6
-
7
- Mọi tool được phân loại theo 2 chiều:
8
-
9
- - **ReadOnly** (`R`) / **Mutating** (`M`) — tool có ghi dữ liệu không? **Tính CẢ ghi xuống workspace
10
- local**, không riêng ghi lên server: một tool "chỉ fetch về" vẫn **ghi đè file local** của bạn, và
11
- đó chính là thao tác làm mất sửa đổi chưa publish (bản cũ được chép vào `_history/` trước — mất thì
12
- lấy lại được, nhưng phải biết là nó đã xảy ra). Chỉ `R` khi tool không chạm byte nào trên đĩa.
13
- - **Safe** (`✅`) / **RequiresConfirm** (`⚠️`) / **Destructive** (`🔴`) — mức độ rủi ro
14
-
15
- > **Nguyên tắc mặc định**: Tool là Mutating và cần xác nhận TRỪ KHI được đánh dấu rõ là ReadOnly/Safe.
16
- > **Per-call rule**: Safety đánh giá theo input thực tế của từng lần gọi — cùng tool có thể safe hay không tùy ngữ cảnh.
17
- >
18
- > **Strict mode (`FUI_MCP_STRICT=1`)**: khi server chạy strict mode, các tool publish/deploy (`module_publish_json`, `module_publish_html`, `module_publish_script`, `component_update`, `db_sp_deploy`) bị **chặn cứng** cho tới khi `skill_get` được gọi trong session; lỗi (error) từ `module_validate` cũng **chặn publish** module.json. Mode thường chỉ cảnh báo mềm.
19
-
20
- ---
21
-
22
- ## STDIO/CLI vs SSE/remote — hai cách lập trình khác nhau
23
-
24
- Server FUI-MCP và client AI có thể **cùng máy (STDIO)** hoặc **khác máy (SSE)** — điều này quyết định workflow nào khả dụng:
25
-
26
- | | STDIO/CLI | SSE/remote |
27
- |---|---|---|
28
- | Filesystem chung với server | Có — client dùng Read/Edit/Write/Grep/Glob của riêng nó chạm thẳng vào file server đọc | Không — hai tiến trình tách biệt, không có ổ đĩa/mount chung |
29
- | Cách sửa file trước khi publish | Sửa file thật trong workspace bằng tool filesystem của client | Gọi tool `*_stage` (xem bên dưới) để server tự ghi nội dung vào workspace |
30
- | Cách tìm kiếm/duyệt nhiều file | Dùng Grep/Glob native của client (rẻ, quét cả thư mục) | Dùng `workspace_glob` / `workspace_grep` (tool riêng, mô phỏng lại) |
31
- | Các tool `_stage`, `workspace_glob`, `workspace_grep` | **Không tồn tại** — server chỉ đăng ký các tool này khi chạy `--sse` | Có sẵn |
32
-
33
- **Quy tắc chọn tool khi sửa module.json / header.html / body.html / script.js / component .vue:**
34
- 1. Nếu đang ở STDIO/CLI và có thể đọc/ghi file trực tiếp → sửa file, rồi gọi thẳng tool publish tương ứng (`module_publish_json`, `module_publish_html`, `module_publish_script`, `component_update`).
35
- 2. Nếu không có filesystem access (SSE/remote) → gọi tool `*_stage` tương ứng trước để ghi nội dung vào workspace của server, sau đó gọi đúng tool publish y hệt bước 1 — không cần biết gì thêm, tool publish luôn đọc lại từ workspace bất kể nội dung đến từ đâu.
36
-
37
- Không bao giờ tự đoán mode đang chạy — nếu tool `*_stage` / `workspace_glob` / `workspace_grep` xuất hiện trong danh sách tool khả dụng, nghĩa là đang chạy SSE và nên dùng chúng thay vì giả định có filesystem.
38
-
39
- ---
40
-
41
- ## Đồng bộ trước khi đọc — kiểm tra mtime file
42
-
43
- Mọi file do FUI MCP lấy về workspace từ server (`module.json`, `header.html`, `body.html`,
44
- `script.js`, `_moduleInfo.json`, `uc-*.vue`, `project.json`, `_projectInfo.json`,
45
- `_db/{alias}/{name}.sql`...) chỉ là **bản sao tại thời điểm checkout gần nhất** — nội dung trên server có
46
- thể đã bị người khác sửa sau đó.
47
-
48
- **Quy tắc bắt buộc**: trước khi đọc bất kỳ file nào thuộc nhóm trên (để review/sửa), kiểm tra thời
49
- gian sửa đổi cuối (mtime) của file trên đĩa. **Cũ hơn 48 giờ → phải đồng bộ lại từ server trước khi
50
- đọc** — không review/sửa trên bản có thể đã lỗi thời, và không publish đè lên thay đổi mới hơn của
51
- người khác mà không biết.
52
-
53
- Các tool đọc (`module_validate`, `module_outline`, `module_simulate`, `module_preview`,
54
- `db_schema_read`, `db_sp_verify`) **tự phát cảnh báo** khi bản local quá 48h — thấy dòng `⏳ ... đồng
55
- bộ lần cuối cách đây N ngày` thì chạy lệnh nó nêu trước khi sửa/publish. Muốn tự kiểm:
56
-
57
- ```powershell
58
- (Get-Item "<đường-dẫn-file>").LastWriteTime
59
- ```
60
-
61
- **Tool đồng bộ theo loại file** — mỗi tool làm mới **toàn bộ** file của phạm vi đó, không phải một file:
62
-
63
- | File | Tool đồng bộ |
64
- |---|---|
65
- | `module.json`, `header.html`, `body.html`, `script.js`, `_moduleInfo.json`, `uc-*.vue` module-scope, nội dung import 2 scope | `module_get` |
66
- | `uc-*.vue` project-scope (`{projectId}/components/`) | `component_get`, hoặc `project_sync` cho cả project |
67
- | `project.json`, `_projectInfo.json`, `_modules.json`, `imports/*` (cả nội dung) | `project_sync` |
68
- | `_db/{alias}/schema.json` **và** toàn bộ `_db/{alias}/*.sql` — **của một kết nối**; project nhiều database phải gọi cho từng alias | `db_schema_get` |
69
- | Một SP lẻ | `db_sp_get` |
70
-
71
- **Luôn ghi đè, không hỏi.** Sync không so sánh để quyết định có ghi hay không — nó ghi. Thứ bảo vệ
72
- sửa đổi local là `{workspaceRoot}/_history/`: mọi file sắp bị ghi đè (hoặc xoá) được chép vào đó
73
- trước, giữ nguyên hình dạng đường dẫn gốc và kèm thời điểm trong tên file:
74
-
75
- ```
76
- _history/{projectId}/modules/{moduleId}/module_20260801_143022.json
77
- _history/{projectId}/_db/{alias}/spAPI_X_20260801_143022.sql
78
- _history/{projectId}/components/uc-abc_20260801_143022_deleted.vue ← _deleted: bị xoá, không phải ghi đè
79
- ```
80
-
81
- Dòng `💾 N file local khác bản server → bản cũ đã lưu vào _history/` là **thông báo, không phải câu
82
- hỏi**. Muốn lấy lại bản cũ: chép ngược file trong `_history` về đúng đường dẫn mà subpath của nó mô
83
- tả (bỏ phần `_{thời điểm}` khỏi tên), rồi publish/deploy lại như bình thường. `_history` không bao
84
- giờ tự dọn — người dùng tự xoá khi thấy đủ.
85
-
86
- Không có filesystem access (SSE/remote): không áp dụng — các tool đọc (`module_get_ui`,
87
- `component_get`, `db_sp_get`...) luôn fetch trực tiếp từ server mỗi lần gọi, không có bản cache cũ
88
- trên đĩa client để lo.
89
-
90
- ---
91
-
92
- ## Bí danh người dùng → tool
93
-
94
- User thường gọi tool bằng tên thân mật tiếng Việt. Bảng tra ngược (cách nói → tool đúng):
95
-
96
- | User nói | Tool |
97
- |---|---|
98
- | "module nào đang active", "đang làm module gì" | `session_read` |
99
- | "chọn module", "đổi module đang làm việc", dán URL module đang chạy, dán route `/projectId/moduleId`, hoặc chỉ nói tên project/module (không kèm get/sync/checkout) | `session_set` |
100
- | "bỏ active module" | `session_clear` |
101
- | "resolve target" | `session_resolve` |
102
- | "danh sách project" | `project_list` |
103
- | "tạo project" | `project_new` |
104
- | "tạo dự án mới", "tạo DB + project FUI mới", "dựng hệ thống từ đầu" | [project-provisioning.md](project-provisioning.md) — quy trình 6 bước, đừng bắt đầu bằng `project_new` |
105
- | "tạo database mới", "đăng ký alias", "thêm DB vào tAPI" | `db_alias_new` |
106
- | "cấp quyền admin project", "cho ai đó sửa project", "thêm người vào project" | `project_user_search` → `project_user_new` |
107
- | "ai được sửa project này" | `project_user_list` |
108
- | "cập nhật project", "sửa project" | `project_update` |
109
- | "cập nhật project.json", "đẩy project.json lên", "sửa menu project" | sửa file `{projectId}/project.json` rồi `project_publish_config` |
110
- | "kết nối DB nhưng chỉ biết alias/apiName", "không có dbToken" | `db_alias_list` → `db_connect_by_name` |
111
- | "đồng bộ project", "refresh project", "lấy project.json" | `project_sync` |
112
- | "danh sách module" | `module_list` |
113
- | "tạo module mới", "thêm module" | `module_new` |
114
- | "đổi tên module", "đổi ID module", "đổi framework" | `module_update` |
115
- | "xóa module", "xoá module" | `module_delete` |
116
- | "lấy module về", "xem module", "đọc module", "down", "clone module", "refresh", "pull mới nhất" | `module_get` |
117
- | "lấy module.json" | `module_get_ui` |
118
- | "lấy header/body html" | `module_get_html` |
119
- | "cập nhật module.json" | `module_publish_json` |
120
- | "xem trước", "kiểm tra trước khi up", "diff" | `module_preview` |
121
- | "validate module", "kiểm tra module.json" | `module_validate` |
122
- | "review giao diện", "xem layout", "outline module" | `module_outline` |
123
- | "mô phỏng", "test luồng", "simulate module", "chạy thử action" | `module_simulate` |
124
- | "render giao diện", "xem UI thật", "chụp màn hình module", "xem trên mobile" | `module_simulate({ renderUI: true })` |
125
- | "up header", "up body", "up html", "cập nhật html", "đẩy lên" | `module_publish_html` |
126
- | "xem component", "đọc component vue" | `component_get` |
127
- | "thử component", "test component riêng", "xem component có chạy không", "component trên mobile" | `component_preview` |
128
- | "tạo component", "thêm component mới" | `component_new` |
129
- | "up component", "push component", "sửa component" | `component_update` |
130
- | "xóa component", "xoá component" | `component_delete` |
131
- | "sync component" | `component_list` |
132
- | "up script", "push script.js", "cập nhật script" | `module_publish_script` |
133
- | "up style", "push style.css", "cập nhật CSS module" | `module_publish_css` |
134
- | "danh sách import file", "sync import" | `file_import_list` |
135
- | "lấy nội dung file import" | `file_import_get` |
136
- | "cập nhật nội dung file" | `file_import_upload_content` |
137
- | "thêm import file" | `file_import_new` |
138
- | "cập nhật import file" | `file_import_update` |
139
- | "xóa import file" | `file_import_delete` |
140
- | "lấy skill rules" | `skill_get` |
141
- | "tạo SP mới", "deploy SP", "cập nhật SP" | `db_sp_save` → `db_sp_deploy` |
142
- | "thêm quyền chức năng", "tạo FunctionRight" | `right_function_new` |
143
- | "sửa quyền chức năng" / "xóa quyền chức năng" | `right_function_update` / `right_function_delete` |
144
- | "thêm/sửa/xóa mức SystemRight" | `right_system_new` / `right_system_update` / `right_system_delete` |
145
- | "lưu user token", "set userToken", "token để gọi API" | `db_user_token_set` |
146
- | "đổi password DB", "rebuild dbToken", "cập nhật kết nối DB" | `db_token_rebuild` |
147
- | "project này đang nối những DB nào", "alias nào default" | `db_config_read` |
148
- | "nối thêm một database nữa", "project dùng 2 DB" | `db_connect` lần nữa với `apiName` mới |
149
- | **"đồng bộ db"**, **"sync database"**, **"refresh schema"**, **"cập nhật schema"**, **"làm mới schema"** | `db_schema_get` — **KHÔNG phải `project_sync`**. Chưa có kết nối DB thì phải thông báo yêu cầu cung cấp thông tin kết nối, KHÔNG đi gọi tool khác thay thế |
150
- | "danh sách design", "có style nào" | `design_list` |
151
- | "lấy design", "dùng style X" | `design_read` |
152
-
153
- Mô tả chức năng đầy đủ của từng tool đã có sẵn trong schema MCP — bảng trên chỉ để ánh xạ cách nói,
154
- mức rủi ro xem các bảng bên dưới.
155
-
156
- ---
157
-
158
- ## Session Tools
159
-
160
- | Tool | R/M | Safety | Ghi chú |
161
- |---|---|---|---|
162
- | `session_read` | R | ✅ | Chỉ đọc session hiện tại |
163
- | `session_set` | M | ✅ | Set active target — reversible |
164
- | `session_clear` | M | ✅ | Clear target — không xóa data |
165
- | `session_resolve` | R | ✅ | Resolve path string, không ghi |
166
-
167
- ---
168
-
169
- ## Project Tools
170
-
171
- | Tool | R/M | Safety | Ghi chú |
172
- |---|---|---|---|
173
- | `project_list` | R | ✅ | Chỉ đọc |
174
- | `project_new` | M | ⚠️ | **Tạo** project mới — `projectData` KHÔNG được có `id` (có thì bị strip + cảnh báo). **Đòi `SystemRight >= 3` trên hệ thống `fp`** (cổng server-side trong `spAPI_FUI_Dev_ProjectEdit`); không có thì từ chối, đừng tạo database trước rồi mới phát hiện. **Chỉ 6 field được đọc**: `ProjectID`/`ProjectName`/`GroupName`/`Framework`/`pDomain`/`Router` — `title`/`login`/`apiDomain`/`menu`… truyền vào bị **bỏ qua lặng lẽ** (SP seed cột `projectData` bằng hằng số rỗng), cấu hình runtime phải đi đường `project_publish_config`. Tóm tắt trước khi gọi. Quy trình đầy đủ: [project-provisioning.md](project-provisioning.md) |
175
- | `project_update` | M | ⚠️ | **Chỉ sửa** project đã tồn tại — `projectData.id` **bắt buộc**, thiếu là lỗi cứng (thiếu id thì server sẽ tạo mới chứ không sửa). Tóm tắt trước khi gọi |
176
- | `project_publish_config` | M | ⚠️ | Đẩy **file** `{projectId}/project.json` local (runtime config: menu, navigation, domainSetting) lên server. **File-driven như `module_publish_*`**: sửa file trước, tool không nhận config qua tham số — nhờ vậy local không bao giờ lệch server sau khi publish. Lỗi cú pháp JSON = **lỗi cứng, không publish** (đẩy `{}` lên là xoá sạch config runtime của project). File không đổi kể từ lần publish/sync gần nhất → bỏ qua, không gọi API. Preview nội dung với user trước khi gọi. Client SSE dùng `project_config_stage` để ghi file trước |
177
- | `project_user_search` | R | ✅ | Tra tài khoản lập trình viên theo tên/username/id — **chỉ đọc, không cấp gì**. Đây là nguồn DUY NHẤT của `userId` mà 3 tool ghi bên dưới đòi, và đó là chủ đích: bảng `UserID \| Username \| Họ tên` nó in ra **chính là bước xác nhận danh tính** — đưa cho user xem và để họ chọn |
178
- | `project_user_list` | R | ✅ | Ai đang có quyền **sửa project trong IDE FUI** (`UserRight` 1/2/3, bảng `tblA_UserProject`). Quyền **luôn cấp project**, không có biến thể cấp module (`@MID` có trong chữ ký SP nhưng thân SP không đọc). Cần `SystemRight >= 2` và (`UserRight > 1` hoặc `SystemRight >= 3`). ⚠️ **KHÔNG phải** `SystemRight` của hệ thống `acc` — xem [permission-system.md](permission-system.md) |
179
- | `project_user_new` | M | ⚠️ | **Cấp** quyền IDE cho user **chưa có**; đã có ⇒ lỗi cứng trỏ sang `project_user_update`. `userId` **bắt buộc và phải chính xác** (lấy từ `project_user_search`) — tên gõ nhầm không bao giờ được biến thành một lượt cấp quyền Admin cho người khác. `userRight`: 1 View only · 2 Develop · **3 Admin** (mức người quản lý project cần). `0` không nhận ở đây. Người gọi cần `SystemRight >= 2` và (`UserRight > 2` trên project đó hoặc `SystemRight >= 4`) |
180
- | `project_user_update` | M | ⚠️ | **Chỉ đổi mức** quyền của user **đã có**; chưa có ⇒ lỗi cứng trỏ sang `project_user_new`. `userId` bắt buộc |
181
- | `project_user_delete` | M | 🔴 | **Thu hồi hẳn** quyền sửa project/module của một user. Tóm tắt hậu quả + chờ user xác nhận trước khi gọi |
182
- | `project_sync` | M | ✅ | Refresh **mọi file cấp project**: project.json, `_projectInfo.json`, `_modules.json`, component `.vue`, metadata import **và nội dung từng import file**; xóa file `.vue`/import content local nào đã từng được track nhưng server không còn nữa (component/import mới local chưa publish thì không đụng). Luôn ghi đè; file local khác bản server được lưu vào `_history/` trước |
183
-
184
- ---
185
-
186
- ## Module Tools
187
-
188
- | Tool | R/M | Safety | Ghi chú |
189
- |---|---|---|---|
190
- | `module_list` | R | ✅ | List module từ server — đồng thời refresh cache local (`modules/_modules.json` + `_moduleInfo.json` các module đã checkout) |
191
- | `module_get` | M | ✅ | Fetch module từ server → ghi/refresh TOÀN BỘ vào local workspace (module.json, html, script, .vue, imports 2 scope) + set active session — luôn ghi đè, file local khác bản server được chép vào `_history/` trước; xóa luôn `.vue`/import content local đã từng track nhưng server đã xóa (cũng lưu `_history/` kèm hậu tố `_deleted`). Metadata đọc từ cache `_modules.json`; cache miss thì **tool tự làm mới danh sách từ server một lần rồi thử lại** — không cần gọi `module_list` trước, và lỗi ở đây nghĩa là module thật sự không tồn tại. Không tham số → refresh module đang active |
192
- | `module_get_ui` | M | ✅ | Fetch module.json — **ghi đè `module.json` local** nếu module đã checkout (bản cũ vào `_history/` trước). Không phải tool chỉ-đọc |
193
- | `module_get_html` | M | ✅ | Fetch body html — **ghi đè `body.html` local** nếu module đã checkout (bản cũ vào `_history/` trước). Không phải tool chỉ-đọc |
194
- | `module_new` | M | ⚠️ | **Tạo module mới** trên server (`projectId` + `moduleId` + `moduleName` bắt buộc) — xác nhận ID và tên với user trước. Module tạo ra là **rỗng, chưa có file local**: gọi `module_get` sau đó để checkout. Trùng `moduleId` trong `_modules.json` → lỗi cứng, trỏ sang `module_update` |
195
- | `module_update` | M | ⚠️ | **Chỉ sửa metadata module đã tồn tại** (name/ID/framework/mDomain/HTMLOnly). Định danh bắt buộc: `projectId` + `moduleId` **hiện hành**. Đọc ModuleInfo từ local, gửi nguyên object + field sửa. Đổi ModuleID → URL đổi (link cũ vỡ) + rename dir local — cảnh báo user trước. Tạo module mới → `module_new` |
196
- | `module_delete` | M | 🔴 | **Xóa vĩnh viễn module trên server (FUI_Dev_moduleDelete) — không khôi phục được, không lưu history.** Đồng thời xóa entry trong `_modules.json`, xóa nguyên thư mục local đã checkout (nếu có), clear active session nếu đang trỏ vào module đó. Yêu cầu xác nhận rõ ràng từ user trước khi gọi |
197
- | `module_publish_json` | M | ⚠️ | Ghi **chỉ module.json** lên server — không đụng header/body/title/script. Không cần preview |
198
- | `module_preview` | R | ✅ | Diff local vs server — chỉ đọc + tạo token. Kèm sẵn báo cáo `module_validate` |
199
- | `module_validate` | R | ✅ | Static semantic validator cho `module.json` — kiểm tra CALL target, grid structure, `@`/`#` shorthand, `children`, component name, import thiếu, API vs schema, **statement trong giá trị `:attr`/`v-bind:`** (`function(){}`/`var`/`return`/`;` → hỏng compile template Vue → trang trắng mà 0 JS error, 0 Vue warn — xem [advanced-techniques.md](advanced-techniques.md) §1)... ⚠️ **KHÔNG** kiểm `script.js` (validator không đọc file đó): `EXE`/`FUN` gọi hàm chưa viết chỉ lộ ra ở `module_simulate({renderUI:true})` dưới dạng `… is not defined`, riêng `FUN` thì hỏng hoàn toàn im lặng — xem [advanced-techniques.md](advanced-techniques.md) §2. Kèm nhóm warning **`[design]`** (chuẩn thẩm mỹ App-mode mặc định: toolbar dialog có màu/dark, nút xóa màu error/đỏ, width dialog ngoài bộ chuẩn, form thiếu floating label, delete thiếu CONFIRM, nút Đóng thừa ở actions) — phải sửa trừ khi user yêu cầu rõ kiểu khác. Chạy SAU KHI sửa module.json, SỬA HẾT ERROR trước khi publish |
200
- | `module_outline` | R | ✅ | Render module.json thành cây layout TEXT để review UI: grid với w (flag Σw>12), binding, action tóm tắt 1 dòng, dialog + nơi mở, state/action không dùng. Cặp với `module_validate` — validate bắt lỗi quy tắc, outline để review cấu trúc |
201
- | `module_simulate` | R | ✅ | **Mô phỏng runtime FUI trên module.json — không cần browser.** Engine bám sát fastproject.js (runAction/getVueData/setValue/callAPI). Chạy init data[] + kịch bản sự kiện `{set}`/`{click}`/`{call}`/`{exe}`/`{assert}`, API trả mock từ `apiMocks` (hoặc `{__error}` để test ERROROUT), watch + deep-watch tự bắn sau mỗi bước (phát hiện vòng lặp), dialog mở/đóng được trace. Trả trace đầy đủ + state cuối + kết quả assert (isError khi assert fail). `apiMocks` bạn truyền luôn thắng; API tĩnh KHÔNG có mock mà SP đích đã xác nhận **chỉ đọc** (từ thân `.sql` local) thì tự động gọi tAPI thật (tối đa 8 lượt/lần, kết quả cache vào `_testdata/{alias}/{spName}.json` để tái dùng) — SP có lệnh ghi hoặc chưa xác định được thì không bao giờ bị gọi thật, rơi về cache/tự sinh mock/`{data:[]}`. **`renderUI: true`** → render module trong browser thật (Playwright chromium headless, optional — cần `npm i -D playwright && npx playwright install chromium`): trang được ghép **đúng như `spA_FUI_ModuleDataSelect`** — file framework theo V2/V3 lấy từ danh mục server (cache 24h) + import project + import module, sort chung `FileSort, FileName`; phần **cấp project** (`$projectData`, component project, CSS project) tải từ server qua `_aset` nên **sửa gì ở cấp project phải publish lên server trước, không thì render vẫn ra bản cũ**, còn phần **cấp module** (module.json, script.js, component/CSS module) dựng cục bộ nên sửa-thử được ngay chưa cần publish. Vue/Vuetify reactivity thật, cùng grammar scenario chạy trên DOM thật (KHÔNG hỗ trợ `item`/`index` — dùng `nth`), thu JS error + `[Vue warn]` + DOM audit (app rỗng, tràn ngang, text "undefined"/"NaN", ảnh vỡ, canvas chart 0-size) + state cuối vueData + screenshot vào `_preview/` (`render.png` trả inline image — quá lớn tự nén JPEG; dialog đang mở chụp riêng `render-dialog.jpg`). Test responsive: `device: "mobile"` (390×844 + touch) / `"tablet"` (768×1024). Chart/animation chậm chưa kịp render → tăng `settleMs` (mặc định 700ms). Toàn bộ network vẫn đi qua một điểm chặn duy nhất; API không có mock mà SP đích đã xác nhận chỉ đọc **và** hostname khớp đúng `apiDomain` của module thì được gọi thật (cùng chính sách/giới hạn với engine vm ở trên) — script trỏ domain khác không bao giờ được gọi thật. Demo data bơm qua param `vueData` |
202
- | `module_publish_html` | M | ⚠️ | Push **header.html / body.html / title + module.json** trong cùng lần gọi. Cần approval token từ `module_preview` (token phủ **toàn bộ payload sẽ đẩy đi** — đổi module.json, header/body.html, script.js, style.css, hoặc bất kỳ `components/*.vue` nào sau lúc preview đều làm token hết hiệu lực; chạy lại `module_preview`). Cũng push `script.js`/`style.css` nếu chúng KHÔNG rỗng (nhưng không tự clear khi rỗng — dùng `module_publish_script`/`module_publish_css` để clear), và **reconcile toàn bộ `components/*.vue`** với server (tạo/cập nhật local, XÓA component nào trên server không còn file local tương ứng) |
203
-
204
- ### Quy tắc publish — Sửa file nào, gọi tool đó
205
-
206
- **Trước khi publish module.json (bằng bất kỳ tool nào):** chạy `module_validate` và sửa hết **error** (warning cân nhắc theo ngữ cảnh). `module_publish_json`/`module_publish_html` cũng tự chạy validator và đính kèm báo cáo — ở strict mode error sẽ chặn publish. Sau đó chạy `module_outline` để tự review cấu trúc UI: đọc cây layout, kiểm tra width từng row, dialog nào chưa có nút mở, action nào không ai gọi.
207
-
208
- **Với logic runtime phức tạp (action chain nhiều bước, watch cascade, dialog flow):** chạy thêm `module_simulate` với kịch bản mô phỏng luồng chính (mở dialog → nhập → lưu → reload) + mock response theo shape suy luận tĩnh từ `db_sp_verify` (SP ghi thì luôn dùng mock — không bao giờ bị gọi thật; SP đọc không có mock có thể tự được gọi thật, xem dòng `module_simulate` ở bảng trên). Assert các điều kiện then chốt (`dialogEdit === false` sau lưu, `items.length > 0` sau load). Trace sẽ chỉ ra CALL trỏ sai, IN thiếu biến, dialog quên đóng, watch lặp vô hạn — TRƯỚC khi publish.
209
-
210
- **Chọn tool theo file đã thay đổi:**
211
-
212
- | File thay đổi | Tool | Ghi chú |
213
- |---|---|---|
214
- | Chỉ `module.json` | `module_publish_json` | Không cần preview |
215
- | `header.html` / `body.html` / title | `module_publish_html` | Cần `module_preview` trước. **module.json được push kèm tự động — không cần gọi thêm `module_publish_json`** |
216
- | `header.html` / `body.html` / title **và** module.json cùng lúc | `module_publish_html` | Một lần gọi đủ cả hai |
217
- | `script.js` (có nội dung hoặc rỗng để clear) | `module_publish_script` | Luôn dùng tool này — kể cả khi xóa trắng script |
218
- | `style.css` (có nội dung hoặc rỗng để clear) | `module_publish_css` | Luôn dùng tool này — kể cả khi xóa trắng CSS |
219
- | `uc-*.vue` component | `component_new` cho lần đẩy ĐẦU TIÊN, `component_update` cho các lần sau | Scope suy từ `moduleId`; kèm gửi `<style scoped>` (nếu có) thành `ComCSS`. `component_update` **lỗi cứng** nếu component chưa có trên server (không âm thầm tạo). Component **cấp project**: phải `component_preview` rồi `component_new`/`component_update` **trước** khi render module dùng nó — `module_simulate({renderUI:true})` chặn cứng nếu bản local lệch bản server |
220
-
221
- **Khi nhiều file thay đổi trong một lần — gọi lần lượt từng tool:**
222
-
223
- ```
224
- Ví dụ: sửa cả module.json + script.js + một component
225
- → module_publish_json (hoặc module_publish_html nếu header/body cũng đổi)
226
- → module_publish_script
227
- → component_update
228
- ```
229
-
230
- **Quy trình khi dùng `module_publish_html`:**
231
- ```
232
- module_preview → user xem diff → user approve → module_publish_html
233
- ```
234
-
235
- Không được gọi `module_publish_html` khi chưa có approval từ user.
236
-
237
- **Backstop tự động (không thay cho việc tự nhớ publish đủ file):** mỗi moduleDir giữ một ledger
238
- cục bộ (hash nội dung, đọc/ghi thuần filesystem, không gọi mạng) đánh dấu file nào đã khớp lần
239
- publish/sync gần nhất. Quên publish một trong các file vừa sửa → cả `module_validate` lẫn kết quả
240
- của tool publish vừa gọi đều tự in dòng `⚠️ N file local chưa publish` kèm đúng tool cần gọi tiếp
241
- cho từng file. Cảnh báo này KHÔNG chặn publish và KHÔNG thay thế quy tắc "gọi lần lượt từng tool"
242
- ở trên — nó chỉ là lưới bắt lại khi quy tắc đó bị quên.
243
-
244
- **Cùng ledger đó cũng tự chặn chiều gọi TRÙNG:** `module_publish_json` / `module_publish_script` /
245
- `module_publish_css` / `component_update` đều tự so nội dung local hiện tại với hash đã ghi ở lần
246
- publish gần nhất **trước khi** gọi API. Khớp — ví dụ gọi `module_publish_json` ngay sau
247
- `module_publish_html` đã đẩy kèm module.json cùng nội dung — thì tool **bỏ qua API call, trả về
248
- ℹ️** thay vì gửi lại. Không cần tự nhớ "đã gọi module_publish_html rồi thì khỏi gọi
249
- module_publish_json nữa": gọi thừa vẫn an toàn, chỉ là không tốn round-trip. Đây KHÔNG áp dụng cho
250
- `module_publish_html` — tool đó luôn thật sự đẩy (nó là nguồn ghi ledger, không phải nơi đọc để
251
- so sánh).
252
-
253
- ---
254
-
255
- ## Component Tools
256
-
257
- | Tool | R/M | Safety | Ghi chú |
258
- |---|---|---|---|
259
- | `component_get` | M | ✅ | Đọc .vue source từ server — **đồng thời ghi đè file `.vue` local** (bản cũ vào `_history/` trước). Bỏ `moduleId` → project-scope |
260
- | `component_preview` | R | ✅ | Render **một** component trong không gian riêng (browser thật) với dữ liệu mẫu truyền thẳng trong tham số, mặc định desktop + mobile. Đọc file `.vue` **local** nên chạy được trên bản chưa push. Quy trình: xem `component-design.md` |
261
- | `component_list` | M | ✅ | Refresh `_components.json` local từ server + xóa `.vue` mồ côi (từng track, server đã xóa). Bỏ `moduleId` → project-scope. Dùng khi list lệch với server |
262
- | `component_new` | M | ⚠️ | **Tạo component chưa có trên server** (INSERT, không gửi ComID). Đọc file `.vue` local — file phải tồn tại sẵn. Làm mới `_components.json` **từ server trước** rồi mới kiểm tra tên: trùng tên = lỗi cứng (cache cũ mà cứ INSERT thì server sinh HAI record cùng tên, không sửa được từ MCP). Sau khi tạo tự sync lại để lấy ComID thật |
263
- | `component_update` | M | ⚠️ | **Chỉ ghi đè component đã tồn tại** — ComID tự lookup từ `_components.json` (không truyền tay); không có trong cache = **lỗi cứng**, không âm thầm tạo mới. Scope suy từ `moduleId`; kèm gửi `ComCSS` (trích từ khối `<style scoped>` trong `.vue`, nếu có). Tự sync `_components.json` sau khi ghi |
264
- | `component_delete` | M | 🔴 | **Xóa component khỏi server — không khôi phục được** (không lưu history như `db_sp_deploy`); tự lookup ComID từ `_components.json`. Scope suy từ `moduleId`. Tự sync `_components.json` + xóa `.vue` local mồ côi. Yêu cầu xác nhận rõ ràng trước khi gọi |
265
-
266
- ### Scope rule — áp dụng cho tất cả component tools
267
-
268
- ```
269
- moduleId có giá trị → module-scope (chỉ module đó)
270
- moduleId vắng mặt → project-scope (global, auto-load ở mọi module)
271
- ```
272
-
273
- | Tình huống | moduleId dùng | projectId dùng |
274
- |---|---|---|
275
- | Truyền cả hai | Arg | Arg |
276
- | Chỉ truyền `projectId` | *(none)* → project-scope | Arg |
277
- | Không truyền gì, session đủ cả hai | session.moduleId | session.projectId |
278
- | Không truyền gì, session chỉ có projectId | *(none)* → project-scope | session.projectId |
279
-
280
- ---
281
-
282
- ## Script & CSS Tools
283
-
284
- | Tool | R/M | Safety | Ghi chú |
285
- |---|---|---|---|
286
- | `module_publish_script` | M | ⚠️ | Push script.js lên server — dùng nội dung rỗng `""` để clear script trên server |
287
- | `module_publish_css` | M | ⚠️ | Push style.css lên server — dùng nội dung rỗng `""` để clear CSS trên server |
288
-
289
- ---
290
-
291
- ## Import File Tools
292
-
293
- | Tool | R/M | Safety | Ghi chú |
294
- |---|---|---|---|
295
- | `file_import_list` | R | ✅ | List + tự đồng bộ METADATA `_imports.json` local (fileID, filePath...) — không tải nội dung file, luôn 1 API call rẻ; xóa file content local mồ côi (từng track, server đã xóa) |
296
- | `file_import_get` | R | ✅ | Fetch source của MỘT file theo fileId — đồng thời ghi xuống mọi `imports/` local đang khai fileID này |
297
- | `file_import_new` | M | ⚠️ | Tạo import file mới trên server, tự sync `_imports.json`. `fileSort` bỏ trống → mặc định an toàn theo scope (project ≥ 20, module ≥ 50); thấp hơn ngưỡng → tự nâng lên (framework luôn FileSort thấp ~1-10, xem platform-architecture.md §2.2) |
298
- | `file_import_update` | M | ⚠️ | Cập nhật metadata import file — tự sync mọi `_imports.json` local có khai fileID này, migrate file vật lý nếu filePath đổi. `fileSort` bỏ trống → giữ nguyên; thấp hơn ngưỡng scope (project ≥ 20, module ≥ 50) → tự nâng lên |
299
- | `file_import_upload_content` | M | ⚠️ | Ghi nội dung file lên server — tự ghi lại xuống mọi local imports/ có khai fileID này |
300
- | `file_import_delete` | M | 🔴 | **Xóa import file** — không khôi phục được; tự xóa entry + file vật lý mồ côi khỏi mọi `_imports.json` local; yêu cầu xác nhận rõ ràng |
301
-
302
- ---
303
-
304
- ## Database Tools
305
-
306
- > **Một project có thể nối NHIỀU database cùng lúc** — mỗi cái một alias (= `apiName` = đoạn đầu trong
307
- > `"API": "/{alias}/Ten"`), lưu tách bạch trong `_db/{alias}/`. Vì vậy **mọi tool trong bảng nhận thêm
308
- > tham số `db`** (alias) để chọn kết nối. Bỏ trống thì MCP tự suy từ tên object đang thao tác; suy
309
- > không ra (không khớp alias nào, hoặc SP trùng tên ở hai DB) thì tool trả về **MENU các alias** —
310
- > chọn một cái rồi gọi lại, **đừng đoán**. Chưa biết project có những kết nối nào: `db_config_read`.
311
-
312
- | Tool | R/M | Safety | Ghi chú |
313
- |---|---|---|---|
314
- | `db_config_read` | R | ✅ | Liệt kê **mọi kết nối** của project (alias, apiDomain, sqlServer, database, thư mục `_db/{alias}/`, trạng thái dbToken/userToken) + alias nào là `default`. Gọi trước tiên khi chưa chắc phải truyền `db` nào. Cũng nêu thư mục trong `_db/` không thuộc kết nối nào (rác — user tự xoá) |
315
- | `db_alias_list` | R | ✅ | Liệt kê **mọi database mà token hiện tại được cấp quyền quản lý** (`APIName`/`SQLServer`/`DatabaseName`/`ModuleName`/`Enable`). **Không cần tham số nào** — danh sách đã lọc sẵn theo quyền của chủ token (tAPI bơm `@sys_UserID` phía server); `search` chỉ lọc thêm phía client. Chạy cái này khi chưa biết alias, hoặc khi `db_connect_by_name` báo không tìm thấy |
316
- | `db_alias_new` | M | ⚠️ | **Đăng ký một database MỚI thành alias tAPI** trên hệ thống `acc` (`SM_Modules_Update` 2 lượt: `UpdateConnection=0` tạo record → `=1` nạp connection). Không tạo database — làm việc đó trước bằng `db_sql_execute_nonquery`. 🔴 `username`/`password` phải là **tài khoản ỨNG DỤNG** (execute-only), nạp nhầm tài khoản dev thì mọi lời gọi API chạy dưới `db_owner` mà không lỗi nào nổi lên. Alias đã tồn tại ⇒ lỗi cứng, không ghi đè. `ModuleID` = MAX+1 trên toàn bộ `acc.tblModules` → cần kết nối alias `acc`. Không in credential. Quy trình đầy đủ: [project-provisioning.md](project-provisioning.md) |
317
- | `db_connect_by_name` | M | ✅ | **Kết nối DB khi chỉ biết `apiName`, không có `dbToken`.** Tra `SQLServer`/`DatabaseName` từ acc → **mượn cặp UID/PWD** của một kết nối sẵn có (`borrowCredentialsFrom: "{projectId}/{alias}"`; bỏ trống thì tự quét workspace tìm kết nối cùng `apiDomain`, nhiều login khác nhau thì trả **menu**) → dựng dbToken → **test `SELECT 1` trước khi lưu** → lưu + fetch schema như `db_connect`. Không tìm thấy `apiName` nghĩa là **alias không tồn tại HOẶC bạn không được cấp quyền quản lý nó** — chạy `db_alias_list()` để biết mình có gì. Không bao giờ in dbToken/UID/PWD |
318
- | `db_connect` | M | ✅ | Kết nối DB + tự fetch schema — **dùng khi ĐÃ có sẵn `dbToken`**; chưa có thì dùng `db_connect_by_name`. — ghi mục `apiName` vào `_db/_connections.json` và `_db/{alias}/schema.json`; archive `_db/{alias}/{name}.sql` mồ côi (SP/function đã bị DROP trên server) vào `_history/`. **Project gọi nhiều database thì gọi nhiều lần**, mỗi alias một lần — lần sau không đụng gì tới kết nối đã có. Kết nối thêm **không tự giành `default`** (muốn đổi: `makeDefault: true`) |
319
- | `db_user_token_set` | M | ✅ | Lưu userToken vào **một kết nối** local — không ảnh hưởng server. Nhiều kết nối thì nêu `db`, bỏ trống là vào kết nối mặc định |
320
- | `db_token_rebuild` | M | ⚠️ | Rebuild dbToken từ uid/password mới — overwrite token hiện tại; xác nhận server/database đúng trước khi gọi. **`db` bắt buộc khi project có >1 kết nối** (ghi nhầm là đè credential của DB khác) |
321
- | `db_schema_get` | M | ✅ | Làm mới **toàn bộ `_db/{alias}/` của ĐÚNG MỘT kết nối** (alias khác không được đụng tới — phải gọi riêng): schema + **tải lại thân từng file `{alias}/*.sql`** (luôn ghi đè; bản local khác server được lưu vào `_history/` trước); đồng thời **quét thư mục `_db/{alias}/`** đối chiếu schema mới. SP từng có trong schema cũ mà nay mất (đã DROP trên server) → tự archive vào `_history/`. File không có ở cả schema cũ lẫn mới → **chỉ liệt kê** (`⚠️ N file trong _db/{alias}/ KHÔNG có trên server`), vì có thể là SP đang soạn local chưa deploy; user xác nhận là rác thì gọi lại `db_schema_get({ pruneLocalOnly: true })` để archive luôn. ĐỌC dòng ⚠️ này và hỏi user, đừng tự ý prune |
322
- | `db_schema_read` | R | ✅ | Đọc cached schema **của một kết nối**. Không thấy một bảng/SP thường không phải "chưa có" mà là đang đọc nhầm kết nối |
323
- | `db_sp_list` | R | ✅ | Liệt kê SPs — bỏ trống `db` thì liệt kê **mọi kết nối**, ghi rõ SP nào thuộc alias nào (đây là tool để *khám phá*, nên không im lặng cắt còn một DB) |
324
- | `db_sp_get` | M | ✅ | Đọc SP source + **ghi đè `_db/{alias}/{name}.sql`** — bản local khác server được lưu vào `_history/` trước. Không phải tool chỉ-đọc |
325
- | `db_sql_execute` | R/M | ⚠️ | SELECT hoặc lệnh ghi trực tiếp (đường user chủ động sửa/xoá dữ liệu thật) — kết quả cắt tối đa 200 dòng; TOP 20 nếu chỉ cần khảo sát cấu trúc; không SELECT binary/max columns; **DROP TABLE/DROP COLUMN bị block ở code; `ALTER TABLE` cho `ADD`+`DROP CONSTRAINT`, `ALTER COLUMN` cần `confirmWrite`**; lệnh ghi cần `confirmWrite: true` |
326
- | `db_sp_save` | M | ⚠️ | Lưu SP vào local — chưa deploy. **Không có tool "tạo SP" riêng**: `CREATE PROCEDURE` lần đầu đi qua đúng cặp `db_sp_save` → `db_sp_deploy` y như một lần sửa. SP **mới hoàn toàn** thì chưa có gì để suy alias — project nhiều kết nối phải nêu `db` ngay lần lưu đầu |
327
- | `db_sp_rename` | M | ⚠️ | Đổi tên SP trong DB — tóm tắt trước khi gọi; tự đổi tên `_db/{alias}/{name}.sql` local theo nếu có |
328
- | `db_sp_deploy` | M | 🔴 | **Deploy SP vào DB** — tự lưu **định nghĩa đang chạy trên server** vào `_history/` trước khi ghi (đây là bản để rollback); tóm tắt SP nào, loại thao tác (CREATE/ALTER); chờ user xác nhận. Nếu tên là `spAPI_*`/`spAPIFILE_*`, tự gọi route `/help` để xoá cache tAPI sau khi deploy (best-effort, không chặn deploy nếu lỗi). **Chặn cứng nếu SP tAPI có tham số gán default value** (`= value`/`= null`, kể cả `@sys_*`) — xem [tapi-reference.md](tapi-reference.md) |
329
- | `db_sp_help` | R | ✅ | Gọi route `/help` của một API SP đã deploy — trả tham số đầu vào **và** xoá cache tAPI cho hàm đó. Gọi **đúng một lần** theo URL chuẩn; hỏng thì chỉ ghi một dòng thông tin, **không phải lỗi** và **không thử URL biến thể** (dạng `/auth/` suy ra từ tên SP, không phải thứ để đoán). `db_sp_deploy` đã tự gọi; dùng tay khi SP đổi bằng đường khác, hoặc chỉ để tra tham số |
330
- | `db_sp_verify` | R | ✅ | Kiểm chứng **tĩnh** contract API SP — **không gọi HTTP/SQL nào cả**. Đọc thân SP thật (local `_db/{alias}/{name}.sql` hoặc live `OBJECT_DEFINITION`), suy luận: tham số, response shape (đếm SELECT top-level, cột, cảnh báo `SELECT *`), contract lỗi (RAISERROR+RETURN), phân loại đọc/ghi, sinh sẵn snippet `apiMocks`/`vueData` cho `module_simulate`. Không đọc được thân SP thật (chưa lưu local, live fetch cũng lỗi) = **lỗi cứng**, không đoán theo tên. Cũng cảnh báo sớm (không chặn) nếu tham số có default value — cùng lỗi `db_sp_deploy` sẽ chặn. Ngoại lệ **tự chọn** duy nhất: `checkGrant: true` chạy **một** truy vấn metadata (`sys.database_permissions`) để trả lời "`[public]` có quyền EXECUTE không" — quyền không nằm trong thân SP nên không cách nào suy ra được; dùng khi endpoint trả lỗi quyền hoặc khi SP được deploy ngoài `db_sp_deploy` |
331
- | `db_sp_delete` | M | 🔴 | **Xóa SP khỏi DB** — không khôi phục được; tự archive `_db/{alias}/{name}.sql` local vào `_history/` nếu có; yêu cầu xác nhận rõ ràng |
332
- | `db_sql_execute_nonquery` | R/M | 🔴 | **Chạy DDL/DML** (đọc lẫn ghi) — **DROP TABLE/DROP COLUMN bị block**; `ALTER TABLE` cho `ADD` + `DROP CONSTRAINT` tự do, `ALTER COLUMN` cần `confirmWrite`; **DELETE/UPDATE không WHERE bị block** (chỉ hiển thị SQL); lệnh ghi khác cần `confirmWrite: true`. Lệnh có `CREATE`/`ALTER PROCEDURE` → kết quả báo `[public]` **thực sự** có quyền EXECUTE hay không; đường này **không auto-grant và không xoá cache tAPI** (khác `db_sp_deploy`) nên tool nêu sẵn lệnh cần chạy tiếp |
333
- | `right_system_list` | R | ✅ | Liệt kê định nghĩa SystemRight (0–9) của project từ hệ thống phân quyền "acc" — cần userToken có quyền vào acc. Cũng ghi cache `{projectId}/_db/rights.json` **dưới khoá `apiName`** (mỗi kết nối một mục riêng) |
334
- | `right_system_new` | M | ⚠️ | **Định nghĩa một mức SystemRight CHƯA có**. Khoá `sysRight` do người dùng chọn (không có ID tự sinh) nên phải hỏi server bằng `SM_SystemRight_Select` trước — mức đó đã có định nghĩa = **lỗi cứng**, trỏ sang `right_system_update` |
335
- | `right_system_update` | M | ⚠️ | **Chỉ sửa mức SystemRight ĐÃ có**. Định danh bắt buộc: `sysRight` (lấy từ `right_system_list`). `sysRight=9` luôn được server gán note "Project Admin" |
336
- | `right_system_delete` | M | 🔴 | **Xóa định nghĩa một mức SystemRight** — tóm tắt trước khi gọi, chờ user xác nhận; server chặn nếu còn user đang giữ mức quyền đó |
337
- | `right_function_list` | R | ✅ | Liệt kê định nghĩa FunctionRight (FunctionID/Code/Name) của project từ "acc" — nguồn duy nhất để lấy `functionId` thật. Cũng ghi cache `{projectId}/_db/rights.json` **dưới khoá `apiName`** (mỗi kết nối một mục riêng): **chưa gọi tool này lần nào thì `module_validate`/`module_simulate`/renderUI không có gì để đối chiếu mã quyền** |
338
- | `right_function_new` | M | ⚠️ | **Tạo FunctionRight mới** (gửi `FunctionID: 0` — lệnh INSERT của SP). Server từ chối nếu `functionCode` trùng |
339
- | `right_function_update` | M | ⚠️ | **Chỉ sửa FunctionRight ĐÃ có**. Định danh bắt buộc: `functionId` (lấy từ `right_function_list`) — không còn `?? 0`, quên tham số không biến update thành create |
340
- | `right_function_delete` | M | 🔴 | **Xóa FunctionRight KÈM toàn bộ phân quyền user** đã gán mã đó — không khôi phục được. Định danh bắt buộc: `functionId`; tóm tắt hậu quả + chờ user xác nhận |
341
-
342
- > Khái niệm SystemRight (cấp bậc) vs FunctionRight (quyền theo chức năng) và chi tiết 8 tool trên: xem [permission-system.md](permission-system.md).
343
- >
344
- > **Gác quyền bằng mã chưa được định nghĩa là lỗi hỏng-âm-thầm:** `rightTest()` luôn trả false → control/menu biến mất, không lỗi JS, và **preview vẫn hiện đúng** (renderUI/`module_simulate` cấp sẵn cho user preview đúng những mã quét được từ module). Chạy `right_function_list`/`right_system_list` trước — vừa để biết mã thật, vừa để `module_validate` có cache đối chiếu.
345
-
346
- ### Quy tắc bắt buộc cho DB tools
347
-
348
- **Áp dụng cho tất cả `db_sql_execute` và `db_sql_execute_nonquery`:**
349
- 1. Trình bày tóm tắt: query làm gì, dữ liệu nào bị ảnh hưởng
350
- 2. Đợi user xác nhận trước khi gọi tool
351
- 3. Lệnh ghi (INSERT/UPDATE+SET/DELETE/MERGE/TRUNCATE) → gọi lại kèm `confirmWrite: true` chỉ SAU KHI
352
- user đã xác nhận trong chat — không tự set để "cho lệnh chạy được" (đây là cổng xác nhận, không
353
- phải cản trở kỹ thuật cần lách qua)
354
-
355
- **Guards được enforce ở code level (không thể bypass):**
356
- - DDL bảng theo tiêu chí **mất dữ liệu hay không**: ✅ tự do `ALTER TABLE … ADD` (cột/ràng buộc) và `DROP CONSTRAINT` (gỡ quy tắc, không gỡ dữ liệu) · ⚠️ cần `confirmWrite` `ALTER COLUMN` (thu hẹp độ chính xác số/thời gian mất dữ liệu ÂM THẦM, trong khi thu hẹp kiểu chuỗi thì SQL Server báo lỗi và huỷ câu lệnh) · 🚫 blocked `DROP TABLE`, `DROP COLUMN`, `SWITCH`, và mọi hành động không nhận diện được (fail-closed). Xét theo TỪNG câu lệnh: một câu `ADD` không bảo lãnh cho câu `DROP COLUMN` đứng sau, và blocked luôn thắng confirm
357
- - `DELETE` / `UPDATE` không có `WHERE` → blocked, trả về SQL dạng display-only để user copy thủ công
358
- - Lệnh ghi thiếu `confirmWrite: true` → blocked, trả bản xem trước (loại lệnh, bảng, có WHERE hay
359
- không) — set `confirmWrite: true` sau khi user xác nhận thì chạy thật. `confirmWrite` **không** mở
360
- được 2 guard phía trên
361
- - `db_sp_deploy` → tự lưu định nghĩa SP đang chạy trên server vào `{workspaceRoot}/_history/` trước khi overwrite
362
-
363
- **Quy tắc bắt buộc — xoá cache tAPI sau mỗi lần ALTER/UPDATE `spAPI_*`/`spAPIFILE_*`:**
364
- - Dùng `db_sp_deploy`: tự gọi `/help` xoá cache **một lần**; hỏng thì bỏ qua, đi tiếp — SP đã deploy xong, đây chỉ là dọn cache.
365
- - Dùng `db_sql_execute_nonquery` chạy `ALTER PROCEDURE` trực tiếp: không có auto-clear → **bắt buộc gọi `db_sp_help` thủ công ngay sau ALTER thành công**. Đây là ca duy nhất bắt buộc gọi tay.
366
- - Không xoá cache → tAPI tiếp tục phục vụ chữ ký cũ, wire IN/OUT sai params mà không có lỗi rõ ràng.
367
-
368
- **Khi dùng `db_sql_execute`:**
369
- - Đây là tool **đọc và ghi dữ liệu thật** — SELECT để khảo sát (thêm `TOP 20` nếu chỉ cần xem cấu trúc, dữ liệu thực tế có thể rất lớn), hoặc ghi trực tiếp khi user chủ động yêu cầu sửa/xoá data (kèm `confirmWrite: true`, xem mục Guards ở trên).
370
- - Không SELECT cột kiểu `varbinary(max)`, `image`, `nvarchar(max)` dữ liệu lớn.
371
- - **Không dùng tool này để "test" logic một API** — kiểm chứng API là đọc thân SP + suy luận (`db_sp_verify`), không phải chạy sub-query sống để dò.
372
-
373
- **Kiểm chứng spAPI_* bằng `db_sp_verify` (suy luận tĩnh — KHÔNG gọi endpoint nào):**
374
- - Không phải "zero HTTP" nguyên văn. Có đúng **hai** ngoại lệ, cả hai là *đọc metadata* chứ không phải chạy SP: lấy `OBJECT_DEFINITION` khi chưa có `.sql` local, và `checkGrant: true` (bạn tự bật) hỏi `sys.database_permissions` về quyền EXECUTE của `[public]`. Quyền không nằm trong thân SP nên không có cách nào suy luận tĩnh ra được.
375
- - Sau khi `db_sp_deploy` một API **đọc** (Select/List/Get) mà sắp wire vào module.json → chạy `db_sp_verify` để suy luận shape response thật (array / array-of-arrays / convert_to_object) từ chính thân SP trước khi viết `OUT`/`CALLBACK` — không gọi endpoint để xác nhận.
376
- - API **ghi** (Insert/Update/Delete/...): `db_sp_verify` đọc thân SP thật (local `_db/{alias}/{name}.sql`, hoặc live `OBJECT_DEFINITION` nếu chưa có local) và liệt kê checklist cần tự suy luận (điều kiện WHERE, transaction, RAISERROR đúng contract) — không chặn theo đọc/ghi vì không có gì được gọi cả.
377
- - Cần test **luồng UI** gọi API ghi (form submit, nút Lưu/Xóa...) → dùng `module_simulate({ apiMocks: { "{FunctionName}": { data: [...] } } })` (hoặc kèm `renderUI: true`) với snippet mock mà `db_sp_verify` sinh sẵn — không gọi API thật.
378
- - KHÔNG đọc được thân SP thật (chưa `db_sp_get`, và fetch live cũng lỗi — ví dụ thiếu quyền DB) → tool trả về **lỗi cứng**, không đoán theo tên, không có cách chạy tiếp; phải `db_sp_get` thành công trước rồi mới verify lại được.
379
- - Kiểm tra logic SP phức tạp trước khi deploy: đọc thân SP (`db_sp_get`) và suy luận tĩnh câu lệnh — **không gọi `spAPI_*` sống để dò logic** dưới bất kỳ hình thức nào.
380
-
381
- **BẮT BUỘC — `apiMocks` của một SP ĐÃ TỒN TẠI phải lấy từ `db_sp_verify`, không được tự suy diễn:** nếu SP đứng sau tên API **đã deploy** (có trong schema local của **bất kỳ kết nối nào** — `module_simulate` đối chiếu gộp cả các alias), cấu trúc `apiMocks` phải là snippet do `db_sp_verify` sinh ra từ thân SP thật — **không** bịa cột/shape theo tên hàm hay quy ước đoán được. Bịa cấu trúc cho một SP có thật là nguyên nhân trực tiếp khiến mô phỏng "chạy đúng" nhưng thực tế vỡ (tên cột lệch, `array` mà thực ra là `array-of-arrays`, thiếu cột lỗi). `module_simulate` tự đối chiếu khoá `apiMocks` với schema local và cảnh báo nổi bật (`🚨 CẤU TRÚC MOCK CHƯA ĐƯỢC KIỂM CHỨNG`) nếu SP đó chưa từng được `db_sp_verify` đọc thân trong phiên hiện tại — thấy cảnh báo này thì dừng lại, chạy `db_sp_verify` rồi copy nguyên văn snippet, không sửa tay apiMocks đang có rồi bỏ qua cảnh báo. Ngoại lệ hợp lệ duy nhất: SP **chưa tồn tại** (giai đoạn thiết kế UI trước khi có SP thật) — lúc đó bịa dữ liệu mẫu là đúng quy trình, cảnh báo trên sẽ không nổ vì không có gì để đối chiếu.
382
-
383
- **CREATE hay ALTER — không phải việc phải đoán:** `db_sp_deploy` đã hỏi server object có tồn tại chưa (để dựng bản rollback), nên nó **tự khớp động từ** trong bản gửi đi và in một dòng `ℹ️` báo đã đổi. Viết `CREATE PROCEDURE` cho một SP đã có **không còn là lỗi** — đừng sửa file thành `ALTER` rồi deploy lại. File `.sql` local không bị tool sửa.
384
-
385
- **`GRANT EXECUTE TO [public]` — đừng viết vào file .sql:** thân `CREATE PROCEDURE` kéo dài tới hết batch, tAPI gửi một batch và không hỗ trợ `GO`, nên câu GRANT sau `END` bị **nuốt vào thân SP** (chạy mỗi lần gọi SP, không cấp quyền lúc deploy, không lỗi nào nổi lên). `db_sp_deploy` tự chạy GRANT cho procedure **thật sự mới**, rồi hỏi lại `sys.database_permissions` và in `✓`/`❗` — đây là câu trả lời thật, không phải giả định. Thấy `❗` thì chạy đúng câu nó in ra, **đừng deploy lại**. Deploy SP qua `db_sql_execute_nonquery` thì không auto-grant và không xoá cache tAPI — tool cảnh báo kèm lệnh cần chạy. Kiểm tra về sau: `db_sp_verify({ name, checkGrant: true })` (checklist đầy đủ: [verification.md](verification.md)).
386
-
387
- **Trước khi `db_connect`:** thông tin kết nối lưu vào `{projectId}/_db/_connections.json` dưới khoá `apiName` — projectId không rõ thì **hỏi user**, không tự đoán (chi tiết: [db-workflow.md](db-workflow.md) §4).
388
-
389
- ---
390
-
391
- ## Skill & Design Tools
392
-
393
- | Tool | R/M | Safety | Ghi chú |
394
- |---|---|---|---|
395
- | `skill_get` | R | ✅ | Đọc skill rules (SKILL.md + Tier A bundled) |
396
- | `skill_reference_get` | R | ✅ | Đọc Tier B/C/D reference file theo đường dẫn — bắt buộc cho client không có filesystem access (web/remote) |
397
- | `skill_sync` | M | ✅ | Refresh skill từ server |
398
- | `design_list` | R | ✅ | Liệt kê brand design systems có sẵn |
399
- | `design_read` | R | ✅ | Đọc DESIGN.md của một brand |
400
-
401
- ---
402
-
403
- ## Maintenance Tools (vòng tiến hoá skill)
404
-
405
- Mọi tool call thất bại (isError) ở mọi session đều được server tự ghi vào `{workspaceRoot}/_logs/tool-errors.jsonl` — **trừ** guard chặn để chờ `confirmWrite` (đó là control-flow bình thường: gọi lại kèm xác nhận là xong, không phải lỗi cần đem đi vá skill).
406
-
407
- | Tool | R/M | Safety | Ghi chú |
408
- |---|---|---|---|
409
- | `error_log_read` | R | ✅ | Đọc log lỗi tool — **gom nhóm** theo tool + chữ ký lỗi đã chuẩn hoá, xếp theo tần suất; nhóm lặp lại nhiều = lỗ hổng trong skill references cần vá. Khối `🛡 Guard chặn ĐÚNG THIẾT KẾ` ở cuối là các lần guard DB cứng chạy đúng (DROP TABLE, ALTER TABLE huỷ dữ liệu, DELETE/UPDATE thiếu WHERE) — **không** phải lỗ hổng, không tính vào bảng chính |
410
- | `error_log_clear` | M | ✅ | Xoá log sau khi đã review và cập nhật skill |
411
-
412
- ---
413
-
414
- ## SSE-only Tools (không tồn tại ở STDIO/CLI)
415
-
416
- Chỉ được đăng ký khi server chạy `--sse` (`node build/index.js --sse`). STDIO/CLI không bao giờ thấy các tool này trong danh sách — không cần cân nhắc dùng hay không khi ở CLI.
417
-
418
- ### Tìm kiếm — thay thế Grep/Glob native
419
-
420
- | Tool | R/M | Safety | Ghi chú |
421
- |---|---|---|---|
422
- | `workspace_glob` | R | ✅ | Tìm file theo glob pattern (`**/*.vue`, `modules/**/module.json`...) trong workspace. Chỉ trả về đường dẫn tương đối, KHÔNG trả nội dung file — dùng để khám phá trước khi gọi `module_get`/`component_get`/`file_import_get` lấy nội dung cụ thể |
423
- | `workspace_grep` | R | ✅ | Tìm nội dung theo regex trên nhiều file cùng lúc, chỉ trả về dòng khớp kèm số dòng (không trả cả file) — giữ chi phí context thấp khi tìm trên nhiều file |
424
-
425
- Scope của cả hai: `projectId`+`moduleId` → module-scope; chỉ `projectId` → toàn bộ project (mọi module); không truyền gì → dùng active session.
426
-
427
- ### Staging — ghi full-content vào workspace trước khi publish
428
-
429
- | Tool | R/M | Safety | Ghi chú | Gọi tiếp theo |
430
- |---|---|---|---|---|
431
- | `module_stage_json` | M | ⚠️ | Ghi `content` (JSON string) vào `module.json` trên workspace server. Validate JSON trước khi ghi | `module_publish_json` |
432
- | `module_stage_html` | M | ⚠️ | Ghi `header`/`body`/`title` (field nào có mới ghi field đó) vào workspace | `module_preview` → `module_publish_html` |
433
- | `script_stage` | M | ⚠️ | Ghi `code` vào `script.js`. Truyền `""` để stage một script rỗng | `module_publish_script` |
434
- | `css_stage` | M | ⚠️ | Ghi `code` vào `style.css`. Truyền `""` để stage một style rỗng | `module_publish_css` |
435
- | `component_stage` | M | ⚠️ | Ghi `code` vào `{name}.vue`. Scope suy từ `moduleId` giống hệt `component_new`/`component_update` | `component_new` (lần đầu) hoặc `component_update` |
436
-
437
- **Lưu ý quan trọng:** các tool `_stage` chỉ ghi xuống đĩa workspace của server — **không** publish lên FUI. Luôn phải gọi tool publish tương ứng ở cột cuối sau khi stage xong, đúng như quy tắc "Sửa file nào, gọi tool đó" ở trên.
438
-
439
- ---
440
-
441
- ## Concurrency Rules
442
-
443
- Các tools có thể chạy song song (parallel):
444
- - Tất cả ReadOnly (`R`) tools
445
- - `session_read`, `session_set`, `project_list`, `module_list`
446
-
447
- Không được chạy song song:
448
- - Bất kỳ Destructive (🔴) tool nào
449
- - `module_publish_html` với bất kỳ tool nào khác
450
- - `db_sp_deploy` với `db_sp_deploy` khác
451
-
452
- ---
453
-
454
- ## Tóm tắt Risk Matrix
455
-
456
- ```
457
- ✅ Safe → Gọi tự do, không cần hỏi
458
- ⚠️ RequiresConfirm → Tóm tắt cho user trước, chờ OK
459
- 🔴 Destructive → Tóm tắt đầy đủ + chờ xác nhận rõ ràng từ user
460
- ```
1
+ # fui commands — safety registry
2
+
3
+ Risk per command. `R` reads only (touches no byte on disk); `M` writes the server or the local workspace (a local refresh overwrites files; the old copy goes to `_history/` first).
4
+
5
+ - ✅ Safe: run freely.
6
+ - ⚠️ Confirm: summarize for the user and wait for OK.
7
+ - 🔴 Destructive: full summary, then an explicit yes from the user.
8
+
9
+ Full syntax: `fui <command> --help`. The fui skill (`fui skill`) has the Fui fui command → command map.
10
+
11
+ ## Commands
12
+
13
+ | Command | R/M | Risk |
14
+ | ------------------------------------------------------------------------------------------- | ----- | ---- |
15
+ | `use`, `use --clear`, `resolve` | M / R | ✅ |
16
+ | `project list` | R | ✅ |
17
+ | `project sync` | M | ✅ |
18
+ | `project new`, `project update`, `project publish-config` | M | ⚠️ |
19
+ | `user search`, `user list` | R | ✅ |
20
+ | `user add`, `user set` | M | ⚠️ |
21
+ | `user remove` | M | 🔴 |
22
+ | `module list`, `module validate`, `module outline`, `module simulate`, `module preview` | R | ✅ |
23
+ | `module get`, `module get-ui`, `module get-html` | M | ✅ |
24
+ | `module new`, `module update` | M | ⚠️ |
25
+ | `module publish json`, `module publish html`, `module publish script`, `module publish css` | M | ⚠️ |
26
+ | `module delete` | M | 🔴 |
27
+ | `component get`, `component list` | M | ✅ |
28
+ | `component preview` | R | ✅ |
29
+ | `component new`, `component update` | M | ⚠️ |
30
+ | `component delete` | M | 🔴 |
31
+ | `import list`, `import get` | R | ✅ |
32
+ | `import new`, `import update`, `import upload` | M | ⚠️ |
33
+ | `import delete` | M | 🔴 |
34
+ | `db list`, `db alias list` | R | ✅ |
35
+ | `db add`, `db add-by-name`, `db user-token` | M | ✅ |
36
+ | `db alias new`, `db token-rebuild` | M | ⚠️ |
37
+ | `schema`, `sp list`, `sp help`, `sp verify` | R | ✅ |
38
+ | `schema pull`, `sp get` | M | ✅ |
39
+ | `query` | R/M | ⚠️ |
40
+ | `sp save`, `sp rename` | M | ⚠️ |
41
+ | `exec` | R/M | 🔴 |
42
+ | `sp deploy`, `sp delete` | M | 🔴 |
43
+ | `right system list`, `right function list` | R | ✅ |
44
+ | `right system new/update`, `right function new/update` | M | ⚠️ |
45
+ | `right system delete`, `right function delete` | M | 🔴 |
46
+ | `skill get`, `skill ref`, `design list`, `design read`, `library`, `log read` | R | ✅ |
47
+ | `log clear` | M | ✅ |
48
+
49
+ ## Refresh scope
50
+
51
+ Each refresh overwrites every file in its scope without asking (old copies go to `_history/`):
52
+
53
+ | Files | Refreshed by |
54
+ | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
55
+ | `module.json`, `header.html`, `body.html`, `script.js`, `_moduleInfo.json`, module-scope `uc-*.vue`, module imports | `fui module get` |
56
+ | project-scope `uc-*.vue` (`{projectId}/components/`) | `fui component get`, or `fui project sync` for all |
57
+ | `project.json`, `_projectInfo.json`, `_modules.json`, `imports/*` | `fui project sync` |
58
+ | `_db/{connectionName}/schema.json` and all `_db/{connectionName}/*.sql` of one connection | `fui schema pull` |
59
+
60
+ ## Publish: which command for which file
61
+
62
+ - Before publishing module.json: `fui module validate`, fix every error. For complex runtime logic (action chains, watch cascades, dialog flows) also `fui module simulate` the main flow.
63
+ - Only `module.json` → `fui module publish json` (no preview needed).
64
+ - `header.html` / `body.html` / title (with or without module.json) → `fui module preview`, user approves, then `fui module publish html --approval <token>`. It pushes module.json too.
65
+ - `script.js` (also to clear it) → `fui module publish script`. `module publish json` does not push it.
66
+ - `style.css` (also to clear it) → `fui module publish css`.
67
+ - `uc-*.vue` → `fui component new <name>` the first time, `fui component update <name>` after; scope comes from `-m`; `<style scoped>` is sent as ComCSS.
68
+ - Several files changed → one command per file, in turn. `fui file push <path...>` routes each path to its publisher; `fui file status` lists what is still unpublished (a local ledger; it never blocks a publish).
69
+
70
+ ## Database rules (enforced in code)
71
+
72
+ - `query` / `exec`: summarize what the SQL does and what data it touches, and wait for the user. Writes (INSERT, UPDATE…SET, DELETE, MERGE, TRUNCATE, ALTER COLUMN) exit 3 until `--confirm-write`, added only after the user approved that exact write.
73
+ - Always blocked, no flag unlocks them: `DROP TABLE`, `ALTER TABLE … DROP COLUMN`/`SWITCH`, `DELETE`/`UPDATE` without `WHERE` in `exec`. Show the SQL for the user to run by hand. `ALTER TABLE … ADD` and `DROP CONSTRAINT` are free.
74
+ - Never call a live API SP or run sub-queries "to test" it: read its body (`fui sp get`) and reason, or `fui sp verify <name|Fn>` (reads the definition; `--check-grant` also reads permissions).
75
+ - `apiMocks` for an SP that exists must come from `fui sp verify`, never guessed.
76
+ - `fui sp deploy`: archives the live body to `_history/`, fixes CREATE/ALTER, grants EXECUTE to `[public]` on new procedures, clears the tAPI cache once. After an `ALTER PROCEDURE` through `exec`, run `fui sp help <name>` to clear the cache yourself, or tAPI keeps the old signature.
77
+ - Never write `GRANT` into the `.sql` file: tAPI sends one batch without `GO`, so it would become part of the procedure body.
78
+ - A project can use several databases at once. `fui db add` stores each in `{projectId}/_db/_connections.json` under a readable `connectionName` (its `_db/` folder, `--name`, suggested from apiName + zone when omitted); `apiName` is a separate field, only the route alias, and may repeat across zones. `--db` takes a connectionName (a unique apiName also works); when ambiguous, commands print a MENU of connectionName + apiName + SQLServer/database: pick a line, never guess. If the project is unclear, ask the user.
79
+ - Secrets only via stdin (`-`) or `--*-env VAR`; never print `_db/_connections.json` or `_db/config.json`.
80
+
81
+ ## Concurrency
82
+
83
+ - Read-only commands can run in parallel.
84
+ - Never in parallel: any 🔴 command, `module publish html` with anything else, two `sp deploy`.