@fui-org/fui-cli 2.2.0 → 2.2.2
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.
- package/README.md +11 -22
- package/dist/{fui-qrb1j9jz.js → fui-gexr4km5.js} +172 -172
- package/dist/fui.js +1 -1
- package/package.json +1 -1
- package/skills/fui/SKILL.md +38 -23
- package/skills/fui/references/INDEX.md +0 -2
- package/skills/fui/references/component-quickref.md +5 -3
- package/skills/fui/references/db-table-design.md +1 -1
- package/skills/fui/references/db-workflow.md +13 -13
- package/skills/fui/references/new-session.md +28 -24
- package/skills/fui/references/script-map.md +1 -1
- package/skills/fui/references/system-design.md +2 -2
- package/skills/fui/references/tools-registry.md +11 -7
- package/skills/fui/references/verification.md +7 -7
- package/skills/fui/scripts/fechart.js +56 -12
- package/skills/fui/agents/fui-builder.md +0 -62
- package/skills/fui/agents/fui-tester.md +0 -77
- package/skills/fui/references/team-run.md +0 -141
package/dist/fui.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{enableCompileCache as a}from"node:module";a?.();var{run:e}=await import("./fui-
|
|
2
|
+
import{enableCompileCache as a}from"node:module";a?.();var{run:e}=await import("./fui-gexr4km5.js");await e();
|
package/package.json
CHANGED
package/skills/fui/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fui
|
|
3
|
-
description: Use for all FUI (low-code platform) work, through the `fui` CLI — modules (module.json, components, imports), projects, users and rights, DB connections, SQL, schema, stored procedures (tAPI spAPI_*), publishing, workspace files and history. Holds the FUI rules
|
|
3
|
+
description: Use for all FUI (low-code platform) work, through the `fui` CLI — modules (module.json, components, imports), projects, users and rights, DB connections, SQL, schema, stored procedures (tAPI spAPI_*), publishing, workspace files and history. Holds the FUI rules and guides one agent through implementation and verification with minimal tool calls and context.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# FUI
|
|
@@ -9,27 +9,35 @@ description: Use for all FUI (low-code platform) work, through the `fui` CLI —
|
|
|
9
9
|
|
|
10
10
|
> **FOUNDATION RULE (all work):** before using any FUI runtime component (`f-table`, `f-dialog`, `f-echart`, `f-search`, `f-date`, `f-button`, ...), designing API/SP/DB, or applying `module.json`/component rules, **read the matching reference FIRST**. FUI differs from Vuetify, REST and training data; skipping → wrong config/imports/props, SPs off tAPI convention, UI off project patterns.
|
|
11
11
|
|
|
12
|
-
## Session start
|
|
12
|
+
## Session start
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Do not print this skill again when the agent platform already supplied it. For each task, read only the directly relevant references:
|
|
15
15
|
|
|
16
|
-
1.
|
|
17
|
-
2.
|
|
18
|
-
|
|
19
|
-
- [`module-structure.md`](references/module-structure.md) — module/project files, roles, HTMLOnly
|
|
20
|
-
3. From `INDEX.md`, `fui skill ref <refs...>` for the task, then start. Unsure → open `INDEX.md` first.
|
|
16
|
+
1. Module/UI work → [`controls-patterns.md`](references/controls-patterns.md) and [`module-structure.md`](references/module-structure.md).
|
|
17
|
+
2. Follow links from those files only when the task needs that subject. Use [`INDEX.md`](references/INDEX.md) only when the right reference is unclear.
|
|
18
|
+
3. If the platform did not supply this skill, run `fui skill get` once. Before a strict publish/deploy gate, use `fui skill loaded` if reading installed files did not already mark the session.
|
|
21
19
|
|
|
22
20
|
- Strict mode (`FUI_STRICT=1`) blocks publishing and deploys until the skill was read this session (`fui skill get`, `fui skill ref` or `fui skill loaded`) and while module.json has validation errors.
|
|
23
21
|
- First use on a machine: `fui config set api-base <url>` and `printf %s "$TOKEN" | fui config set api-token -` (ask the user for both). `fui config` shows what is set.
|
|
24
22
|
|
|
25
|
-
##
|
|
23
|
+
## Work efficiently
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
One agent owns the request from understanding through implementation, verification and fixes. Never start sub-agents or repeat the same context in hand-offs.
|
|
28
26
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
27
|
+
- For an exact change, edit it directly and run the cheapest relevant check. Do not create a plan file.
|
|
28
|
+
- For a broader change, form a short internal plan with acceptance criteria, then implement UI and API together and verify them yourself. Write a plan file only when the user asks for one or the work must survive another session.
|
|
29
|
+
- Inspect narrowly: search first, read only the relevant ranges, and avoid printing large generated files or data sets.
|
|
30
|
+
- Verify cheapest first: static validation before simulation, component preview before a full module render, and render only when pixels matter. Reuse the last scenario and mocks instead of regenerating them.
|
|
31
|
+
- Fix proven failures and rerun only the affected check. When the requested module work is complete and clean, publish it without adding a separate approval round.
|
|
32
|
+
|
|
33
|
+
### Completion includes upload
|
|
34
|
+
|
|
35
|
+
A request to create, design, fix or update a module authorizes the agent to publish and deploy everything required to complete that module after all assigned or planned work passes its checks. This includes the module files, its components, imports, project config and stored procedures. Do not stop merely to ask "may I upload?".
|
|
36
|
+
|
|
37
|
+
- For HTML publish, run `fui module preview`, review the diff yourself, then use its token immediately. The preview remains a technical safety check, not a user approval gate.
|
|
38
|
+
- Publish only files and SPs that belong to the current request. Never include unrelated local changes.
|
|
39
|
+
- If the developer said **do not upload**, **local only**, **draft**, **preview first**, or equivalent at any point, leave everything local and wait for explicit later approval before any publish/deploy.
|
|
40
|
+
- This standing authorization does not cover deleting modules/components/imports/SPs, changing users/rights, or writing real data. Those operations still require explicit approval for the exact action.
|
|
33
41
|
|
|
34
42
|
## Working rules
|
|
35
43
|
|
|
@@ -64,13 +72,13 @@ For every request to build or change something, decide yourself and say which in
|
|
|
64
72
|
|
|
65
73
|
**Imports**
|
|
66
74
|
|
|
67
|
-
-
|
|
75
|
+
- Before using an existing control, check `defaultControlAttr[control].import` in `scripts/component.js` (V2) or `scripts/component-3.0.js` (V3). Treat that array and its order as the source of truth for required JS/CSS; then check imports on every add or remove. → [component-quickref.md](references/component-quickref.md)
|
|
68
76
|
- **NEVER** add CDN for bundled libs (jQuery, lodash, moment, numeral, Vuetify, toast, jquery-confirm...); list: [script-map.md](references/script-map.md) §0.
|
|
69
77
|
- That ban is `HTMLOnly=false` only. `HTMLOnly: true` bundles **nothing** (no Vue, Vuetify, jQuery, lodash, MDI, `projectdefaultstyle.css`, `#fastProjectAPP`): CDNs are **required**, **per HTMLOnly module** (project level has no effect). → [module-structure.md](references/module-structure.md) §HTMLOnly=true
|
|
70
78
|
|
|
71
79
|
**Database** (enforced in code; details under "Writes need the user")
|
|
72
80
|
|
|
73
|
-
- **NEVER** `DROP
|
|
81
|
+
- **NEVER** `DROP DATABASE` or drop a persistent table, anywhere, incl. SP scripts. `DROP TABLE #name` (one local temporary table) is allowed; `##name`, schema-qualified names and a mixed drop list remain blocked.
|
|
74
82
|
- `ALTER TABLE` (structure OK, data loss not): **free** `ADD` (column/constraint), `DROP CONSTRAINT` · **needs `--confirm-write`** `ALTER COLUMN` · **hard-blocked** `DROP COLUMN`, `SWITCH`, all else (fail-closed). Checked **per statement**: an `ADD` doesn't cover a later `DROP COLUMN` in the batch; hard-block wins.
|
|
75
83
|
- **NEVER** `DELETE`/`UPDATE` without `WHERE`; show the SQL for the user to run.
|
|
76
84
|
- **Never test on the live system**; the line is **writes**, not network. Verify = read definition + reason + cross-check; **never run an SP that writes**, and never call a real API/SP/DML "to test". Levels:
|
|
@@ -136,7 +144,7 @@ Mode comparison, `border-radius` limits, DESIGN.md loop → [design-modes.md](re
|
|
|
136
144
|
- Writes never use the default when a project has several connections.
|
|
137
145
|
- `fui file where` prints what resolved and why.
|
|
138
146
|
- `fui config` shows the workspace and API settings with their sources: flag, env (`FUI_WORKDIR`, `FUI_API_BASE`, `FUI_API_TOKEN`), then `fui config set`. The default workspace is `~/.fui/workspaces`.
|
|
139
|
-
- A global install updates itself in the background, at most once an hour. A line starting `# fui updated` means a new version is running
|
|
147
|
+
- A global install updates itself in the background, at most once an hour. A line starting `# fui updated` means a new version is running and this skill refreshes on its own. `fui --version` prints the version.
|
|
140
148
|
|
|
141
149
|
## Modules: get, check, publish
|
|
142
150
|
|
|
@@ -158,8 +166,8 @@ uc-*.vue edited: fui component preview → (project-level component: fui compone
|
|
|
158
166
|
- `fui component preview <uc-name> --cases '[{"name":"empty","props":{"items":[]}}]'`: one local `.vue` alone in a real browser (desktop + mobile, sample data, works unpushed), so later bugs are assembly bugs. Do it before wiring a component in and before publishing a project-scope one.
|
|
159
167
|
- `fui module simulate --render [--device mobile]`: the real page in headless Chromium, last and only for problems that need pixels. It prints screenshot paths: open and read them, then fix what you see (cap above). → [ui-screenshot-review.md](references/ui-screenshot-review.md). Needs Playwright once, installed with the same package manager as fui: `npm install -g playwright && npx playwright install chromium` (or `bun add -g playwright && bunx playwright install chromium`).
|
|
160
168
|
- **Push project-level components BEFORE rendering modules that use them**: `--render` takes the project layer from the server bundle and **hard-blocks (no bypass)** when a local project-level `uc-*.vue` differs. Server newer → `fui project sync`, **don't overwrite**. → [component-design.md](references/component-design.md)
|
|
161
|
-
4. Publish **each edited file
|
|
162
|
-
- **Whole module, including header/body:** `fui module preview` →
|
|
169
|
+
4. Publish **each edited file** after the requested work passes its checks; command table and safety rules → [tools-registry.md](references/tools-registry.md):
|
|
170
|
+
- **Whole module, including header/body:** `fui module preview` → review the diff → `fui module publish html --approval <token>` without a separate user-confirmation turn.
|
|
163
171
|
- The token breaks if a payload file, an import it uploads or the module ids change after the preview.
|
|
164
172
|
- It reads and parses every local file and lists the server's components before the first request. A failure midway cannot be undone: the message names what reached the server and what did not.
|
|
165
173
|
- **One file:** `fui module publish json|script|css`, `fui component update <name>`, or `fui file push <path...>`, which routes each path to the right publisher.
|
|
@@ -217,7 +225,7 @@ Before writing `apiMocks` for an SP that exists, run `fui sp verify <name>`. It
|
|
|
217
225
|
- Writes to real data exit `3` until you add `--confirm-write`. That covers `INSERT`, `UPDATE`, `DELETE`, `MERGE` and `TRUNCATE` in `query` or `exec` (also inside `EXEC('...')` or `sp_executesql`), `SELECT ... INTO` a real table, `DROP PROCEDURE`/`FUNCTION`/`VIEW`, and `ALTER TABLE ... ALTER COLUMN`.
|
|
218
226
|
- Add `--confirm-write` **only after the user approved that exact write in chat**, never just to make it run. → [db-workflow.md](references/db-workflow.md)
|
|
219
227
|
- Always blocked, with no flag to unlock them. Show the SQL to the user to run by hand:
|
|
220
|
-
- `DROP TABLE` and `DROP DATABASE`
|
|
228
|
+
- `DROP TABLE` for a persistent/global table and `DROP DATABASE` (a single local `#name` temporary table is allowed)
|
|
221
229
|
- `ALTER TABLE ... DROP COLUMN` or `SWITCH`
|
|
222
230
|
- `xp_cmdshell`
|
|
223
231
|
- `DELETE`/`UPDATE` without `WHERE`, in `query` and `exec`
|
|
@@ -249,6 +257,12 @@ fui query "SELECT TOP 5 ID, Name FROM tblX" --json | jq -r '.[].Name'
|
|
|
249
257
|
|
|
250
258
|
## Connections and secrets
|
|
251
259
|
|
|
260
|
+
For any DB exploration, schema, SQL, or API/SP design, start with `fui db list -p <project>` and use a saved connection with `--db`. These operations use its **dbToken**. A `userToken` is only for the `acc` management lookup and end-user API calls; it cannot authenticate SQL requests.
|
|
261
|
+
|
|
262
|
+
One `userToken` is reusable across projects in the same SSO zone (the parent domain, e.g. `*.lhu.edu.vn`). When a project has no token, the CLI looks for one on the exact API host first, then on another host in that zone. Do not ask for a new login when there is one unique token in the zone. A different zone needs its own token; if several distinct tokens exist in the zone, use `--user-token-from <project/connectionName>` for `db alias list` or `db add-by-name` to select an already saved token without exposing it. → [db-workflow.md](references/db-workflow.md) §6a.
|
|
263
|
+
|
|
264
|
+
If no connection exists, find the project's tAPI domain with `fui project sync -p <project>` when needed, then run `fui db alias list -p <project>` to see databases the account may manage. Connect the chosen alias with `fui db add-by-name <apiName> -p <project>`. This discovers SQLServer/DatabaseName through `acc`, reuses a SQL UID/PWD pair from a saved dbToken (same apiDomain preferred; another domain works when it is the only login), builds a new dbToken, tests it against the target DB, and fetches schema. With several source logins, select one with `--borrow-from <project/connectionName>`. If there is no saved SQL login, use `--uid <login> --pwd -` or `--pwd-env VAR` with `add-by-name`. A management userToken alone cannot reveal the SQL password; never treat the `Password` field from `acc` as one. Then use `--db <project/connectionName>` for DB work.
|
|
265
|
+
|
|
252
266
|
```bash
|
|
253
267
|
printf %s "$TOKEN" | fui db add docs -p lhu-docs --token - --api-domain tapi.lhu.edu.vn --user-token-env UT
|
|
254
268
|
fui db add local -p demo --conn-env SQLITE_URL # sqlite:// connects directly (MSSQL goes through tAPI)
|
|
@@ -260,11 +274,12 @@ fui token decode --db lhu-docs/docs # never shows the password
|
|
|
260
274
|
Secrets are accepted only from stdin (`-`) or `--*-env VAR`. Never echo or paste token values.
|
|
261
275
|
|
|
262
276
|
- Never `cat`, `jq` or otherwise print `_db/_connections.json` or `~/.config/fui/config.json`. Use `fui db list`, `fui token decode` or `fui config`; they never print secrets.
|
|
263
|
-
-
|
|
264
|
-
- Know the alias but not the connection string? `fui db alias list`, then `fui db add-by-name <apiName>`: it
|
|
277
|
+
- Need a management userToken for the `acc` lookup? `fui db user-token` lists fingerprints of tokens already in the workspace; copy one with `--from <project/alias>`. This does not create a dbToken. The value never appears.
|
|
278
|
+
- Know the alias but not the connection string? `fui db alias list`, then `fui db add-by-name <apiName>`: it reuses a saved SQL UID/PWD pair and combines it with the target server/database returned by `acc`.
|
|
265
279
|
- `db add` / `db add-by-name` take `--name <connectionName>`; omitted, it is suggested from apiName, then apiName_zone. The same server + database re-added keeps its name, and folders are never renamed.
|
|
280
|
+
- `fui db remove <project>/<connectionName>` removes one local connection from `_connections.json`. It does not change the server; cached schema and SQL files under `_db/<connectionName>/` remain available.
|
|
266
281
|
- `right *` and `db alias new` write to the shared acc system. Ask the user first, especially for `delete`.
|
|
267
|
-
- `_db/_connections.json`
|
|
282
|
+
- `_db/_connections.json` has no `version` field. Existing files with `"version": 2` or connections missing `apiName` are normalized on first read (the old file goes to `_history/`); `fui db migrate` does this for every project at once.
|
|
268
283
|
|
|
269
284
|
## FUI conventions
|
|
270
285
|
|
|
@@ -95,8 +95,6 @@ Load: `fui skill ref references/a.md references/b.md` (several at once OK).
|
|
|
95
95
|
## Operations / publish
|
|
96
96
|
|
|
97
97
|
- "new session" / "phiên mới" / "cửa sổ mới": open another Claude Code CLI in its own terminal window (workspace root resolved dynamically, NEVER hard-coded) → `new-session.md`
|
|
98
|
-
- Hand work / instructions to another running Claude session (coordinating several sessions, a multi-AI workflow, parallelizing work per module) — `ListAgents`/`SendMessage` → `new-session.md` §6
|
|
99
|
-
- Build, test and fix one module with little supervision (planner → builder → tester → fix, one approval at the end) → `team-run.md` (the `fui` skill decides between this and a direct change; the agents come with fui)
|
|
100
98
|
- Per-command safety (R/M, Safe/Confirm/Destructive), strict mode, `fui sp verify`, error log → `tools-registry.md`
|
|
101
99
|
- Pre-publish definition-of-done (`fui module validate` + `fui module outline` + `fui module simulate` + static `fui sp verify`) → `verification.md`
|
|
102
100
|
- UI broken, cause unknown — cheapest verification layer (symptom → layer; read BEFORE `--render`, reread after ≥2 renders without progress) → `verification.md` §"Pick the tier by SYMPTOM"
|
|
@@ -41,23 +41,25 @@ Prefer `f-*`; use `v-*` only when no FUI equivalent exists.
|
|
|
41
41
|
|
|
42
42
|
## Components needing JS/CSS imports
|
|
43
43
|
|
|
44
|
-
**When adding or removing
|
|
44
|
+
**Before using any built-in control, inspect `defaultControlAttr[control].import` in `scripts/component.js` for V2 or `scripts/component-3.0.js` for V3.** That ordered array is the source of truth for JS/CSS URLs. The table below is a quick reference, not an exhaustive list. When adding or removing a control with imports, run `fui import list` and add/remove the matching imports. Do not substitute a similar CDN URL without checking the selected framework's source.
|
|
45
45
|
|
|
46
46
|
| Component | Required imports |
|
|
47
47
|
| ----------------- | -------------------------------------------------------------------------------------------------------- |
|
|
48
48
|
| `f-pdfmake` | `/include/pdfmake/pdfmake.min.js` · `/include/pdfmake/print.min.js` · `/include/pdfmake/vfs_fonts.js` |
|
|
49
49
|
| `f-file-upload` | `/include/plupload-2.3.7/plupload.full.min.js` |
|
|
50
|
-
| `f-image-update` | `/include/vue-advanced-cropper/index.umd.js` · `/include/vue-advanced-cropper/style.css`
|
|
50
|
+
| `f-image-update` | V2: `/include/vue-advanced-cropper/index.umd.js` · `/include/vue-advanced-cropper/style.css`; V3: use the two `unpkg.com/vue-advanced-cropper` URLs in `component-3.0.js` |
|
|
51
51
|
| `f-qrcode` | `/include/qrcode/qrcode.min.js` |
|
|
52
52
|
| `f-qrcode-reader` | `/include/qrcode/qrcode-reader.min.js` |
|
|
53
53
|
| `f-echart` | `/include/chart/echarts.min.js` · `/include/chart/fechart.js` (**in this order**) — Apache ECharts |
|
|
54
54
|
| `f-sheet` | `/include/ag-grid/ag-grid-community.min.js` · `/include/ag-grid/fsheet.js` (**in this order**) — AG Grid |
|
|
55
55
|
| `f-editor` | `/include/ckeditor5/build/ckeditor.js` |
|
|
56
56
|
| `f-editor-dialog` | `/include/ckeditor5/build/ckeditor.js` |
|
|
57
|
+
| `f-audio`, `f-audio-recorder` | `/include/audio/vueaudio.js` |
|
|
58
|
+
| `f-q-and-a`, `f-etest-review` | MathJax, Q&A CSS, context menu, audio and QandA.js; `f-q-and-a` also needs CKEditor and Plupload. V3 `f-q-and-a` additionally loads Sortable and vuedraggable. Read the complete ordered array in the matching `component*.js`. |
|
|
57
59
|
|
|
58
60
|
> **Bundled, NO import needed:** `v-*` (Vuetify) · `f-table` · `f-dialog` · `f-button` ·
|
|
59
61
|
> `f-date` · `f-time` · `f-search` · `f-menu` · `f-radiobox` · `f-box` · `f-label` · `f-header` ·
|
|
60
|
-
> `f-title` · `f-slider` · `f-excel-reader
|
|
62
|
+
> `f-title` · `f-slider` · `f-excel-reader`. Other components may also declare `import` in `defaultControlAttr`; check the source before assuming none is needed.
|
|
61
63
|
|
|
62
64
|
**Workflow when adding a component with imports** (see `fui import --help`):
|
|
63
65
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Owns: **table design rules: naming, PK/FK, audit columns, data types**. Connection/SP workflow: [db-workflow.md](db-workflow.md). Load when designing a new schema.
|
|
4
4
|
|
|
5
|
-
> **DDL — structure changes OK, data loss not:** `ALTER TABLE ... ADD` (column/constraint) and `DROP
|
|
5
|
+
> **DDL — structure changes OK, data loss not:** `ALTER TABLE ... ADD` (column/constraint), `DROP CONSTRAINT`, and `DROP TABLE #name` for one local temporary table run directly via fui. `ALTER COLUMN` (type change) runs but **needs `--confirm-write`** — narrowing numeric/time precision silently loses data. `CREATE TABLE`, `DROP COLUMN`, and dropping persistent or global (`##name`) tables are **hard-blocked**; the developer runs them. Conventions below are documentation — present DDL to the user for approval before running.
|
|
6
6
|
>
|
|
7
7
|
> DB connection, dbToken, schema, SP workflow: [db-workflow.md](db-workflow.md). Multi-table/multi-module app design: [system-design.md](system-design.md).
|
|
8
8
|
|
|
@@ -33,7 +33,6 @@ One `_db/` subfolder PER connection. The folder name is a short, readable `conne
|
|
|
33
33
|
|
|
34
34
|
```json
|
|
35
35
|
{
|
|
36
|
-
"version": 2,
|
|
37
36
|
"default": "docs",
|
|
38
37
|
"connections": {
|
|
39
38
|
"docs": {
|
|
@@ -59,20 +58,19 @@ One `_db/` subfolder PER connection. The folder name is a short, readable `conne
|
|
|
59
58
|
|
|
60
59
|
| Field | Req | Meaning |
|
|
61
60
|
| ----------- | --- | ------------------------------------------------------------------ |
|
|
62
|
-
| `version` | ✅ | Always `2` for this layout |
|
|
63
61
|
| key | ✅ | `connectionName`, also the folder name (`docs`, `docs_lhbs`) |
|
|
64
62
|
| `apiName` | ✅ | tAPI alias in `"API": "/{apiName}/Ten"`; may repeat across zones |
|
|
65
63
|
| `apiDomain` | ✅ | Host only, NO alias, NO trailing `/` (`api.example3.vn`) |
|
|
66
64
|
| `sqlServer` | ✅ | SQL Server host; with `database`, identifies the physical database |
|
|
67
65
|
| `database` | ✅ | Database name; with `sqlServer`, prevents duplicate connections |
|
|
68
66
|
| `dbToken` | ✅ | Base64 SQL Server connection string |
|
|
69
|
-
| `userToken` | ❌ | Bearer
|
|
67
|
+
| `userToken` | ❌ | Bearer for `acc` management lookup and end-user `spAPI_*` calls; never a SQL credential |
|
|
70
68
|
|
|
71
69
|
Without `--sql-server`/`--database`, `fui db add` reads both from the connection string in the token.
|
|
72
70
|
|
|
73
71
|
**Naming:** pass `--name <connectionName>` for a specific name. Omitted, fui suggests `apiName` first; if taken, adds the zone from `apiDomain` (`docs` → `docs_lhbs`); still taken, adds the database and a number. Names take letters, digits, `.`, `_`, `-` and are lowercased. The same server + database added again keeps its existing name.
|
|
74
72
|
|
|
75
|
-
**
|
|
73
|
+
**Older files, no folder moves:** a record without `apiName` reads as `apiName = connectionName = key`. A legacy `"version": 2` marker is accepted. On first read, fui normalizes the file without a version field (old file kept in `_history/`). It never renames old SQL folders.
|
|
76
74
|
|
|
77
75
|
> **CRITICAL — `apiDomain` has two meanings:** `_connections.json` → bare host (`api.example3.vn`); `project.json` `data.apiDomain` → full base URL with apiName + trailing `/` (`https://tapi.example.vn/acc/`). Top bug: bare host + apiName without `/` → `tapi.lhu.edu.vnts` instead of `tapi.lhu.edu.vn/ts`. See [tapi-reference.md](tapi-reference.md) §3. Don't build URLs; copy the `url (reference only, not called; copy verbatim)` line from `fui sp verify`/`fui sp help`.
|
|
78
76
|
|
|
@@ -107,11 +105,12 @@ Without `--sql-server`/`--database`, `fui db add` reads both from the connection
|
|
|
107
105
|
Never extract UID/PWD by hand (PowerShell etc.) — exposes credentials.
|
|
108
106
|
|
|
109
107
|
1. `fui db alias list` — no args: tAPI injects `@sys_UserID` from the Bearer token, so `SM_Modules_ManagerSelect` returns only DBs you're granted. Columns `APIName | SQLServer | DatabaseName | ModuleName | Enable`; `--search` filters client-side (APIName/DatabaseName/ModuleName, case-insensitive).
|
|
110
|
-
2. `fui db add-by-name <apiName>` — looks up SQLServer/DatabaseName on acc → borrows the UID/PWD pair of an existing connection → builds dbToken → tests `SELECT 1` before saving anything → saves + fetches schema to `_db/{connectionName}/`. Never prints dbToken/UID/PWD.
|
|
108
|
+
2. `fui db add-by-name <apiName>` — looks up SQLServer/DatabaseName on acc → borrows the UID/PWD pair of an existing connection, or takes `--uid <login> --pwd -` / `--pwd-env VAR` → builds dbToken → tests `SELECT 1` before saving anything → saves + fetches schema to `_db/{connectionName}/`. Never prints dbToken/UID/PWD.
|
|
111
109
|
|
|
112
|
-
-
|
|
110
|
+
- Reuse the UID/PWD pair from a saved connection; target SQLServer and DatabaseName come from `acc` and may differ from the source. Prefer sources on the same apiDomain; if none exist, a unique login elsewhere in the workspace is tried against the target DB. Several different logins → menu; pass `--borrow-from <projectId>/<connectionName>`. Credentials are never printed.
|
|
113
111
|
- "apiName not found" = alias doesn't exist OR you're not granted it. Don't assume a typo; run `fui db alias list`.
|
|
114
|
-
-
|
|
112
|
+
- A project with no connection can use apiDomain from local `project.json`. A project whose connection lacks userToken can use that connection's apiDomain. In either case fui looks for a token on the exact API host first, then another host in the same SSO zone (auto only if one distinct token; otherwise use `--user-token-from <project/connectionName>`). Else pass `--api-domain` + `--user-token-env VAR`.
|
|
113
|
+
- `userToken` authorizes only the `acc` lookup. It cannot become a `dbToken` or reveal a SQL password. If no saved dbToken contains a usable SQL login, supply the SQL login and password through `add-by-name`, or supply a dbToken through `fui db add`.
|
|
115
114
|
|
|
116
115
|
> ⚠️ `Password` in `SM_Modules_ManagerSelect` is a tAPI internal hash, not the SQL password — unusable for dbToken. fui never prints it.
|
|
117
116
|
|
|
@@ -127,7 +126,7 @@ Never extract UID/PWD by hand (PowerShell etc.) — exposes credentials.
|
|
|
127
126
|
5. Module uses other aliases? Repeat 4 per alias. Added connections do NOT become default (use --default).
|
|
128
127
|
```
|
|
129
128
|
|
|
130
|
-
Already have a dbToken → skip 3–4, use `fui db add`.
|
|
129
|
+
Already have a dbToken → skip 3–4, use `fui db add`. Already connected → skip discovery and use `--db <project/connectionName>` for schema, SQL, SP and API design.
|
|
131
130
|
|
|
132
131
|
## 3. Building a dbToken
|
|
133
132
|
|
|
@@ -178,19 +177,19 @@ UID/PWD changed, Server/Database unchanged:
|
|
|
178
177
|
|
|
179
178
|
```
|
|
180
179
|
dbToken → SQL Server connection to run schema/SP
|
|
181
|
-
userToken → call tAPI REST API as an end-user
|
|
180
|
+
userToken → discover managed aliases through acc, or call tAPI REST API as an end-user
|
|
182
181
|
```
|
|
183
182
|
|
|
184
|
-
- Shareable across projects
|
|
183
|
+
- Shareable across projects in the same SSO zone: `fui db user-token --db <connectionName> --from <project/connectionName>` copies a specific token without exposing its value. `fui db user-token` with no source lists workspace tokens. `GroupName` alone does not prove that two projects share an SSO zone.
|
|
185
184
|
- Stored PER CONNECTION in `_connections.json`. Multi-DB → one token per connection; pass `--db <connectionName>` (omitted → default).
|
|
186
|
-
- `fui right …` calls `acc` with the userToken of the connection matching the current apiName (else default);
|
|
185
|
+
- `fui right …` calls `acc` with the userToken of the connection matching the current apiName (else default); if absent, fui searches saved tokens in the same SSO zone.
|
|
187
186
|
- Not set at `fui db add` → `fui db user-token --db <connectionName> --token -`.
|
|
188
187
|
|
|
189
188
|
## 6a. Domain SSO — same parent domain: token works, don't ask
|
|
190
189
|
|
|
191
190
|
SSO is by parent domain: all APIs under e.g. `*.lhu.edu.vn` (`tapi.lhu.edu.vn`, `api.lhu.edu.vn`, `capnhatluong.lhu.edu.vn`…) accept the same `userToken`.
|
|
192
191
|
|
|
193
|
-
- Have a token for that parent domain → use it for other projects/aliases there. Do
|
|
192
|
+
- Have a token for that parent domain → use it for other projects/aliases there. Fui prefers an exact API host match, then a unique token from the zone. If several distinct tokens qualify, use `--user-token-from <project/connectionName>` for the `acc` lookup. Do not ask the user to log in again when the right token is already saved.
|
|
194
193
|
- Scanning the workspace for tokens (`fui db user-token` without a token) is valid and recommended.
|
|
195
194
|
|
|
196
195
|
| Case | Action |
|
|
@@ -248,7 +247,7 @@ Prints `📋 Archived orphaned local SP file(s)...` when archiving. Name match i
|
|
|
248
247
|
- `--db` omitted → inferred from SP name (schema + local `.sql` per connection). One match → silent; zero or several (same name in two DBs) → connection menu, pick and re-run, don't guess.
|
|
249
248
|
- `fui sp save` for a brand-new SP can't infer: multi-connection projects must pass `--db` on first save.
|
|
250
249
|
|
|
251
|
-
> `fui sp verify` reads the real body, not the name; hard error if unreadable. Write-API testing with `fui module simulate`: [tools-registry.md](tools-registry.md). Guards on `DROP TABLE
|
|
250
|
+
> `fui sp verify` reads the real body, not the name; hard error if unreadable. Write-API testing with `fui module simulate`: [tools-registry.md](tools-registry.md). Guards on persistent/global `DROP TABLE` (a single local `#name` temporary table is allowed), `DROP DATABASE`/`ALTER TABLE`, `xp_cmdshell`, `DELETE`/`UPDATE` without `WHERE` are enforced in code, no bypass. `sp deploy` also refuses a file that is not exactly one definition of the named object. Writes via `fui query`/`fui exec` need `--confirm-write`.
|
|
252
251
|
|
|
253
252
|
**Rollback:** read `{workspace}/_history/{projectId}/_db/{connectionName}/{name}_{timestamp}.sql` → `fui sp save <name> -f <old file>` → `fui sp deploy <name>`.
|
|
254
253
|
|
|
@@ -285,6 +284,7 @@ EXEC XDATA23.Calendar2015.dbo.spIO_IN_DeleteMonHocInfo @MonHocID, @ErrorDKMH OUT
|
|
|
285
284
|
| Alias only, no dbToken | `fui db alias list` → `fui db add-by-name` |
|
|
286
285
|
| Which DBs am I granted | `fui db alias list` |
|
|
287
286
|
| Another DB (new alias) | `fui db add-by-name` again |
|
|
287
|
+
| Remove one local connection | `fui db remove <project>/<connectionName>`; server alias and cached schema/SQL files remain |
|
|
288
288
|
| Connections + default | `fui db list` |
|
|
289
289
|
| UID/PWD changed | `fui db token-rebuild` (`--db` if several) |
|
|
290
290
|
| Set userToken | `fui db user-token` (`--db` if several) |
|
|
@@ -26,27 +26,27 @@ Session for **one project** → `{workspaceRoot}/{projectId}`; general work →
|
|
|
26
26
|
**Windows (PowerShell)** — most common:
|
|
27
27
|
|
|
28
28
|
```powershell
|
|
29
|
-
powershell -Command "Start-Process powershell -ArgumentList '-NoExit', '-Command', 'cd ''<THƯ-MỤC>''; claude --rc'"
|
|
29
|
+
powershell -Command "Start-Process powershell -ArgumentList '-NoExit', '-Command', 'Remove-Item Env:\CLAUDE_CODE_CHILD_SESSION -ErrorAction SilentlyContinue; cd ''<THƯ-MỤC>''; claude --rc'"
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
**macOS
|
|
32
|
+
**macOS** (by analogy, not yet verified on a Mac — see §4):
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
osascript -e 'tell app "Terminal" to do script "cd \"<THƯ-MỤC>\" && claude --rc"'
|
|
35
|
+
osascript -e 'tell app "Terminal" to do script "unset CLAUDE_CODE_CHILD_SESSION; cd \"<THƯ-MỤC>\" && claude --rc"'
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
**Linux** (swap `gnome-terminal` for the terminal in use):
|
|
38
|
+
**Linux** (swap `gnome-terminal` for the terminal in use; not yet verified):
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
gnome-terminal -- bash -c 'cd "<THƯ-MỤC>" && claude --rc; exec bash'
|
|
41
|
+
gnome-terminal -- bash -c 'unset CLAUDE_CODE_CHILD_SESSION; cd "<THƯ-MỤC>" && claude --rc; exec bash'
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Team default is **`claude --rc`**. If the user gives other flags (`-c`, `-r`, `--resume <id>`…), substitute them.
|
|
45
45
|
|
|
46
|
-
**With an opening prompt ("open a new session and do X") → the prompt goes BEFORE `--rc`, not after.** `--rc` consumes the token right after it as its own value (see the warning in §4)
|
|
46
|
+
**With an opening prompt ("open a new session and do X") → the prompt goes BEFORE `--rc`, not after.** `--rc` consumes the token right after it as its own value (see the warning in §4), so placing it first opens an idle session instead of running the prompt. Correct order:
|
|
47
47
|
|
|
48
48
|
```powershell
|
|
49
|
-
powershell -Command "Start-Process powershell -ArgumentList '-NoExit', '-Command', 'cd ''<THƯ-MỤC>''; claude ''X'' --rc'"
|
|
49
|
+
powershell -Command "Start-Process powershell -ArgumentList '-NoExit', '-Command', 'Remove-Item Env:\CLAUDE_CODE_CHILD_SESSION -ErrorAction SilentlyContinue; cd ''<THƯ-MỤC>''; claude ''X'' --rc'"
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
---
|
|
@@ -80,26 +80,30 @@ Report **PID + folder**. No new process ⇒ say it failed; **never report succes
|
|
|
80
80
|
|
|
81
81
|
**Windows: go through `powershell`.** `claude` is usually `claude.ps1` (not `.exe`), so `cmd` can't run it.
|
|
82
82
|
|
|
83
|
+
**🔴 Clear `CLAUDE_CODE_CHILD_SESSION` first, before `cd` — otherwise the new session can never be resumed.** The session running this command carries `CLAUDE_CODE_CHILD_SESSION=1`, and `Start-Process` / `osascript` / `bash -c` inherit the parent environment. The new `claude` sees the marker, treats itself as a child session and **turns transcript saving off**: it works normally but never appears in `claude --resume` (not even with Ctrl+A / all folders), however it is closed. A window the user opens by hand has no such variable, which is the only difference — not the folder, not how the window was closed. Verified on Windows (2026-10-17): the status line "Transcript saving is off — inherited CLAUDE_CODE_CHILD_SESSION marker" disappears once `Remove-Item Env:\CLAUDE_CODE_CHILD_SESSION -ErrorAction SilentlyContinue;` runs first.
|
|
84
|
+
|
|
85
|
+
> In auto mode, the classifier **blocks this command the first time** ("Auto-Mode Bypass"). It goes through once the user has this allow rule in `~/.claude/settings.json` (verified — not a hard deny):
|
|
86
|
+
> ```json
|
|
87
|
+
> "permissions": {
|
|
88
|
+
> "allow": [
|
|
89
|
+
> "PowerShell(Start-Process powershell -ArgumentList '-NoExit', '-Command', 'Remove-Item Env:\\CLAUDE_CODE_CHILD_SESSION*)"
|
|
90
|
+
> ]
|
|
91
|
+
> }
|
|
92
|
+
> ```
|
|
93
|
+
> The rule is per machine (it does not ship with the skill). If it is missing and the command is blocked, tell the user to add it. **Do not route around the block, and do not drop the `Remove-Item` step to get past it** — that brings back the unresumable session.
|
|
94
|
+
>
|
|
95
|
+
> **Offer to add the rule yourself.** After the block, explain in one or two sentences why the rule is needed (so the new session can be resumed, not to bypass oversight), then ask the user whether you should add it. Only on an explicit yes:
|
|
96
|
+
> 1. Read `~/.claude/settings.json` first; create it only if it does not exist.
|
|
97
|
+
> 2. Append the rule to `permissions.allow`, keeping every existing entry (merge, never replace the array).
|
|
98
|
+
> 3. The rule must end with `*)` — a missing `)` fails settings validation ("Malformed Tool(content) rule").
|
|
99
|
+
> 4. Retry the open command once. If it is still blocked, stop and tell the user; do not try other variants.
|
|
100
|
+
>
|
|
101
|
+
> Never add the rule without the user's yes, and never add it pre-emptively before a block has actually happened.
|
|
102
|
+
|
|
83
103
|
---
|
|
84
104
|
|
|
85
105
|
## 5. The new session is an INDEPENDENT process
|
|
86
106
|
|
|
87
107
|
- **Own session state**: active module target, skill-loaded mark, publish approval and verified-SP list are separate; fui keeps one state file per Claude Code session (or per `FUI_SESSION` when it is set). The new session must run `fui skill get` and `fui use` itself.
|
|
88
|
-
- **You cannot type into that window
|
|
108
|
+
- **You cannot type into that window from this session.** The user owns and controls the new window directly.
|
|
89
109
|
- **Permissions are per session.** Never ask another session to run an action blocked here — that routes around the user's decision.
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## 6. Coordinating sessions — hand out work, not just talk
|
|
94
|
-
|
|
95
|
-
`ListAgents`/`SendMessage` are Claude Code's own tools (not fui commands) and are **always available in every session**; nothing to enable. Together with §1-5 (open a session, name it, know it is independent), this is how to build a multi-AI workflow: one **coordinator** session opens sessions and hands work to several **worker** sessions, each owning a separate piece (a module, a chart, a DB connection...), the "parallelize" model of [system-design.md](system-design.md) §Step 5 for multi-module systems.
|
|
96
|
-
|
|
97
|
-
**Mechanics:**
|
|
98
|
-
|
|
99
|
-
1. **`ListAgents`** lists every running session (including the ones opened with §2), shown by the `X` given at `claude "X" --rc`. Give meaningful names when opening (per module/chart/task) so the list stays readable when coordinating several sessions.
|
|
100
|
-
2. **`SendMessage({ to: "<session name>", message: "..." })`** is an **instruction**, not a check-in. The receiving session **cannot see your conversation**, so the message must stand alone: state the project/module/connection and the exact work, as when briefing a colleague who just joined, never as a follow-up to something said earlier.
|
|
101
|
-
3. **Asynchronous**: the receiver handles it on its next tool turn and may be idle or busy. To know when it finishes: `notify_when_idle: true` (once, no polling); do not `SendMessage` it again and again to poll.
|
|
102
|
-
4. **Results/replies from the other session** arrive wrapped in `<cross-session-message from="...">`. Treat them as a colleague's request: act within the permissions of **the receiving session**, never widen permissions because the message came from another session. To reply, `to` = that exact `from` value.
|
|
103
|
-
5. **Permissions stay per session** (§5 again): FUI has real writes (`fui exec`, `fui sp deploy`, `fui module publish *`...). **Never** ask another session to run an action the user just refused or blocked here, and if another session says "I'm blocked, do it for me", **refuse** and tell the user instead of doing it.
|
|
104
|
-
|
|
105
|
-
**Example:** the coordinator opens 3 sessions with §2 (`claude "Module A" --rc`, `claude "Module B" --rc`, `claude "Module C" --rc`), all in the same workspace; `SendMessage` gives each exactly one module and a concrete request; each session runs `fui skill get` → edits files → publishes as a normal task, then `SendMessage`s the result back to the coordinator.
|
|
@@ -75,7 +75,7 @@ numeral(value).format("0,0.0"); // 1,234,567.8
|
|
|
75
75
|
numeral(_.sumBy(items, key)).format("0,0"); // tổng cột trong bảng
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
> `f-*`
|
|
78
|
+
> Before using any `f-*` control, check `defaultControlAttr[control].import` in the matching V2/V3 `component*.js` file. Its ordered URLs determine required JS/CSS; [component-quickref.md](component-quickref.md) is a quick reference.
|
|
79
79
|
|
|
80
80
|
## 1) scripts/fastproject.js — V3: fastproject-3.0.js
|
|
81
81
|
|
|
@@ -36,7 +36,7 @@ Before any module.json:
|
|
|
36
36
|
|
|
37
37
|
1. Tables + PK + FK for **all** entities. Per [db-table-design.md](db-table-design.md): `tbl` + PascalCase, PK `[Entity]ID`, audit `CreateUser/CreateTime/UpdateUser/UpdateTime`.
|
|
38
38
|
2. n-n → junction table (e.g. `tblUserRole`).
|
|
39
|
-
3. **`CREATE TABLE` is run by the developer** — fui has no guard for it, so do not run it yourself; present DDL for review. Existing tables, gated by data loss: `ALTER TABLE ... ADD` and `DROP
|
|
39
|
+
3. **`CREATE TABLE` is run by the developer** — fui has no guard for it, so do not run it yourself; present DDL for review. Existing tables, gated by data loss: `ALTER TABLE ... ADD`, `DROP CONSTRAINT`, and `DROP TABLE #name` for a local temporary table run directly; `ALTER COLUMN` needs `--confirm-write`; `DROP COLUMN`/persistent or global `DROP TABLE`/`SWITCH` hard-blocked.
|
|
40
40
|
4. Design lookup/catalog tables early (shared dropdowns).
|
|
41
41
|
|
|
42
42
|
**Output:** tables + relations, user-confirmed.
|
|
@@ -74,7 +74,7 @@ A code exists only as a row in the project's `acc.tblSysRight`/`acc.tblFunction`
|
|
|
74
74
|
5. **Dependent modules** (reports, dashboards) once data exists.
|
|
75
75
|
6. **Menu + shared components** last.
|
|
76
76
|
|
|
77
|
-
Once the shared infrastructure (schema, rights
|
|
77
|
+
Once the shared infrastructure (schema, rights and shared components) is settled in Steps 0-4b, build independent modules one at a time in the same session. Keep the established convention and finish each module's checks before moving to the next one.
|
|
78
78
|
|
|
79
79
|
Each module: full [fullstack-workflow.md](fullstack-workflow.md) — analyze → **Design Review Gate (§Step 1b)** → hard-coded UI → contract → SP → API wiring → static verification.
|
|
80
80
|
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
Two axes per command:
|
|
6
6
|
|
|
7
7
|
- `R` reads only (touches no byte on disk) / `M` writes the server **or the local workspace**. A command that "only fetches" still **overwrites local files**, which is how unpublished edits get lost; the old copy goes to `_history/` first.
|
|
8
|
-
- ✅ Safe: run freely · ⚠️
|
|
8
|
+
- ✅ Safe: run freely · ⚠️ Scoped mutation: run when it completes the user's requested module work, otherwise summarize and wait · 🔴 Destructive: full summary, then an explicit yes.
|
|
9
9
|
|
|
10
|
-
**Default:**
|
|
10
|
+
**Default:** judge authorization from the user's requested outcome, not only from the command. A request to create, design, fix or update a module authorizes the module's required create/publish/deploy commands after verification. Ask separately for mutations outside that scope, destructive operations and real-data writes. **Per call:** judge the actual input; the same command can be safe or not.
|
|
11
|
+
|
|
12
|
+
If the developer said **do not upload**, **local only**, **draft**, **preview first**, or equivalent, no server-changing module command is authorized until they explicitly approve it later. This instruction overrides the normal completion rule.
|
|
11
13
|
|
|
12
14
|
**Strict mode (`FUI_STRICT=1`)**, for runs nobody reviews step by step: `module publish json|html|script|css`, `component new|update`, `project publish-config` and `sp deploy` are **blocked** until the skill was loaded this session (`fui skill get` / `fui skill ref`), and validator **errors block** publishing module.json. Without it both are warnings.
|
|
13
15
|
|
|
@@ -51,7 +53,7 @@ Users name commands loosely, often in Vietnamese.
|
|
|
51
53
|
| "let someone edit this project" / "cấp quyền admin project", "thêm người vào project" | `fui user search` → `fui user add` |
|
|
52
54
|
| "who can edit this project" / "ai được sửa project này" | `fui user list` |
|
|
53
55
|
| "update project.json", "edit the project menu" / "sửa menu project" | edit `{projectId}/project.json`, then `fui project publish-config` |
|
|
54
|
-
| "connect the DB but I only know the alias" / "không có dbToken" | `fui db alias list` → `fui db add-by-name`
|
|
56
|
+
| "connect the DB but I only know the alias" / "không có dbToken" | `fui db list` → `fui db alias list` → `fui db add-by-name`; if no saved SQL login, supply `--uid` and `--pwd -` / `--pwd-env` |
|
|
55
57
|
| "sync / refresh the project" / "đồng bộ project", "lấy project.json" | `fui project sync` |
|
|
56
58
|
| "get / pull / clone / refresh the module" / "lấy module về", "pull mới nhất" | `fui module get` |
|
|
57
59
|
| "new module" / "tạo module mới" | `fui module new` |
|
|
@@ -77,7 +79,7 @@ Users name commands loosely, often in Vietnamese.
|
|
|
77
79
|
| "DB password changed" / "đổi password DB", "rebuild dbToken" | `fui db token-rebuild` |
|
|
78
80
|
| "which DBs does this project use" / "project này đang nối những DB nào" | `fui db list` |
|
|
79
81
|
| "connect one more database" / "nối thêm một database nữa" | `fui db add` again with the new apiName |
|
|
80
|
-
| **"sync the db", "refresh schema"** / **"đồng bộ db", "cập nhật schema", "làm mới schema"** | `fui
|
|
82
|
+
| **"sync the db", "refresh schema"** / **"đồng bộ db", "cập nhật schema", "làm mới schema"** | `fui db list` → existing `--db`: `fui schema pull`. No connection: `fui db alias list` → `fui db add-by-name` (automatically fetches schema) |
|
|
81
83
|
| "list designs" / "có style nào" · "use style X" / "dùng style X" | `fui design list` · `fui design read <brand>` |
|
|
82
84
|
|
|
83
85
|
## Commands
|
|
@@ -150,6 +152,7 @@ Scope, for every component command:
|
|
|
150
152
|
| `db list`, `db test`, `token decode` | R | ✅ | never print secrets |
|
|
151
153
|
| `db alias list` | R | ✅ | databases your token may manage on `acc`; run it when an alias is unknown or `db add-by-name` finds nothing |
|
|
152
154
|
| `db add`, `db add-by-name` | M | ✅ | test, save, fetch the schema. `add-by-name` borrows a SQL login from a connection on the same `apiDomain`; "not found" means the alias does not exist **or** you may not manage it |
|
|
155
|
+
| `db remove <project>/<connectionName>` | M | ⚠️ | removes only the named local connection and updates the default; server alias and cached `_db/<connectionName>/` files remain |
|
|
153
156
|
| `db user-token`, `db default`, `db migrate` | M | ✅ | local only |
|
|
154
157
|
| `db token-rebuild` | M | ⚠️ | overwrites the stored token; `--db` is required when the project has several connections |
|
|
155
158
|
| `db alias new` | M | ⚠️ | registers an existing database as a tAPI alias on `acc`; the login must be the **application** account (execute-only), never a `db_owner` dev login. Ask the user first |
|
|
@@ -160,7 +163,8 @@ Scope, for every component command:
|
|
|
160
163
|
| `sp rename` | M | ⚠️ | renames on the server and the local file; summarize first |
|
|
161
164
|
| `query` | R/M | ⚠️ | reads and, on the user's request, writes real data. Default cap 200 rows; `TOP 20` to look at structure; no `varbinary(max)`/large `nvarchar(max)` columns |
|
|
162
165
|
| `exec` | R/M | 🔴 | DDL/DML. A `CREATE`/`ALTER PROCEDURE` here gets **no auto-grant and no cache clear**; the output names the command to run next |
|
|
163
|
-
| `sp deploy
|
|
166
|
+
| `sp deploy` | M | ⚠️ | authorized when the SP is part of the requested module work; saves the live definition to `_history/`, fixes CREATE/ALTER, grants and clears the tAPI cache |
|
|
167
|
+
| `sp delete` | M | 🔴 | permanent; always requires explicit approval for the exact SP |
|
|
164
168
|
| `right system list`, `right function list` | R | ✅ | read `acc` and refresh `{projectId}/_db/rights.json`; **until they ran once, validate/simulate/render cannot check right codes** |
|
|
165
169
|
| `right system new/update`, `right function new/update` | M | ⚠️ | create and edit are separate; `update` needs the id from `list` |
|
|
166
170
|
| `right system delete`, `right function delete` | M | 🔴 | `function delete` also removes every user assignment of that code |
|
|
@@ -185,7 +189,7 @@ Guarding with a right code that is not defined fails silently: `rightTest()` is
|
|
|
185
189
|
|
|
186
190
|
- Before publishing module.json: `fui module validate`, fix every error, then `fui module outline` (row widths, dialogs nobody opens, actions nobody calls). For complex runtime logic (action chains, watch cascades, dialog flows) also `fui module simulate` the main flow with asserts.
|
|
187
191
|
- Only `module.json` → `fui module publish json` (no preview needed).
|
|
188
|
-
- `header.html` / `body.html` / title (with or without module.json) → `fui module preview`,
|
|
192
|
+
- `header.html` / `body.html` / title (with or without module.json) → `fui module preview`, review the diff yourself, then `fui module publish html --approval <token>`. It pushes module.json too. A separate approval turn is unnecessary when this publish completes the requested module work; stop if the developer previously asked not to upload or to review first.
|
|
189
193
|
- `script.js` (also to clear it) → `fui module publish script`. `module publish json` does not push it.
|
|
190
194
|
- `style.css` (also to clear it) → `fui module publish css`.
|
|
191
195
|
- `uc-*.vue` → `fui component new <name>` the first time, `fui component update <name>` after. A **project-scope** component must be previewed and pushed **before** rendering a module that uses it: `--render` hard-blocks when the local file differs from the server.
|
|
@@ -196,7 +200,7 @@ Guarding with a right code that is not defined fails silently: `rightTest()` is
|
|
|
196
200
|
## Database rules (enforced in code)
|
|
197
201
|
|
|
198
202
|
- `query` / `exec`: say what the SQL does and what data it touches, and wait for the user. Writes (INSERT, UPDATE…SET, DELETE, MERGE, TRUNCATE, `SELECT … INTO` a real table, a write inside `EXEC('…')` or `sp_executesql`, `DROP PROCEDURE`/`FUNCTION`/`VIEW`, ALTER COLUMN) exit 3 until `--confirm-write`, added only after the user approved that exact write. It is a confirmation gate, not an obstacle to work around.
|
|
199
|
-
- Table DDL is judged by data loss, **per statement**: free `ALTER TABLE … ADD` and `DROP
|
|
203
|
+
- Table DDL is judged by data loss, **per statement**: free `ALTER TABLE … ADD`, `DROP CONSTRAINT`, and `DROP TABLE #name` for one local temporary table · `--confirm-write` for `ALTER COLUMN` (narrowing numeric or date precision loses data silently) · always blocked `DROP TABLE` on persistent or global (`##name`) tables, mixed drop lists, `DROP DATABASE`, `DROP COLUMN`, `SWITCH`, `xp_cmdshell` and any action fui cannot parse. A blocked statement wins over a confirmable one. `DELETE`/`UPDATE` without `WHERE` is blocked too, in `query` and `exec` (a `MERGE` is scoped by its `ON`). A `--` or a quote inside a `[name]` or `"name"` does not hide the statements after it. Show blocked SQL for the user to run by hand; no flag unlocks it.
|
|
200
204
|
- 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>`. `sp verify` calls no endpoint; its only network reads are metadata (`OBJECT_DEFINITION` when no local `.sql`, permissions with `--check-grant`). An unreadable body is a hard error: it never guesses from the name.
|
|
201
205
|
- `--mocks` for an SP that **exists** must be the snippet `fui sp verify` prints, never a guessed shape. On `🚨 UNVERIFIED MOCK SHAPE` stop, run `fui sp verify`, copy the snippet. Invented data is right only for an SP that does not exist yet.
|
|
202
206
|
- `fui sp deploy` asks the server whether the object exists, so `CREATE PROCEDURE` for an existing SP is fine: do not edit the file to `ALTER` and redeploy. tAPI parameters with a default value are hard-blocked.
|
|
@@ -124,12 +124,12 @@ Tiers differ ~100× in cost per run:
|
|
|
124
124
|
### Publish — only what changed
|
|
125
125
|
|
|
126
126
|
- [ ] Only `module.json` → `fui module publish json` (no preview/approval)
|
|
127
|
-
- [ ] `header.html` / `body.html` / title → `fui module preview` →
|
|
127
|
+
- [ ] `header.html` / `body.html` / title → `fui module preview` → self-review the diff → `fui module publish html --approval <token>` (includes module.json); wait only when the developer previously said not to upload or requested review first
|
|
128
128
|
- [ ] `script.js` (even emptied) → `fui module publish script` — **⚠️ `publish html` does not clear an empty script on the server**
|
|
129
129
|
- [ ] `uc-*.vue` → `fui component new` (first) / `fui component update` (later), per file — `update` hard-errors if absent on server, never creates
|
|
130
130
|
- [ ] Several parts → one command each, in turn
|
|
131
131
|
|
|
132
|
-
For `fui module publish html`: preview ran and diff reviewed ·
|
|
132
|
+
For `fui module publish html`: preview ran and diff reviewed · upload is authorized by the module request · approval token in hand. If the developer requested local-only or review-first work, explicit later confirmation replaces the standing authorization.
|
|
133
133
|
|
|
134
134
|
---
|
|
135
135
|
|
|
@@ -165,7 +165,7 @@ For `fui module publish html`: preview ran and diff reviewed · user explicitly
|
|
|
165
165
|
- [ ] `fui sp save` first (local only)
|
|
166
166
|
- [ ] Full body reviewed in the local file
|
|
167
167
|
- [ ] Summary to user: SP name, CREATE/ALTER, affected tables
|
|
168
|
-
- [ ]
|
|
168
|
+
- [ ] The SP belongs to the requested module work and all static checks passed, or the developer explicitly approved a previously paused/local-only deployment
|
|
169
169
|
- [ ] Any API (read or write) about to be wired into module.json → `fui sp verify` once: static shape/error contract + param check, **no endpoint call** (metadata reads only, as above)
|
|
170
170
|
- [ ] **Write** APIs: verify by reading the body (`fui sp get`/`fui sp verify`) — WHERE, transaction, RAISERROR; test the UI flow with `fui module simulate --mocks '{...}'` (snippet from `fui sp verify`), never the real API
|
|
171
171
|
|
|
@@ -227,10 +227,10 @@ Before any mutating command:
|
|
|
227
227
|
|
|
228
228
|
| Question | If NO → |
|
|
229
229
|
| ------------------------------------------ | ------------------------------ |
|
|
230
|
-
| Read-only
|
|
231
|
-
|
|
|
232
|
-
| 🔴 Destructive?
|
|
230
|
+
| Read-only or in current module scope? | Continue after checks |
|
|
231
|
+
| Unrelated server mutation? | Confirm intent with user |
|
|
232
|
+
| 🔴 Destructive or real-data write? | Require explicit confirmation |
|
|
233
233
|
| `fui module publish html`: approval token? | Run `fui module preview` first |
|
|
234
|
-
| `fui sp deploy`:
|
|
234
|
+
| `fui sp deploy`: in current module scope? | Deploy after static checks |
|
|
235
235
|
|
|
236
236
|
Per-command classification: [tools-registry.md](tools-registry.md).
|