create-restforge-skills 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -7,55 +7,36 @@ CLI, and OpenAI Codex** — not only Claude Code.
7
7
 
8
8
  ## What this package is (and is not)
9
9
 
10
- This package is the **portable** distribution of RESTForge agent knowledge.
10
+ This package is the **only** distribution of RESTForge agent knowledge.
11
11
 
12
12
  - It contains pure Agent Skills: a `skills/restforge/SKILL.md` plus `references/`.
13
13
  - It has **no** client-specific packaging — no Claude Code `plugin.json`,
14
- `marketplace.json`, or `.mcp.json`.
14
+ `marketplace.json`, or `.mcp.json`. The installer (`create-restforge-skills`)
15
+ copies the skill into each client and registers the MCP server there.
15
16
 
16
- It is a **complement to**, not a replacement for, [`restforge-plugins`](../packages/restforge-plugins).
17
-
18
- | | `restforge-plugins` | `restforge-skills` (this package) |
19
- |---|---|---|
20
- | Target | Claude Code only | Claude Code, Cursor, Gemini CLI, Codex |
21
- | Distribution | Claude Code plugin + marketplace | Copy/symlink the skill folder into each client's skills directory |
22
- | MCP registration | Bundled (`.mcp.json`) | Done per client by the user (see below) |
23
- | Knowledge source | `skills/restforge-skills/` | Same knowledge, portable form |
24
-
25
- Both packages wrap the **same** workflow knowledge and depend on the **same**
26
- execution engine: the `@restforgejs/mcp-server` MCP server. A skill describes
27
- *how* to drive RESTForge; the MCP server is *what* actually executes the
28
- operations. The skill is useless without the MCP server registered in the client.
17
+ The skill depends on one execution engine: the `@restforgejs/mcp-server` MCP
18
+ server. A skill describes *how* to drive RESTForge; the MCP server is *what*
19
+ actually executes the operations. The skill is useless without the MCP server
20
+ registered in the client.
29
21
 
30
22
  ## Directory layout
31
23
 
32
24
  ```
33
25
  restforge-skills/
34
- ├── README.md ← this file
26
+ ├── README.md ← this file (end-user guide, published to npm)
35
27
  ├── package.json ← npm package: create-restforge-skills
36
- ├── bump-and-publish.bat ← version bump + npm publish
37
- ├── sync-to-plugin.bat ← mirror the skill into the Claude Code plugin
28
+ ├── *.bat ← maintainer scripts (see docs/DEVELOPMENT.md)
38
29
  ├── cli/
39
30
  │ ├── index.js ← installer that copies the skill into each client
40
31
  │ └── mcp.js ← merges the MCP server into each client config
41
- ├── docs/ ← internal docs, NOT published (excluded from npm files)
32
+ ├── docs/
33
+ │ └── DEVELOPMENT.md ← maintainer guide, NOT published (excluded from npm files)
42
34
  └── skills/
43
35
  └── restforge/
44
36
  ├── SKILL.md ← the portable skill (name + description + workflow)
45
37
  └── references/ ← progressive-disclosure reference material
46
38
  ```
47
39
 
48
- ## Single source of truth
49
-
50
- `skills/restforge/` here is the **one** authoritative copy of the skill. Two
51
- distribution channels consume it — do not edit the skill anywhere else:
52
-
53
- - **This package** (`create-restforge-skills`) — published to npm; cross-client.
54
- - **The Claude Code plugin** (`../packages/restforge-plugins`) — its
55
- `skills/restforge-skills/` folder is a **generated mirror**. After editing the
56
- canonical skill, run `sync-to-plugin.bat` to propagate, then commit the plugin
57
- repo. Hand-edits to the plugin's skill copy are overwritten on the next sync.
58
-
59
40
  ## Install
60
41
 
61
42
  One command. It detects your installed clients (Claude Code, Cursor), copies the
@@ -117,6 +98,19 @@ operations (Designer/frontend tools need no license). On Claude Code, if the
117
98
  skills directory was just created, restart the client so it watches the new
118
99
  directory.
119
100
 
101
+ ### Update
102
+
103
+ `npx` caches previously downloaded packages, so when updating always pin
104
+ `@latest` and pass `--force` to overwrite the installed skill folder:
105
+
106
+ ```bash
107
+ npx create-restforge-skills@latest --force
108
+ ```
109
+
110
+ If the machine already has the RESTForge MCP server registered the way you want
111
+ it (for example via a globally installed `restforge-mcp` binary), add `--no-mcp`
112
+ so the update touches only the skill and leaves the MCP config alone.
113
+
120
114
  ### Where it installs
121
115
 
122
116
  | Client | Scope | Skill | MCP config |
@@ -130,9 +124,6 @@ Note the asymmetry on the project row: Claude Code reads a project-scope MCP
130
124
  server from `./.mcp.json` in the repo root, so that is where the installer writes
131
125
  it — not into `./.claude/`.
132
126
 
133
- > For Claude Code, a turnkey alternative is the `restforge-plugins` package,
134
- > which bundles the skill **and** MCP registration in one `/plugin install`.
135
-
136
127
  ### Manual install (no CLI)
137
128
 
138
129
  The skill folder is self-contained — copy `skills/restforge/` (including
@@ -145,13 +136,12 @@ to the client's MCP config.
145
136
  Planned. Both consume the same `skills/restforge/` folder; only the skills
146
137
  directory path and MCP config file differ per client.
147
138
 
148
- ## Source of truth
139
+ ## Developing and releasing
149
140
 
150
- The knowledge in this skill mirrors the RESTForge handbook
151
- ([`restforge-handbook`](../restforge-handbook)) and the MCP tool surface
152
- ([`mcp-server`](../packages/mcp-server)). When RESTForge behavior changes, update the
153
- handbook first, then this skill — the skill is downstream documentation of real
154
- tool behavior, never an independent source.
141
+ Maintainer topics live in [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md): the
142
+ skill source, testing the skill from the working tree, the reference audit, the
143
+ release flow, and the extra care needed on machines that double as RESTForge
144
+ development machines. That guide is not published to npm.
155
145
 
156
146
  ## License
157
147
 
package/package.json CHANGED
@@ -1,30 +1,33 @@
1
- {
2
- "name": "create-restforge-skills",
3
- "version": "0.3.0",
4
- "description": "Install the RESTForge Agent Skill into Claude Code, Cursor, and other skills-compatible clients.",
5
- "type": "commonjs",
6
- "bin": {
7
- "create-restforge-skills": "cli/index.js"
8
- },
9
- "files": [
10
- "cli",
11
- "skills",
12
- "README.md"
13
- ],
14
- "engines": {
15
- "node": ">=18"
16
- },
17
- "keywords": [
18
- "restforge",
19
- "agent-skills",
20
- "skill",
21
- "claude-code",
22
- "cursor",
23
- "mcp"
24
- ],
25
- "author": {
26
- "name": "RESTForge",
27
- "url": "https://restforge.dev"
28
- },
29
- "license": "MIT"
30
- }
1
+ {
2
+ "name": "create-restforge-skills",
3
+ "version": "0.4.0",
4
+ "description": "Install the RESTForge Agent Skill into Claude Code, Cursor, and other skills-compatible clients.",
5
+ "type": "commonjs",
6
+ "bin": {
7
+ "create-restforge-skills": "cli/index.js"
8
+ },
9
+ "scripts": {
10
+ "audit-references": "node scripts/audit-references.js"
11
+ },
12
+ "files": [
13
+ "cli",
14
+ "skills",
15
+ "README.md"
16
+ ],
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "keywords": [
21
+ "restforge",
22
+ "agent-skills",
23
+ "skill",
24
+ "claude-code",
25
+ "cursor",
26
+ "mcp"
27
+ ],
28
+ "author": {
29
+ "name": "RESTForge",
30
+ "url": "https://restforge.dev"
31
+ },
32
+ "license": "MIT"
33
+ }
@@ -10,7 +10,7 @@ description: >
10
10
  active for the codegen_*, designer_*, setup_*, runtime_* MCP tools and the
11
11
  @restforgejs/platform / @restforgejs/mcp-server packages. Defines the canonical
12
12
  operation order for the backend track (setup → schema → payload → codegen →
13
- runtime) and the frontend track (init → udf → validate → generate), the
13
+ runtime) and the frontend track (migrate RDF → udf → validate → generate), the
14
14
  grounding-first catalog rules, decision branches, and destructive-operation
15
15
  guardrails. Active whenever working on a RESTForge project, not only when the
16
16
  word "skill" is mentioned.
@@ -146,6 +146,11 @@ earlier steps that already succeeded.
146
146
 
147
147
  8. codegen_dbschema_validate
148
148
  Validate SDF before any DDL is generated. Catch errors here, not at migrate.
149
+ File-only by default. With 'config' it also compares every model with the
150
+ database and gives one verdict per table: [OK], [DRIFT], or [ERROR] with
151
+ category table-missing or sdf-invalid. Exit code 1 in that mode is a
152
+ result (drift or error found), not a tool failure. SQLite is not
153
+ supported by the database mode.
149
154
  codegen_dbschema_models (optional) lists the models already defined in the
150
155
  SDF files with field count, primary key kind, indexes, uniques, relations.
151
156
 
@@ -166,19 +171,22 @@ earlier steps that already succeeded.
166
171
  Check the SELECT / WITH statement against the live database (EXPLAIN, no
167
172
  rows executed) BEFORE pasting it into the payload: syntax, column
168
173
  references, function existence, type compatibility, JOIN resolution.
169
- Needs a platform that provides the 'query validate' sub-command
170
- (confirmed present in 5.5.5).
171
174
 
172
175
  13. codegen_generate_payload
173
176
  Generate payload JSON from a table. Foundation for all subsequent
174
- codegen operations.
177
+ codegen operations. 'detail' (a detail table name) also writes the
178
+ masterDetail block, the detail query file, and the composite actions.
179
+ Re-running it on an existing payload keeps the customisations made to
180
+ generator-owned keys; commit payload/.meta/<name>.json together with the
181
+ payload (see Decision Points § RDF Payload).
175
182
 
176
183
  14. codegen_validate_payload
177
184
  Validate the payload before codegen. Catch errors here.
178
185
 
179
186
  15. codegen_diff_payload (when a payload exists and the DB schema has changed)
180
- → codegen_sync_payload (sync payload to the current DB state — non-breaking)
181
- → codegen_migrate_payload (when the payload has breaking changes)
187
+ → codegen_sync_payload (apply the schema drift to the payload)
188
+ 'expandFk' (with 'table') also writes query/<table>-join.sql so
189
+ datatablesQuery (and viewQuery) show columns of referenced tables.
182
190
 
183
191
  16a. codegen_create_endpoint (standard CRUD module)
184
192
  Leave 'database' UNSET unless the user named a database: the CLI then
@@ -186,16 +194,17 @@ earlier steps that already succeeded.
186
194
  MySQL/Oracle/SQLite project generates for its own dialect. 'config'
187
195
  selects that .env explicitly. createDemo (default true) writes the
188
196
  curl / Postman / Insomnia examples. force defaults to true — an existing
189
- module is overwritten and the previous version archived as .archive.NNN;
190
- force=false stops without writing anything when the module exists, which
191
- is the closest thing to a conflict dry run.
197
+ module is overwritten and the previous files are moved to
198
+ .restforge/archive/<run>/<original relative path> (the 5 most recent runs
199
+ are kept); force=false stops without writing anything when the module
200
+ exists, which is the closest thing to a conflict dry run.
192
201
  16b. codegen_get_dashboard_catalog
193
202
  → codegen_validate_dashboard_payload
194
203
  ── GATE ── structural check of a dashboard payload; writes nothing.
195
- Needs a platform NEWER than 5.5.5 ('dashboard create --validate-only').
196
- On an older platform the tool answers with an upgrade suggestion instead
197
- of a validation result — then let the generator itself validate, since it
198
- runs the same validator before it writes.
204
+ On a platform without 'dashboard create --validate-only' the tool
205
+ answers with an upgrade suggestion instead of a validation result — then
206
+ let the generator itself validate, since it runs the same validator
207
+ before it writes.
199
208
  → codegen_create_dashboard (analytic dashboard with SQL widgets)
200
209
  No database auto-detection here: the dashboard command uses 'database'
201
210
  when given and plain postgres otherwise, so pass it whenever the project
@@ -269,34 +278,47 @@ frontend can be defined and generated without the backend live.
269
278
 
270
279
  ```
271
280
  1. designer_list_plugins
272
- ── GROUNDING ── list available output plugins before initializing.
273
- Built-in: vanilla-js-basic (no auth), vanilla-js-auth (JWT auth).
281
+ ── GROUNDING ── list available output plugins before creating the UDF.
282
+ Built-in: vanilla-js-basic (no auth), vanilla-js-auth and
283
+ vanilla-js-custom (JWT auth + RBAC).
274
284
  → references/udf-catalog.md § Plugins
275
285
 
276
- 2. designer_init_project
277
- Scaffold a new frontend project from a plugin. Creates the project folder,
278
- the initial UDF payload (payload.json), and plugin assets.
286
+ 2a. codegen_migrate_payload ── PRIMARY ── when a backend RDF payload exists
287
+ Convert the RDF into a split UDF set in the output folder (default
288
+ frontend/payload/): app-config.json, pages/<pageId>.json, the aggregator
289
+ <appCode>.json, and snapshots in .meta/pages/. Run it once per RDF with
290
+ the same output folder to add pages to one app. It derives fields, types,
291
+ lookups, details[], status filters, and the date patterns from the
292
+ backend, so start here instead of writing pages by hand.
293
+ Needs a license and the backend config (like every codegen_* tool).
294
+ 2b. [hand-write the UDF] only when there is no RDF to migrate from
295
+ Ground every key with designer_get_udf_catalog first.
296
+ designer_init_project (optional) scaffold a project folder with the
297
+ assets of an auth-capable plugin (vanilla-js-auth / vanilla-js-custom).
298
+ It writes no UDF payload file.
279
299
 
280
300
  3. designer_get_udf_catalog
281
- ── GROUNDING ── call before defining or editing any UDF payload.
282
- Returns valid field types, page anatomy, features, data-source formats,
283
- and validation rules for the installed plugin version.
301
+ ── GROUNDING ── call before editing any UDF page.
302
+ Returns valid field types, enums, limits, and validation constants for
303
+ the installed designer version.
284
304
  → references/udf-catalog.md
285
305
 
286
- 4. [define / edit UDF payload JSON]
287
- Edit payload.json: appConfig, pages[], navigation[], homepage.
288
- One page entry = one CRUD page or one dashboard page.
306
+ 4. [edit the UDF pages]
307
+ Edit pages/<pageId>.json (labels, layout, features, workflowActions) and
308
+ the aggregator (navigation, homepage). One page entry = one CRUD page or
309
+ one dashboard page. Re-running migrate later merges RDF changes into
310
+ these files without losing the edits (Decision Points § Frontend UDF).
289
311
 
290
312
  5. designer_validate_payload
291
- ── GATE ── validate the UDF payload. Catches structural errors before
292
- generation. Run before preview or generate, every time.
313
+ ── GATE ── validate the UDF (the aggregator file). Catches structural
314
+ errors before generation. Run before preview or generate, every time.
293
315
 
294
316
  6. designer_preview_files
295
317
  Dry-run: list files that would be generated, without writing to disk.
296
318
  Use to verify scope before an overwrite.
297
319
 
298
320
  7. designer_generate
299
- Generate frontend HTML/JS/CSS from the UDF payload. Writes output files.
321
+ Generate frontend HTML/JS/CSS from the aggregator. Writes output files.
300
322
  The agent STOPS here — the user opens the output in a browser.
301
323
  ```
302
324
 
@@ -314,7 +336,8 @@ not serve or deploy).
314
336
 
315
337
  Licensing note: the Designer tools (`designer_preview_files`, `designer_generate`,
316
338
  etc.) do **not** require a RESTForge license, unlike the `codegen_*`, `runtime_*`,
317
- and `setup_validate_config` tools on the backend track.
339
+ and `setup_validate_config` tools. `codegen_migrate_payload` is a `codegen_*`
340
+ tool, so step 2a runs in the backend project folder.
318
341
 
319
342
  ---
320
343
 
@@ -407,6 +430,7 @@ definition content from memory.
407
430
  | Defining `fieldValidation` in an RDF payload | `codegen_get_field_validation_catalog` | references/field-validation.md |
408
431
  | Defining queries in an RDF payload | `codegen_get_query_declarative_catalog` | — |
409
432
  | Defining a dashboard payload | `codegen_get_dashboard_catalog` | — |
433
+ | Defining `/aggregate` joins or requests | — (no catalog tool yet) | references/rdf-advanced.md § Aggregate Config |
410
434
  | Defining UDF (frontend) | `designer_get_udf_catalog` | references/udf-catalog.md |
411
435
  | Listing available frontend plugins | `designer_list_plugins` | references/udf-catalog.md § Plugins |
412
436
  | Setting `db-connection.env` parameters | `setup_get_config_schema` | references/config-schema.md |
@@ -457,19 +481,41 @@ branch still obeys the Grounding-First Rules above.
457
481
  the SDF, and run `codegen_dbschema_validate`. The design shows presentation,
458
482
  not storage — do not turn every visible label into a column.
459
483
  → references/design-to-sdf.md
460
- - **DB exists with drift** → `codegen_dbschema_diff` to review, then
461
- `codegen_dbschema_apply`. Not `codegen_dbschema_migrate` — that is for empty
462
- DBs only.
484
+ - **"Is my schema valid and in sync with the database?"** →
485
+ `codegen_dbschema_validate` with `config` (optionally `table`): one verdict per
486
+ table, `[OK]`, `[DRIFT]`, or `[ERROR]` (`table-missing` → migrate/apply fixes
487
+ it; `sdf-invalid` → fix the file). Exit code 1 means drift or an error was
488
+ found, not that the tool failed. Not available for SQLite.
489
+ - **DB exists with drift** → `codegen_dbschema_diff` to review the per-column
490
+ differences, then `codegen_dbschema_apply`. Not `codegen_dbschema_migrate` —
491
+ that is for empty DBs only.
463
492
 
464
493
  ### RDF Payload
465
494
 
466
495
  - **No payload yet** → `codegen_generate_payload`.
467
496
  - **Payload exists, edit is API-layer only** (e.g. add/adjust `fieldValidation`,
468
497
  messages, or a query — no column added or dropped) → ground via the matching
469
- catalog, edit `payload.json`, run `codegen_validate_payload`, then regenerate
498
+ catalog, edit `payload/<name>.json`, run `codegen_validate_payload`, then regenerate
470
499
  with `codegen_create_endpoint`. No DB migration: the schema (SDF) is unchanged.
471
500
  - **Payload exists, DB schema changed** → `codegen_diff_payload` first, then
472
- `codegen_sync_payload` (non-breaking) or `codegen_migrate_payload` (breaking).
501
+ `codegen_sync_payload`. Turning the RDF into a frontend UDF is a separate
502
+ frontend step (Frontend Pipeline step 2a), not part of this branch.
503
+ - **Customisations survive regeneration.** `codegen_generate_payload` and
504
+ `codegen_sync_payload` keep edits made to generator-owned keys (`action`,
505
+ `fieldValidation`, inline SQL, `auditColumns`, the datatables query file).
506
+ A column deliberately removed from `fieldName` stays removed because generate
507
+ records the known columns in `payload/.meta/<name>.json`; commit that snapshot
508
+ with the payload and never edit it.
509
+ - **Show columns of a referenced table in the list** (e.g. `supplier_name` next
510
+ to `supplier_id`) → `codegen_sync_payload` with `table` and `expandFk`
511
+ (`"both"`, or `"datatables-only"` to leave a custom `viewQuery` alone). It
512
+ writes `query/<table>-join.sql` and points `datatablesQuery` (and `viewQuery`)
513
+ at it; `FK_AUTO_JOIN` picks LEFT or INNER JOIN. The display column per FK is
514
+ chosen automatically and is never the primary key. Use `fkColumns`
515
+ (`ref_table.column`, or `local_fk:ref_table.column`) to override it and
516
+ `expandFkSkip` to leave a relation out. When the CLI reports "No natural
517
+ display column found", **ask the user** which column to show or whether to
518
+ skip that relation — do not pick one yourself.
473
519
  - **Custom query needed** → ground via `codegen_get_query_declarative_catalog`,
474
520
  check the statement with `codegen_validate_sql` against the live database, then
475
521
  set `datatablesQuery`, `viewQuery`, or `exportQuery` in the payload. External
@@ -500,21 +546,36 @@ branch still obeys the Grounding-First Rules above.
500
546
  after the endpoints exist, and after `project_auth` when the project needs
501
547
  auth, so `client.auth` is included.
502
548
  - **Integration test for an existing endpoint** → `codegen_generate_test`.
503
- - **Workflow (status transitions)** → add `workflow` and `workflowActions` to the
504
- RDF payload; generates a `/change-status` endpoint automatically.
549
+ - **Every feature endpoint needs its `action` flag.** A feature block without
550
+ the matching flag in `action` produces no endpoint.
551
+ → references/rdf-advanced.md § The `action` Block
552
+ - **Workflow (status transitions)** → set `action.workflow: true` and add a
553
+ `workflow` block (`statusField`, `transitions` as a map `status → [targets]`,
554
+ optional `hooks` keyed by target status) to the RDF; generates
555
+ `/change-status`. The buttons are UDF `workflowActions` — a frontend key that
556
+ never goes into the RDF.
505
557
  → references/rdf-advanced.md § Workflow
506
- - **Master-detail (composite CRUD)** → add `details[]` to the RDF payload;
507
- generates `/create-composite`, `/update-composite`, `/read-composite`.
558
+ - **Master-detail (composite CRUD)** → run `codegen_generate_payload` with
559
+ `detail: "<detail table>"`. It writes the `masterDetail` block, the detail
560
+ query file, and `action.createComposite` / `updateComposite` /
561
+ `readComposite`; then fill `headerCalculations` and `calculated` formulas by
562
+ hand. Generates `/create-composite`, `/update-composite`, `/read-composite`.
508
563
  → references/rdf-advanced.md § Master-Detail
564
+ - **Summary numbers per resource** (count, sum, avg, min, max, optionally
565
+ grouped) → `action.aggregate: true`; the request body carries the operations,
566
+ and `aggregateConfig.joins` only whitelists JOINs. For charts or KPIs across
567
+ several tables, prefer a backend dashboard (`codegen_create_dashboard`).
568
+ → references/rdf-advanced.md § Aggregate Config
509
569
  - **Excel export** → `/export` works by default (falls back to
510
570
  `SELECT {fields} FROM tableName`); customise the columns/filter with
511
571
  `exportQuery` in the RDF payload. Tune `EXPORT_FILE_EXPIRY` / `EXPORT_CHUNK_SIZE`
512
572
  in config. Ground `exportQuery` via `codegen_get_query_declarative_catalog`.
513
573
  → references/rdf-advanced.md § Data Source Resolution
514
- - **Excel import (.xlsx)** → add `importConfig` (sheet, startRow, strategy,
515
- upsertKey, columns header→fieldName, optional lookup) to the RDF payload;
516
- generates `/import-preview` (validates, returns a diff) and `/import-commit`
517
- (applies). → references/rdf-advanced.md § Import Config
574
+ - **Excel import (.xlsx)** → set `action.import: true` and add `importConfig`
575
+ with `enabled: true` (`upsertKeys`, `upsertStrategy`, `requiredFields`,
576
+ optional `lookupFields`) to the RDF payload; generates `/import-upload`,
577
+ `/import-preview`, `/import-commit`, and `/import-status`.
578
+ → references/rdf-advanced.md § Import Config
518
579
  - Activate on an existing project: edit the payload to add `importConfig`
519
580
  (and/or `exportQuery`) → `codegen_validate_payload` → `codegen_create_endpoint`.
520
581
 
@@ -551,15 +612,38 @@ is `schemaPath` (CLI `--schema-path`, default `schema`).
551
612
  twice inserts the rows twice. Confirm with the user before pushing into a
552
613
  database that may already hold those rows.
553
614
 
615
+ ### Frontend UDF
616
+
617
+ - **A backend RDF exists** → `codegen_migrate_payload`; do not write the page by
618
+ hand. Run it once per RDF into the same output folder to build one app.
619
+ - **Re-running migrate** (RDF changed, or a page must pick up new columns) →
620
+ run it again **without** `overwrite`. Existing pages are merged: user edits
621
+ (labels, layout, removed fields, blocks) are kept and RDF changes to untouched
622
+ values are applied. Backend contract values (`apiPath`, `primaryKey`, `type`,
623
+ `required`, `maxlength`, `decimalPlaces`, `tableField`, lookup source, option
624
+ values) follow the RDF when both sides changed, with a warning. The merge uses
625
+ the snapshots in `<output>/.meta/pages/<pageId>.json`; commit them with the
626
+ pages and never edit them. The aggregator (`navigation`, `homepage`) and
627
+ `app-config.json` are merged too.
628
+ - **`overwrite: true`** recreates the page from the RDF and discards every
629
+ customisation (the old file goes to `.restforge/archive/`). Confirm with the
630
+ user before using it.
631
+ - **Date patterns** → `appConfig.dateFormat` / `dateTimeFormat` are rewritten
632
+ from the backend `DATEFORMAT` / `DATETIMEFORMAT` on every migrate. After the
633
+ backend changes them, re-run migrate and `designer_generate`; never edit the
634
+ frontend values to differ from the backend.
635
+
554
636
  ### Frontend page type
555
637
 
556
638
  - **Standard CRUD page** → `pageType: "crud"` (default) with `apiPath`,
557
639
  `primaryKey`, `displayField`, and `fields[]`.
558
- - **Dashboard page** → `pageType: "dashboard"` with `dataSources[]` and `rows[]`
559
- containing widget columns.
640
+ - **Dashboard page** → `pageType: "dashboard"` with a `dataSources` object
641
+ (`name → { url, method, body }`) and `rows[]` → `columns[]` → `widgets[]`.
560
642
  → references/udf-catalog.md § Dashboard Page
561
- - **Page with approval workflow** → add `workflow.statusField` and
562
- `workflowActions[]` to the page.
643
+ - **Page with approval workflow** → add `workflow` (`statusField` and
644
+ `transitions`, identical to the RDF) and `workflowActions[]` whose `actionId`
645
+ equals the target status. Add `fieldStates` to lock rows in final statuses.
646
+ → references/udf-catalog.md § Workflow Actions
563
647
 
564
648
  ### Frontend plugin choice
565
649
 
@@ -601,11 +685,15 @@ The following require explicit user confirmation before execution:
601
685
  and resource files of endpoints that no longer exist are left behind.
602
686
  - `setup_validate_config` with `autoCreateDb: true` — it runs CREATE DATABASE on
603
687
  the database server. The default call is read-only.
688
+ - `codegen_migrate_payload` with `overwrite: true` — existing UDF pages are
689
+ recreated and every customisation in them is discarded (the old files are
690
+ archived). Without `overwrite`, pages are merged and nothing is lost.
604
691
 
605
692
  `codegen_create_endpoint` and `codegen_create_dashboard` overwrite by default
606
- (`force` is true) but archive the previous version as `.archive.NNN` first, so
607
- they need a plain intent confirmation rather than a destructive-operation
608
- confirmation. Use `force: false` when the point is to find out whether the module
693
+ (`force` is true) but first move the previous files to
694
+ `.restforge/archive/<run>/<original relative path>` (the 5 most recent runs are
695
+ kept), so they need a plain intent confirmation rather than a
696
+ destructive-operation confirmation. Use `force: false` when the point is to find out whether the module
609
697
  already exists: the endpoint command then stops at its confirmation question
610
698
  without writing, and the dashboard command refuses with a clean error.
611
699
 
@@ -711,13 +799,14 @@ pass:
711
799
 
712
800
  ### Tools that depend on the installed platform version
713
801
 
714
- Two tools wrap CLI sub-commands that older platforms do not have. Both fail in a
715
- recognisable way, so treat the failure as a version answer, not a payload problem:
802
+ Two tools wrap CLI sub-commands that old platform releases do not have. Current
803
+ releases have both. On an old project they fail in a recognisable way, so treat
804
+ the failure as a version answer, not a payload problem:
716
805
 
717
806
  | Tool | Requirement | Symptom on an older platform |
718
807
  |---|---|---|
719
- | `codegen_validate_sql` | a platform providing `query validate` (confirmed present in 5.5.5; the exact minimum is not established) | `Unknown command: query` |
720
- | `codegen_validate_dashboard_payload` | a platform providing `dashboard create --validate-only`, which exists only after 5.5.5 | `Unknown flag: --validate-only`; the tool reports it as an upgrade requirement |
808
+ | `codegen_validate_sql` | a platform providing `query validate` | `Unknown command: query` |
809
+ | `codegen_validate_dashboard_payload` | a platform providing `dashboard create --validate-only` | `Unknown flag: --validate-only`; the tool reports it as an upgrade requirement |
721
810
 
722
811
  When `codegen_validate_dashboard_payload` is unavailable, the fallback is
723
812
  `codegen_create_dashboard` itself — it runs the same validator before writing.
@@ -734,6 +823,9 @@ When `codegen_validate_dashboard_payload` is unavailable, the fallback is
734
823
  | "Widget uses undeclared placeholder" | `:paramName` in SQL not in `params` | Add the entry to `params` in the dashboard payload |
735
824
  | "tableName and widgets conflict" | Payload contains both | Dashboard uses `widgets`; CRUD uses `tableName` — remove the wrong one |
736
825
  | UDF validation error on field type | Field type not supported by the active plugin | Run `designer_list_plugins` + `designer_get_udf_catalog` to verify supported types |
826
+ | `constraints.format ... is not supported for type 'date'` (or `timestamp`) | Per-field date pattern in RDF | Remove `format`; the pattern comes from `DATEFORMAT` / `DATETIMEFORMAT` |
827
+ | Frontend shows a different date than the backend stored | `appConfig.dateFormat` / `dateTimeFormat` differ from the backend config | Re-run `codegen_migrate_payload`, then `designer_generate` |
828
+ | Hook rejection answered HTTP 400 with only the hook message | A component handler returned `{ success: false }` or threw | Expected behaviour; the handler name and path are in the server log |
737
829
 
738
830
  When an error is not in this table, do not guess a fix. Re-run the relevant
739
831
  `*_validate_*` tool, read its message, and ground against the catalog before
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Offline mirror.** This file mirrors the auth commands of the installed
4
4
  > RESTForge platform and Designer (`restforge project auth`, `npx
5
- > restforge-designer auth`). The live tools/CLI are authoritative — when this file and them disagree,
5
+ > npx restforge-designer auth`). The live tools/CLI are authoritative — when this file and them disagree,
6
6
  > trust the tools, then update this file.
7
7
 
8
8
  **This file documents the auth EXTENSION — auth WITHOUT RBAC.** It is one of two
@@ -116,7 +116,7 @@ injected automatically when `designer_generate` creates pages later.
116
116
  **Prerequisites:** the Designer is invoked via `npx restforge-designer` and is
117
117
  bundled inside the `@restforgejs/platform` package; the prerequisite is that
118
118
  `@restforgejs/platform` is installed in the project (e.g. a project created with
119
- `npx create-restforge-app`), not a standalone binary on PATH.
119
+ `npx create-restforge-app`).
120
120
 
121
121
  Both are idempotent. **`--remove` is destructive** — confirm project name and
122
122
  intent with the user before running (MCP always passes `--force`).