create-restforge-skills 0.2.0 → 0.3.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.
@@ -1,559 +1,740 @@
1
- ---
2
- name: restforge
3
- description: >
4
- RESTForge end-to-end workflow — use for any task involving RESTForge: SDF
5
- (Schema Definition File), RDF (Resource Definition File), UDF (UI Definition
6
- File), dbschema, defineModel, codegen, payload, generate endpoint, generate
7
- dashboard, generate frontend, migrate schema, setup project, add authentication
8
- (project auth backend, embedded rfx_auth frontend auth), or design-to-SDF
9
- (deriving a schema from an HTML mockup, screenshot, image, or UI design). Also
10
- active for the codegen_*, designer_*, setup_*, runtime_* MCP tools and the
11
- @restforgejs/platform / @restforgejs/mcp-server packages. Defines the canonical
12
- operation order for the backend track (setup → schema → payload → codegen →
13
- runtime) and the frontend track (init → udf → validate → generate), the
14
- grounding-first catalog rules, decision branches, and destructive-operation
15
- guardrails. Active whenever working on a RESTForge project, not only when the
16
- word "skill" is mentioned.
17
- license: MIT
18
- compatibility: >
19
- Requires the RESTForge MCP server (@restforgejs/mcp-server) registered in the
20
- client, plus a RESTForge license for codegen_*, runtime_*, and
21
- setup_validate_config operations. Designer tools do not require a license.
22
- ---
23
-
24
- ## Mental Model
25
-
26
- RESTForge is a deterministic, definition-first generator with two output tracks:
27
-
28
- - **Backend track** — SDF defines the database schema; RDF defines REST API
29
- endpoints. One SDF produces identical DDL; one RDF payload produces an
30
- identical endpoint module on every execution.
31
- - **Frontend track** — UDF defines the frontend application. One UDF payload
32
- produces identical HTML/JS/CSS via `npx restforge-designer`, plugin-driven,
33
- no build step required.
34
-
35
- The agent interacts with the platform **exclusively through MCP tools**. The
36
- agent does not write generation code itself, does not modify generated output,
37
- and does not guess options outside the catalog. All valid options come from the
38
- catalog returned by grounding tools.
39
-
40
- The platform exposes its capabilities as MCP tools grouped by domain: `health_*`,
41
- `setup_*`, `codegen_*`, `runtime_*`, `designer_*`, `data_*`, `key_*`,
42
- `project_*`. Two facts follow from this and shape every task:
43
-
44
- 1. **The skill describes intent and order; the MCP server executes.** If the
45
- RESTForge MCP server is not registered in the client, this skill cannot do
46
- anything — there is nothing to call. Confirm the tools are available before
47
- planning a multi-step operation.
48
- 2. **The catalog is the source of truth, not memory.** Field types, constraints,
49
- validation rules, and plugin capabilities belong to the *installed* platform
50
- version. Always ground against the catalog before proposing definition
51
- content (see Grounding-First Rules, below).
52
-
53
- ---
54
-
55
- ## Preflight (run before any RESTForge task)
56
-
57
- Verify readiness before planning or producing anything:
58
-
59
- 1. **Are the RESTForge MCP tools present?** If `codegen_*` / `designer_*` are not
60
- in your available tools, the MCP server is **not active**. Stop and tell the
61
- user to register the RESTForge MCP server and restart the client. Do **not**
62
- finish the task by hand-reading the bundled `references/` — that bypasses the
63
- generator and yields slower, non-deterministic output.
64
- 2. **Backend work** → confirm the project and config are ready with
65
- `runtime_detect_project`, then the `setup_validate_config` gate.
66
- 3. **Frontend work** → the Designer tools pre-check that `npx restforge-designer`
67
- can run (its binary is bundled in `@restforgejs/platform`, so it is available
68
- once the project is created with `npx create-restforge-app` / the platform is
69
- installed); if it cannot run, surface that before proceeding.
70
-
71
- If a prerequisite is missing, report it as the next step — do not improvise around it.
72
-
73
- ---
74
-
75
- ## Backend Pipeline (canonical)
76
-
77
- This is the canonical (golden) path. For state-dependent choices see Decision
78
- Points; for failure handling see Guardrails and Common Errors.
79
-
80
- The sequence below applies to a **new project from scratch**. For an existing
81
- project, start from the step that matches the current state — do not re-run
82
- earlier steps that already succeeded.
83
-
84
- ```
85
- 1. npx create-restforge-app <name> ── PRIMARY ── human-run scaffolder
86
- One shot: creates the project folder, runs
87
- npm install @restforgejs/platform (local), and bundles the designer
88
- binary. This is the dominant way to start a new project.
89
- Granular alternative (agent scaffolds step by step):
90
- setup_create_folder → create the project folder.
91
-
92
- 2. setup_install_package (granular path only)
93
- Install @restforgejs/platform into the folder. SKIP when the project
94
- was created with create-restforge-app (already installed). Plain
95
- 'npm install @restforgejs/platform' stays valid but is not the
96
- primary entry point.
97
-
98
- 3. setup_init_config
99
- Write config/db-connection.env from the default template.
100
-
101
- 4. setup_write_env / setup_update_env
102
- Set values: LICENSE, SERVER_ADDRESS, SERVER_PORT, DB_TYPE,
103
- DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME (9 required parameters).
104
- Use setup_read_env to read existing values before overwriting.
105
-
106
- 5. setup_validate_config
107
- ── GATE ── Must pass before any codegen_* operation starts.
108
- Validates database connection and license. Running codegen before this
109
- gate passes produces uninformative errors.
110
-
111
- 6. codegen_get_dbschema_catalog
112
- ── GROUNDING ── Source of truth before defining SDF: field types,
113
- constraints, shorthand syntax, relations, referential actions,
114
- check operations, and the soft-delete contract.
115
- → references/dbschema-catalog.md
116
-
117
- 7a. codegen_dbschema_init (empty DB — scaffold SDF with audit columns)
118
- codegen_dbschema_template (minimal template, no DB connection required)
119
- 7b. codegen_dbschema_introspect (existing DB — generate SDF from actual schema)
120
-
121
- 8. codegen_dbschema_validate
122
- Validate SDF before any DDL is generated. Catch errors here, not at migrate.
123
-
124
- 9. codegen_dbschema_generate_ddl (optional — preview DDL without executing)
125
-
126
- 10a. codegen_dbschema_migrate (empty DB — apply DDL directly)
127
- 10b. codegen_dbschema_diff (existing DB — review the differences first)
128
- → codegen_dbschema_apply (apply only after confirming the drift)
129
-
130
- 11. codegen_get_field_validation_catalog
131
- ── GROUNDING ── before defining fieldValidation in a payload.
132
- → references/field-validation.md
133
-
134
- 12. codegen_get_query_declarative_catalog
135
- ── GROUNDING ── when the payload contains datatablesQuery, viewQuery,
136
- viewName, exportQuery, or detailQuery.
137
-
138
- 13. codegen_generate_payload
139
- Generate payload JSON from a table. Foundation for all subsequent
140
- codegen operations.
141
-
142
- 14. codegen_validate_payload
143
- Validate the payload before codegen. Catch errors here.
144
-
145
- 15. codegen_diff_payload (when a payload exists and the DB schema has changed)
146
- → codegen_sync_payload (sync payload to the current DB state — non-breaking)
147
- → codegen_migrate_payload (when the payload has breaking changes)
148
-
149
- 16a. codegen_create_endpoint (standard CRUD module)
150
- 16b. codegen_get_dashboard_catalog
151
- → codegen_create_dashboard (analytic dashboard with SQL widgets)
152
- 16c. codegen_create_processor (background processing)
153
- 16d. codegen_create_kafka_consumer (Kafka event streaming)
154
-
155
- 17. runtime_generate_launcher
156
- Generate the launcher script. The agent STOPS here. The user executes
157
- the launcher — the server runs independently of the agent session.
158
-
159
- 18. (user executes the launcher)
160
-
161
- 19. runtime_check_status
162
- Verify the server is running and endpoints are reachable.
163
- ```
164
-
165
- Two hard checkpoints (see Guardrails): **step 5** is a gate — no `codegen_*` call
166
- before `setup_validate_config` passes; **step 17** is where the agent stops (it
167
- generates the launcher, never runs the server).
168
-
169
- ---
170
-
171
- ## Frontend Pipeline (canonical)
172
-
173
- This is the canonical (golden) path for the frontend track. It runs
174
- **independently** from the backend pipeline. The backend API must be running and
175
- reachable at `apiBaseUrl` before the generated frontend is useful, but the
176
- frontend can be defined and generated without the backend live.
177
-
178
- ```
179
- 1. designer_list_plugins
180
- ── GROUNDING ── list available output plugins before initializing.
181
- Built-in: vanilla-js-basic (no auth), vanilla-js-auth (JWT auth).
182
- → references/udf-catalog.md § Plugins
183
-
184
- 2. designer_init_project
185
- Scaffold a new frontend project from a plugin. Creates the project folder,
186
- the initial UDF payload (payload.json), and plugin assets.
187
-
188
- 3. designer_get_udf_catalog
189
- ── GROUNDING ── call before defining or editing any UDF payload.
190
- Returns valid field types, page anatomy, features, data-source formats,
191
- and validation rules for the installed plugin version.
192
- → references/udf-catalog.md
193
-
194
- 4. [define / edit UDF payload JSON]
195
- Edit payload.json: appConfig, pages[], navigation[], homepage.
196
- One page entry = one CRUD page or one dashboard page.
197
-
198
- 5. designer_validate_payload
199
- ── GATE ── validate the UDF payload. Catches structural errors before
200
- generation. Run before preview or generate, every time.
201
-
202
- 6. designer_preview_files
203
- Dry-run: list files that would be generated, without writing to disk.
204
- Use to verify scope before an overwrite.
205
-
206
- 7. designer_generate
207
- Generate frontend HTML/JS/CSS from the UDF payload. Writes output files.
208
- The agent STOPS here — the user opens the output in a browser.
209
- ```
210
-
211
- For plugin development (custom output plugins):
212
-
213
- ```
214
- designer_scaffold_plugin → [develop plugin templates]
215
- → designer_inspect_plugin (verify plugin metadata and capabilities)
216
- → designer_generate (test generation with the custom plugin)
217
- ```
218
-
219
- Two checkpoints (see Guardrails): **step 5** is a gate — never `designer_generate`
220
- an unvalidated payload; **step 7** is where the agent stops (generates files, does
221
- not serve or deploy).
222
-
223
- Licensing note: the Designer tools (`designer_preview_files`, `designer_generate`,
224
- etc.) do **not** require a RESTForge license, unlike the `codegen_*`, `runtime_*`,
225
- and `setup_validate_config` tools on the backend track.
226
-
227
- ---
228
-
229
- ## Auth Extension
230
-
231
- RESTForge has **two different auth mechanisms — do not confuse them.** Pick the
232
- right one; never describe one as the other, and never claim the extension does RBAC.
233
-
234
- | Mechanism | RBAC? | How |
235
- |---|---|---|
236
- | **Plugin auth** — built into the frontend at generation time | **Yes (auth + RBAC)** | `vanilla-js-auth` or `vanilla-js-custom` plugin in `designer_init_project`; disable with `noAuth: true` (`--no-auth`) |
237
- | **Auth extension** — bolt-on added to an existing project | **No RBAC** | backend `project_auth`; frontend `designer_auth_create` (embedded `rfx_auth`) |
238
-
239
- Confirm which plugins provide auth with `designer_list_plugins` — do not hardcode
240
- it. The rest of this section covers the **extension** (the no-RBAC bolt-on); for
241
- plugin auth see Decision Points § Frontend plugin choice. Google Sign-In and
242
- `@restforgejs/auth` are out of scope for the extension.
243
-
244
- ### Backend auth — `project_auth`
245
-
246
- Adds the auth backend to an existing RESTForge project (run the standard backend
247
- pipeline first; the project and its endpoint must already exist, and the DB must
248
- be active).
249
-
250
- ```
251
- project_auth (wraps: npx restforge project auth --create --project=<name>)
252
- ```
253
-
254
- Installs auth SDF (`rfx`), DB tables, middleware, router, six processors
255
- (register/login/refresh/logout/me/reset-password), a random `JWT_SECRET`, and
256
- `bcrypt`+`jsonwebtoken`. Idempotent. → references/auth.md § Backend
257
-
258
- ### Frontend auth — `designer_auth_create` / `designer_auth_remove`
259
-
260
- Adds (or removes) an **embedded** login / signup / forget-password overlay
261
- (`rfx_auth`) on an existing frontend project, at route
262
- `/api/<project>/rfx_auth`. This is independent of the `vanilla-js-auth` plugin.
263
-
264
- ```
265
- designer_auth_create (wraps: npx restforge-designer auth --create --project=<name>)
266
- designer_auth_remove (wraps: npx restforge-designer auth --remove --project=<name> --force)
267
- ```
268
-
269
- `create` writes the auth pages + `js/rfx_auth.js` and injects a guard into existing
270
- pages; `remove` deletes them. Idempotent. Runs via `npx restforge-designer`
271
- (bundled in `@restforgejs/platform`; available once the project was created with
272
- `npx create-restforge-app` / the platform is installed).
273
- → references/auth.md § Frontend
274
-
275
- Do not combine the two mechanisms on one app: if an app already has plugin auth
276
- (`vanilla-js-auth` / `vanilla-js-custom`), do not also add embedded `rfx_auth`.
277
-
278
- ---
279
-
280
- ## Grounding-First Rules
281
-
282
- Before reasoning about, proposing, or generating any **definition content** —
283
- SDF fields, RDF `fieldValidation`, queries, dashboard widgets, or UDF pages —
284
- call the matching grounding tool first and use only what it returns. Never write
285
- definition content from memory.
286
-
287
- | Context | Grounding tool | Reference |
288
- |---|---|---|
289
- | Defining or reviewing SDF | `codegen_get_dbschema_catalog` | references/dbschema-catalog.md |
290
- | Deriving SDF from a UI design (HTML / image / screenshot) | `codegen_get_dbschema_catalog` | references/design-to-sdf.md |
291
- | Defining `fieldValidation` in an RDF payload | `codegen_get_field_validation_catalog` | references/field-validation.md |
292
- | Defining queries in an RDF payload | `codegen_get_query_declarative_catalog` | — |
293
- | Defining a dashboard payload | `codegen_get_dashboard_catalog` | — |
294
- | Defining UDF (frontend) | `designer_get_udf_catalog` | references/udf-catalog.md |
295
- | Listing available frontend plugins | `designer_list_plugins` | references/udf-catalog.md § Plugins |
296
-
297
- **Why this rule exists.** The catalog is the source of truth for valid options
298
- in the *installed* platform version. Reasoning without it produces confident but
299
- wrong output — field types that do not exist, constraints not applicable to a
300
- type, or wrong semantics. Two concrete failure modes this rule prevents:
301
-
302
- - **Inventing options.** Without grounding, an agent may write a made-up key
303
- (e.g. `"toUpper": true`) that the validator rejects. The catalog gives the
304
- exact key and value type.
305
- - **Misreading semantics.** A constraint can mean something different from its
306
- plain-English name. For example, `uppercase` on a `string` field is a
307
- *normalization transform* (it forces the stored value to upper case), grouped
308
- with `trim` and `lowercase` — it is **not** a validator that rejects
309
- non-uppercase input. If the user wants rejection, the answer is `pattern`, not
310
- `uppercase`; if they want database-level enforcement, that is an SDF check
311
- constraint, not RDF `fieldValidation`. Grounding surfaces this distinction
312
- before the agent commits to the wrong one.
313
-
314
- The reference files help you *understand* the catalog; they do **not** replace
315
- the tool. Call the tool to ground, produce, and validate — do not hand-produce
316
- output a tool would generate. The live tool is authoritative; when a reference and
317
- the tool disagree, trust the tool.
318
-
319
- ---
320
-
321
- ## Decision Points
322
-
323
- Use these to pick the correct branch when the request is state-dependent. Each
324
- branch still obeys the Grounding-First Rules above.
325
-
326
- ### Schema (SDF)
327
-
328
- - **DB does not exist** → `codegen_dbschema_init` (scaffold with audit columns)
329
- or `codegen_dbschema_template` (minimal template, no DB connection required).
330
- - **DB already exists** → `codegen_dbschema_introspect` to generate SDF from the
331
- actual schema. Do not hand-write a schema that a real DB can describe.
332
- - **Starting from a UI design** (HTML mockup, screenshot, image, Figma export)
333
- → first confirm the design is an entity to model, not a dashboard/analytics
334
- screen (those map to the Dashboard RDF branch below, not to a new SDF table).
335
- Then classify visible elements into stored / derived / relation / audit, draft
336
- the SDF, and run `codegen_dbschema_validate`. The design shows presentation,
337
- not storage — do not turn every visible label into a column.
338
- → references/design-to-sdf.md
339
- - **DB exists with drift** → `codegen_dbschema_diff` to review, then
340
- `codegen_dbschema_apply`. Not `codegen_dbschema_migrate` — that is for empty
341
- DBs only.
342
-
343
- ### RDF Payload
344
-
345
- - **No payload yet** → `codegen_generate_payload`.
346
- - **Payload exists, edit is API-layer only** (e.g. add/adjust `fieldValidation`,
347
- messages, or a query — no column added or dropped) → ground via the matching
348
- catalog, edit `payload.json`, run `codegen_validate_payload`, then regenerate
349
- with `codegen_create_endpoint`. No DB migration: the schema (SDF) is unchanged.
350
- - **Payload exists, DB schema changed** → `codegen_diff_payload` first, then
351
- `codegen_sync_payload` (non-breaking) or `codegen_migrate_payload` (breaking).
352
- - **Custom query needed** → ground via `codegen_get_query_declarative_catalog`,
353
- then set `datatablesQuery`, `viewQuery`, or `exportQuery` in the payload.
354
- External SQL files use the `file:` prefix
355
- (e.g. `"datatablesQuery": "file:sql/orders.sql"`).
356
-
357
- > **"Add an uppercase / case constraint" is ambiguous — disambiguate first.**
358
- > In RESTForge `uppercase` is an RDF `fieldValidation` *normalization transform*
359
- > (forces the stored value to upper case), not a reject-if-not-uppercase
360
- > validator. If the user wants rejection, use `pattern`. If the user wants the
361
- > database to enforce it, that is an SDF check constraint, not RDF. Confirm which
362
- > one is meant before editing — see Grounding-First Rules § Misreading semantics.
363
-
364
- ### Backend module type
365
-
366
- - **Standard CRUD** → `codegen_create_endpoint`. One payload = one module.
367
- - **Analytic dashboard** → `codegen_create_dashboard`. Payload must have
368
- `widgets` (not `tableName`); page name must be prefixed `dash-`.
369
- - **Background job** → `codegen_create_processor`.
370
- - **Kafka event consumer** → `codegen_create_kafka_consumer`; requires
371
- `KAFKA_ENABLED=true` in config.
372
- - **Workflow (status transitions)** → add `workflow` and `workflowActions` to the
373
- RDF payload; generates a `/change-status` endpoint automatically.
374
- → references/rdf-advanced.md § Workflow
375
- - **Master-detail (composite CRUD)** → add `details[]` to the RDF payload;
376
- generates `/create-composite`, `/update-composite`, `/read-composite`.
377
- → references/rdf-advanced.md § Master-Detail
378
- - **Excel export** → `/export` works by default (falls back to
379
- `SELECT {fields} FROM tableName`); customise the columns/filter with
380
- `exportQuery` in the RDF payload. Tune `EXPORT_FILE_EXPIRY` / `EXPORT_CHUNK_SIZE`
381
- in config. Ground `exportQuery` via `codegen_get_query_declarative_catalog`.
382
- → references/rdf-advanced.md § Data Source Resolution
383
- - **Excel import (.xlsx)** → add `importConfig` (sheet, startRow, strategy,
384
- upsertKey, columns header→fieldName, optional lookup) to the RDF payload;
385
- generates `/import-preview` (validates, returns a diff) and `/import-commit`
386
- (applies). → references/rdf-advanced.md § Import Config
387
- - Activate on an existing project: edit the payload to add `importConfig`
388
- (and/or `exportQuery`) → `codegen_validate_payload` → `codegen_create_endpoint`.
389
-
390
- ### Soft-delete vs hard-delete
391
-
392
- - Use soft-delete when deleted rows must be audited or recoverable. Declare
393
- `softDelete: { enabled: true }` in SDF and add the three contract columns
394
- (`is_deleted`, `deleted_at`, `deleted_by`).
395
- - Soft-delete is supported on PostgreSQL only (Phase 1).
396
- - Tables with composite UNIQUE constraints are incompatible with soft-delete.
397
-
398
- ### Data seeding / migration (rows, not schema)
399
-
400
- Move table **rows** through SDF-driven envelope files. This is for data, never
401
- for schema — use the dbschema tools for structure.
402
-
403
- **Default output location:** `data-storage/<schema>/<table>.json`, relative to the
404
- project cwd. The `data-storage` folder is the default of the `storagePath` param
405
- (CLI `--storage-path <folder>`); override it to write elsewhere. The SDF read from
406
- is `schemaPath` (CLI `--schema-path`, default `schema`).
407
-
408
- - **Export / dump / snapshot / back up rows** → `data_pull`. Scope is exactly one
409
- of `table`, `schema`, or `allSchemas`. Only tables registered in the SDF can be
410
- pulled. `force: true` overwrites existing envelope files. Optional `limit`,
411
- `batchSize`, `config` (falls back to the default set via `config set-default`,
412
- i.e. `.restforge/defaults.json`), `schemaPath`, `storagePath`.
413
- - **Import / load / seed / restore rows** → `data_push`. Same file names as
414
- `data_pull`, so pulled files push back directly. Scope is exactly one of `table`,
415
- `schema`, or `allSchemas`; for `schema`/`allSchemas` tables load in FK
416
- parent→child order.
417
- - **Move data between databases** → `data_pull` from the source, then `data_push`
418
- into the target (`config` selects the env per side).
419
- - ⚠ `data_push` is **APPEND-ONLY** (batch INSERT, no upsert/replace). Running it
420
- twice inserts the rows twice. Confirm with the user before pushing into a
421
- database that may already hold those rows.
422
-
423
- ### Frontend page type
424
-
425
- - **Standard CRUD page** → `pageType: "crud"` (default) with `apiPath`,
426
- `primaryKey`, `displayField`, and `fields[]`.
427
- - **Dashboard page** → `pageType: "dashboard"` with `dataSources[]` and `rows[]`
428
- containing widget columns.
429
- → references/udf-catalog.md § Dashboard Page
430
- - **Page with approval workflow** → add `workflow.statusField` and
431
- `workflowActions[]` to the page.
432
-
433
- ### Frontend plugin choice
434
-
435
- - **No auth** → `vanilla-js-basic`.
436
- - **Auth WITH RBAC, built into the app** → `vanilla-js-auth` or
437
- `vanilla-js-custom` at `designer_init_project`. Use `noAuth: true` (`--no-auth`)
438
- to get the plugin's UI without its auth.
439
- - **Custom branding / new plugin** → `designer_scaffold_plugin`.
440
- - **Bolt-on auth WITHOUT RBAC** → not a plugin; see Authentication below.
441
- → references/udf-catalog.md § Plugins
442
-
443
- ### Authentication
444
-
445
- - **Needs RBAC** → plugin auth (`vanilla-js-auth` / `vanilla-js-custom`) at
446
- `designer_init_project`. The extension below does **not** do RBAC.
447
- - **Backend auth on an existing project (no RBAC)** → `project_auth` (after the
448
- project and its endpoint exist, with an active DB).
449
- - **Frontend auth on an app built WITHOUT plugin auth (no RBAC)** →
450
- `designer_auth_create` (embedded `rfx_auth`).
451
- - **Remove embedded frontend auth** → `designer_auth_remove` — destructive,
452
- confirm first (see Guardrails).
453
-
454
- ---
455
-
456
- ## Guardrails
457
-
458
- These are hard rules. They override convenience and override an eager reading of
459
- the user's request. When a guardrail conflicts with finishing faster, the
460
- guardrail wins.
461
-
462
- **1. Confirm before destructive operations.**
463
- The following require explicit user confirmation before execution:
464
-
465
- - `codegen_dbschema_migrate` or `codegen_dbschema_apply` that drops a table or
466
- column, or alters a column in a way that loses data.
467
- - `project_delete` — permanent project deletion.
468
-
469
- For schema changes, run `codegen_dbschema_diff` first, present a summary of the
470
- destructive parts (dropped tables/columns, type narrowing), and wait for
471
- confirmation before calling `codegen_dbschema_apply`. Never infer approval from
472
- the original request — "update the schema" is not consent to drop a column.
473
-
474
- **2. The agent does not run the server.**
475
- The agent's last step on the backend track is `runtime_generate_launcher`. The
476
- user executes the launcher in their own terminal. The agent never calls shell
477
- commands to start, stop, or restart the server, and never assumes the server is
478
- running — verify with `runtime_check_status` instead.
479
-
480
- **3. The `validate_config` gate is mandatory.**
481
- `setup_validate_config` must pass before any `codegen_*` operation starts. Do not
482
- skip it "to save a step" — running codegen against an invalid config produces
483
- uninformative errors that cost more time than the gate.
484
-
485
- **4. Validate before generating.**
486
- Always run `codegen_validate_payload` before `codegen_create_*`, and
487
- `designer_validate_payload` before `designer_generate`. Generation on an invalid
488
- payload produces incomplete or broken output that looks like it succeeded.
489
-
490
- **5. Stay inside the task scope.**
491
- Do not modify files outside the requested task. If the change is a backend
492
- payload edit, do not also "tidy up" the SDF, the runtime, or the frontend. If a
493
- change genuinely requires touching another area (e.g. an RDF edit that needs a
494
- new column, which is an SDF change), stop and report the cross-over, then ask
495
- before expanding scope.
496
-
497
- **6. Ground before defining — repeated here because it is a guardrail, not a
498
- suggestion.** Never write SDF fields, `fieldValidation`, queries, dashboard
499
- widgets, or UDF content from memory. Call the matching catalog tool first (see
500
- Grounding-First Rules). Inventing an option that "should" exist is the most
501
- common way to produce confidently wrong output.
502
-
503
- **7. Confirm before removing embedded auth.**
504
- `designer_auth_remove` deletes the auth files (`login.html`, `signup.html`, the
505
- forget-password overlay, `js/rfx_auth.js`) and strips the guard from existing
506
- pages. Under MCP it runs with `--force` (no interactive prompt), so confirm the
507
- project name and intent with the user **before** calling it.
508
-
509
- **8. Execute through tools; never emulate them.** The bundled `references/` help
510
- you *understand* options — they do not replace the tools. When a tool can produce
511
- or validate an artifact (`codegen_dbschema_template`/`init`,
512
- `codegen_generate_payload`, any `*_validate_*`), **call it**; do not hand-write its
513
- output by reading a reference. Emulating the generator is slower, loses
514
- determinism, and drifts from what the installed version emits. If the tool is not
515
- available, stop (see Preflight) rather than improvising from the references.
516
-
517
- ---
518
-
519
- ## Prerequisites and Common Errors
520
-
521
- ### Environment prerequisites
522
-
523
- - Node.js ≥ 18.
524
- - A reachable database matching the configured `DB_TYPE` (PostgreSQL, MySQL,
525
- Oracle, or SQLite).
526
- - A valid RESTForge license for `codegen_*`, `runtime_*`, and
527
- `setup_validate_config`. Designer tools do not require a license.
528
- - The RESTForge MCP server registered in the client
529
- (`npm install -g @restforgejs/mcp-server`, then registered as the `restforge`
530
- MCP server). Without it, none of the tools below exist.
531
- - Redis if using cache, distributed lock, or live sync.
532
- - Kafka if using a Kafka consumer (`KAFKA_ENABLED=true`).
533
-
534
- ### Required backend config parameters
535
-
536
- Nine of the full parameter set are mandatory before `setup_validate_config` can
537
- pass:
538
-
539
- `LICENSE`, `SERVER_ADDRESS`, `SERVER_PORT`, `DB_TYPE`, `DB_HOST`, `DB_PORT`,
540
- `DB_USER`, `DB_PASSWORD`, `DB_NAME`.
541
-
542
- → references/config-schema.md for the full parameter list.
543
-
544
- ### Common error patterns
545
-
546
- | Symptom | Cause | Recovery |
547
- |---|---|---|
548
- | Tool not found / no `codegen_*` tools available | MCP server not registered in the client | Install `@restforgejs/mcp-server`, register it as the `restforge` MCP server, restart the client |
549
- | "authenticity check failed" / HTTP 401 | License not active or expired | Set `LICENSE` in `config/db-connection.env`, run `setup_validate_config` |
550
- | HTTP 429 from license server | Rate limit (10 req/min/IP) | Expected since v5.1.15 — the client falls back to cache; wait or retry |
551
- | DB connection failed | Wrong DB config or DB not running | Check `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`; verify the DB is running |
552
- | "softDelete contract violation" | Contract columns missing or wrong type | Fix the SDF declaration, run `codegen_dbschema_validate` |
553
- | "Widget uses undeclared placeholder" | `:paramName` in SQL not in `params` | Add the entry to `params` in the dashboard payload |
554
- | "tableName and widgets conflict" | Payload contains both | Dashboard uses `widgets`; CRUD uses `tableName` — remove the wrong one |
555
- | 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 |
556
-
557
- When an error is not in this table, do not guess a fix. Re-run the relevant
558
- `*_validate_*` tool, read its message, and ground against the catalog before
559
- changing the definition.
1
+ ---
2
+ name: restforge
3
+ description: >
4
+ RESTForge end-to-end workflow — use for any task involving RESTForge: SDF
5
+ (Schema Definition File), RDF (Resource Definition File), UDF (UI Definition
6
+ File), dbschema, defineModel, codegen, payload, generate endpoint, generate
7
+ dashboard, generate frontend, migrate schema, setup project, add authentication
8
+ (project auth backend, embedded rfx_auth frontend auth), or design-to-SDF
9
+ (deriving a schema from an HTML mockup, screenshot, image, or UI design). Also
10
+ active for the codegen_*, designer_*, setup_*, runtime_* MCP tools and the
11
+ @restforgejs/platform / @restforgejs/mcp-server packages. Defines the canonical
12
+ operation order for the backend track (setup → schema → payload → codegen →
13
+ runtime) and the frontend track (init → udf → validate → generate), the
14
+ grounding-first catalog rules, decision branches, and destructive-operation
15
+ guardrails. Active whenever working on a RESTForge project, not only when the
16
+ word "skill" is mentioned.
17
+ license: MIT
18
+ compatibility: >
19
+ Requires the RESTForge MCP server (@restforgejs/mcp-server) registered in the
20
+ client, plus a RESTForge license for codegen_*, runtime_*, and
21
+ setup_validate_config operations. Designer tools do not require a license.
22
+ ---
23
+
24
+ ## Mental Model
25
+
26
+ RESTForge is a deterministic, definition-first generator with two output tracks:
27
+
28
+ - **Backend track** — SDF defines the database schema; RDF defines REST API
29
+ endpoints. One SDF produces identical DDL; one RDF payload produces an
30
+ identical endpoint module on every execution.
31
+ - **Frontend track** — UDF defines the frontend application. One UDF payload
32
+ produces identical HTML/JS/CSS via `npx restforge-designer`, plugin-driven,
33
+ no build step required.
34
+
35
+ The agent interacts with the platform **exclusively through MCP tools**. The
36
+ agent does not write generation code itself, does not modify generated output,
37
+ and does not guess options outside the catalog. All valid options come from the
38
+ catalog returned by grounding tools.
39
+
40
+ The platform exposes its capabilities as MCP tools grouped by domain: `health_*`,
41
+ `setup_*`, `codegen_*`, `runtime_*`, `designer_*`, `data_*`, `key_*`,
42
+ `project_*`, `license_*`. Two facts follow from this and shape every task:
43
+
44
+ 1. **The skill describes intent and order; the MCP server executes.** If the
45
+ RESTForge MCP server is not registered in the client, this skill cannot do
46
+ anything — there is nothing to call. Confirm the tools are available before
47
+ planning a multi-step operation.
48
+ 2. **The catalog is the source of truth, not memory.** Field types, constraints,
49
+ validation rules, and plugin capabilities belong to the *installed* platform
50
+ version. Always ground against the catalog before proposing definition
51
+ content (see Grounding-First Rules, below).
52
+
53
+ ---
54
+
55
+ ## Preflight (run before any RESTForge task)
56
+
57
+ Verify readiness before planning or producing anything:
58
+
59
+ 1. **Are the RESTForge MCP tools present?** If `codegen_*` / `designer_*` are not
60
+ in your available tools, the MCP server is **not active**. Stop and tell the
61
+ user to register the RESTForge MCP server and restart the client. Do **not**
62
+ finish the task by hand-reading the bundled `references/` — that bypasses the
63
+ generator and yields slower, non-deterministic output.
64
+ 2. **Backend work** → confirm the project and config are ready with
65
+ `runtime_detect_project`, list the candidate `.env` files in `config/` with
66
+ `runtime_detect_config` when the config to use is not obvious, then the
67
+ `setup_validate_config` gate.
68
+ 3. **Before writing a launcher** → `runtime_validate_preflight`. It re-runs the
69
+ config validation and adds the two runtime-only checks the gate does not
70
+ cover: a possibly-running server (`.restforge/server.pid`) and availability
71
+ of the local port. Use it as the last check before `runtime_generate_launcher`,
72
+ not as a replacement for the `setup_validate_config` gate earlier in the run.
73
+ 4. **License questions** → `license_info` reports the activation stored on this
74
+ machine (key, e-mail, type, machine id, last validation, expiry) and changes
75
+ nothing. Repeat the key, e-mail, or machine id back to the user only when
76
+ they asked for them. Activation and `license deactivate` are deliberately
77
+ **not** wrapped by MCP — deactivation frees a machine slot across machines,
78
+ so the user runs it in their own terminal.
79
+ 5. **Frontend work** → the Designer tools pre-check that `npx restforge-designer`
80
+ can run (its binary is bundled in `@restforgejs/platform`, so it is available
81
+ once the project is created with `npx create-restforge-app` / the platform is
82
+ installed); if it cannot run, surface that before proceeding.
83
+
84
+ If a prerequisite is missing, report it as the next step — do not improvise around it.
85
+
86
+ ---
87
+
88
+ ## Backend Pipeline (canonical)
89
+
90
+ This is the canonical (golden) path. For state-dependent choices see Decision
91
+ Points; for failure handling see Guardrails and Common Errors.
92
+
93
+ The sequence below applies to a **new project from scratch**. For an existing
94
+ project, start from the step that matches the current state — do not re-run
95
+ earlier steps that already succeeded.
96
+
97
+ ```
98
+ 1. npx create-restforge-app <name> ── PRIMARY ── human-run scaffolder
99
+ One shot: creates the project folder, runs
100
+ npm install @restforgejs/platform (local), and bundles the designer
101
+ binary. This is the dominant way to start a new project.
102
+ Granular alternative (agent scaffolds step by step):
103
+ setup_create_folder → create the project folder.
104
+
105
+ 2. setup_install_package (granular path only)
106
+ Install @restforgejs/platform into the folder. SKIP when the project
107
+ was created with create-restforge-app (already installed). Plain
108
+ 'npm install @restforgejs/platform' stays valid but is not the
109
+ primary entry point.
110
+
111
+ 3. setup_init_config
112
+ Write config/db-connection.env from the default template.
113
+ setup_get_init_template returns that same template WITHOUT writing a
114
+ file — use it to compare an edited config against the defaults.
115
+
116
+ 4. setup_write_env / setup_update_env
117
+ Set values: LICENSE, SERVER_ADDRESS, SERVER_PORT, DB_TYPE,
118
+ DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME (9 required parameters).
119
+ Use setup_read_env to read existing values before overwriting.
120
+ Grounding for the full parameter set: setup_get_config_schema.
121
+
122
+ 5. setup_validate_config
123
+ ── GATE ── Must pass before any codegen_* operation starts.
124
+ Validates database connection and license. Running codegen before this
125
+ gate passes produces uninformative errors.
126
+ Read-only by default. Set autoCreateDb=true only when the target database
127
+ itself does not exist yet AND the user agreed to have it created: it runs
128
+ CREATE DATABASE on the server (postgres/mysql only, ignored for sqlite and
129
+ oracle), and validation has to be repeated afterwards.
130
+
131
+ 6. codegen_get_dbschema_catalog
132
+ ── GROUNDING ── Source of truth before defining SDF: field types,
133
+ constraints, shorthand syntax, relations, referential actions,
134
+ check operations, and the soft-delete contract.
135
+ → references/dbschema-catalog.md
136
+
137
+ 7a. codegen_dbschema_init (empty DB — scaffold SDF with audit columns)
138
+ codegen_dbschema_template (minimal template, no DB connection required)
139
+ 7b. codegen_list_tables (existing DB — what is actually in there)
140
+ → codegen_describe_table (columns, PK, FKs, indexes of one table)
141
+ → codegen_dbschema_introspect (generate SDF from the actual schema)
142
+ list/describe are read-only catalog reads: they answer "what does this
143
+ database already hold?" without writing an SDF file. Use them before
144
+ introspecting a subset, and whenever a question about an existing table
145
+ would otherwise be answered from memory.
146
+
147
+ 8. codegen_dbschema_validate
148
+ Validate SDF before any DDL is generated. Catch errors here, not at migrate.
149
+ codegen_dbschema_models (optional) lists the models already defined in the
150
+ SDF files with field count, primary key kind, indexes, uniques, relations.
151
+
152
+ 9. codegen_dbschema_generate_ddl (optional — preview DDL without executing)
153
+
154
+ 10a. codegen_dbschema_migrate (empty DB — apply DDL directly)
155
+ 10b. codegen_dbschema_diff (existing DB — review the differences first)
156
+ → codegen_dbschema_apply (apply only after confirming the drift)
157
+
158
+ 11. codegen_get_field_validation_catalog
159
+ ── GROUNDING ── before defining fieldValidation in a payload.
160
+ → references/field-validation.md
161
+
162
+ 12. codegen_get_query_declarative_catalog
163
+ ── GROUNDING ── when the payload contains datatablesQuery, viewQuery,
164
+ viewName, exportQuery, or detailQuery.
165
+ codegen_validate_sql
166
+ Check the SELECT / WITH statement against the live database (EXPLAIN, no
167
+ rows executed) BEFORE pasting it into the payload: syntax, column
168
+ 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
+
172
+ 13. codegen_generate_payload
173
+ Generate payload JSON from a table. Foundation for all subsequent
174
+ codegen operations.
175
+
176
+ 14. codegen_validate_payload
177
+ Validate the payload before codegen. Catch errors here.
178
+
179
+ 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)
182
+
183
+ 16a. codegen_create_endpoint (standard CRUD module)
184
+ Leave 'database' UNSET unless the user named a database: the CLI then
185
+ auto-detects DB_TYPE from the active config (fallback postgres), so a
186
+ MySQL/Oracle/SQLite project generates for its own dialect. 'config'
187
+ selects that .env explicitly. createDemo (default true) writes the
188
+ 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.
192
+ 16b. codegen_get_dashboard_catalog
193
+ → codegen_validate_dashboard_payload
194
+ ── 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.
199
+ → codegen_create_dashboard (analytic dashboard with SQL widgets)
200
+ No database auto-detection here: the dashboard command uses 'database'
201
+ when given and plain postgres otherwise, so pass it whenever the project
202
+ is not postgres. force defaults to true and then re-registers the project
203
+ under the database type carried by this call; force=false refuses cleanly
204
+ instead of writing.
205
+ 16c. codegen_create_processor (background processing)
206
+ 16d. codegen_create_kafka_consumer (Kafka event streaming)
207
+ → runtime_generate_consumer_launcher
208
+ Prepare a way to RUN that consumer: mode=host writes the fixed
209
+ consumer-start/consumer-stop pair in the project root, mode=pm2 produces
210
+ ecosystem.config.js + consumer-manager.sh in ./deploy/. 'config' is
211
+ required and must end with .env.
212
+ → (user runs the consumer) — the agent never starts it, same rule as the
213
+ server launcher below.
214
+
215
+ 17. codegen_generate_test (optional)
216
+ Jest + Supertest integration test for an endpoint that ALREADY exists.
217
+ Natural follow-up once the module is generated.
218
+
219
+ 18. project_sdk_generate (optional)
220
+ Write the JavaScript SDK source for the project (one resource file per
221
+ registered endpoint, plus client.auth when the backend auth extension is
222
+ installed) so a frontend calls client.<resource>.<verb>(payload). Source
223
+ only: the user runs install / build / deploy. Without force it refuses
224
+ when an SDK exists; with force=true it overwrites IN PLACE with no
225
+ archive, so local edits in the SDK folder are lost.
226
+
227
+ 19. runtime_check_launcher_exists → runtime_validate_preflight
228
+ → runtime_generate_launcher
229
+ Check what is already there (read-only), validate the runtime
230
+ prerequisites, then write the launcher script. The agent STOPS here. The
231
+ user executes the launcher — the server runs independently of the agent
232
+ session.
233
+
234
+ 20. (user executes the launcher)
235
+
236
+ 21. runtime_check_status
237
+ Verify the server is running and endpoints are reachable.
238
+ ```
239
+
240
+ Two hard checkpoints (see Guardrails): **step 5** is a gate — no `codegen_*` call
241
+ before `setup_validate_config` passes; **step 19** is where the agent stops (it
242
+ generates the launcher, never runs the server).
243
+
244
+ **Payload naming differs per generator** — the value is handed to the CLI and
245
+ each verb resolves it differently:
246
+
247
+ | Tool | Accepted form |
248
+ |---|---|
249
+ | `codegen_create_endpoint`, `codegen_create_processor` | bare name, with or without `.json`; lowercased by the CLI; path forms are rejected |
250
+ | `codegen_create_dashboard`, `codegen_validate_dashboard_payload` | name or relative path **with** the extension, used verbatim (`dash-sales.json`, `payload/dash-sales.json`) — nothing is appended |
251
+ | `codegen_create_kafka_consumer` | name or path |
252
+
253
+ **Config selection across calls.** Most backend tools take an optional `config`
254
+ and otherwise fall back to the default recorded per working directory in
255
+ `.restforge/defaults.json`. Manage that default instead of repeating the file
256
+ name on every call: `setup_list_configs` (which `.env` files exist),
257
+ `setup_set_default_config` (record one), `setup_get_default_config` (which one is
258
+ active), `setup_clear_default_config` (remove it — afterwards every call must
259
+ name its config explicitly).
260
+
261
+ ---
262
+
263
+ ## Frontend Pipeline (canonical)
264
+
265
+ This is the canonical (golden) path for the frontend track. It runs
266
+ **independently** from the backend pipeline. The backend API must be running and
267
+ reachable at `apiBaseUrl` before the generated frontend is useful, but the
268
+ frontend can be defined and generated without the backend live.
269
+
270
+ ```
271
+ 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).
274
+ → references/udf-catalog.md § Plugins
275
+
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.
279
+
280
+ 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.
284
+ → references/udf-catalog.md
285
+
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.
289
+
290
+ 5. designer_validate_payload
291
+ ── GATE ── validate the UDF payload. Catches structural errors before
292
+ generation. Run before preview or generate, every time.
293
+
294
+ 6. designer_preview_files
295
+ Dry-run: list files that would be generated, without writing to disk.
296
+ Use to verify scope before an overwrite.
297
+
298
+ 7. designer_generate
299
+ Generate frontend HTML/JS/CSS from the UDF payload. Writes output files.
300
+ The agent STOPS here — the user opens the output in a browser.
301
+ ```
302
+
303
+ For plugin development (custom output plugins):
304
+
305
+ ```
306
+ designer_scaffold_plugin → [develop plugin templates]
307
+ → designer_inspect_plugin (verify plugin metadata and capabilities)
308
+ → designer_generate (test generation with the custom plugin)
309
+ ```
310
+
311
+ Two checkpoints (see Guardrails): **step 5** is a gate — never `designer_generate`
312
+ an unvalidated payload; **step 7** is where the agent stops (generates files, does
313
+ not serve or deploy).
314
+
315
+ Licensing note: the Designer tools (`designer_preview_files`, `designer_generate`,
316
+ etc.) do **not** require a RESTForge license, unlike the `codegen_*`, `runtime_*`,
317
+ and `setup_validate_config` tools on the backend track.
318
+
319
+ ---
320
+
321
+ ## Auth Extension
322
+
323
+ RESTForge has **two different auth mechanisms — do not confuse them.** Pick the
324
+ right one; never describe one as the other, and never claim the extension does RBAC.
325
+
326
+ | Mechanism | RBAC? | How |
327
+ |---|---|---|
328
+ | **Plugin auth** — built into the frontend at generation time | **Yes (auth + RBAC)** | `vanilla-js-auth` or `vanilla-js-custom` plugin in `designer_init_project`; disable with `noAuth: true` (`--no-auth`) |
329
+ | **Auth extension** — bolt-on added to an existing project | **No RBAC** | backend `project_auth`; frontend `designer_auth_create` (embedded `rfx_auth`) |
330
+
331
+ Confirm which plugins provide auth with `designer_list_plugins` — do not hardcode
332
+ it. The rest of this section covers the **extension** (the no-RBAC bolt-on); for
333
+ plugin auth see Decision Points § Frontend plugin choice. Google Sign-In and
334
+ `@restforgejs/auth` are out of scope for the extension.
335
+
336
+ ### Backend auth — `project_auth`
337
+
338
+ Adds the auth backend to an existing RESTForge project (run the standard backend
339
+ pipeline first; the project and its endpoint must already exist, and the DB must
340
+ be active).
341
+
342
+ ```
343
+ project_auth (wraps: npx restforge project auth --create --project=<name>)
344
+ ```
345
+
346
+ Installs auth SDF (`rfx`), DB tables, middleware, router, six processors
347
+ (register/login/refresh/logout/me/reset-password), a random `JWT_SECRET`, and
348
+ `bcrypt`+`jsonwebtoken`. Idempotent. → references/auth.md § Backend
349
+
350
+ ### Frontend auth — `designer_auth_create` / `designer_auth_remove`
351
+
352
+ Adds (or removes) an **embedded** login / signup / forget-password overlay
353
+ (`rfx_auth`) on an existing frontend project, at route
354
+ `/api/<project>/rfx_auth`. This is independent of the `vanilla-js-auth` plugin.
355
+
356
+ ```
357
+ designer_auth_create (wraps: npx restforge-designer auth --create --project=<name>)
358
+ designer_auth_remove (wraps: npx restforge-designer auth --remove --project=<name> --force)
359
+ ```
360
+
361
+ `create` writes the auth pages + `js/rfx_auth.js` and injects a guard into existing
362
+ pages; `remove` deletes them. Idempotent. Runs via `npx restforge-designer`
363
+ (bundled in `@restforgejs/platform`; available once the project was created with
364
+ `npx create-restforge-app` / the platform is installed).
365
+ → references/auth.md § Frontend
366
+
367
+ ### Retrofit on a generated app — `designer_auth_attach`
368
+
369
+ ```
370
+ designer_auth_attach (wraps: npx restforge-designer auth --attach --project=<name>)
371
+ ```
372
+
373
+ The "turn auth on afterwards" path for an app whose pages already exist. It
374
+ installs `js/rfx_auth.js`, injects the script tag into the existing pages (except
375
+ the login page), and writes the `embeddedAuth` marker — **page files themselves
376
+ are never touched**, so customisations survive. When the project payload has an
377
+ auth block on an auth-capable plugin (`vanilla-js-auth` / `vanilla-js-custom`) it
378
+ additionally renders the plugin login artifacts (`js/auth.js`, `login.html`,
379
+ `js/login.js`) and extends `js/config.js` with a marked block; in that mode the
380
+ `rfx_auth` login/signup pages are not written, and the storage key is aligned with
381
+ the plugin login so both sides read the same session. Idempotent — existing files
382
+ are skipped unless `overwrite` is set.
383
+
384
+ Pick between the two: `designer_auth_create` when the app just needs a standalone
385
+ login/signup overlay and no auth-capable plugin is in play;
386
+ `designer_auth_attach` when the pages already exist, the plugin is
387
+ `vanilla-js-auth` / `vanilla-js-custom`, or `designer_generate` reported missing
388
+ auth artifacts. The CLI accepts exactly one of `--create` / `--attach` /
389
+ `--remove` per invocation.
390
+
391
+ Do not combine the two mechanisms on one app: if an app already has plugin auth
392
+ (`vanilla-js-auth` / `vanilla-js-custom`), do not also add embedded `rfx_auth`.
393
+
394
+ ---
395
+
396
+ ## Grounding-First Rules
397
+
398
+ Before reasoning about, proposing, or generating any **definition content** —
399
+ SDF fields, RDF `fieldValidation`, queries, dashboard widgets, or UDF pages —
400
+ call the matching grounding tool first and use only what it returns. Never write
401
+ definition content from memory.
402
+
403
+ | Context | Grounding tool | Reference |
404
+ |---|---|---|
405
+ | Defining or reviewing SDF | `codegen_get_dbschema_catalog` | references/dbschema-catalog.md |
406
+ | Deriving SDF from a UI design (HTML / image / screenshot) | `codegen_get_dbschema_catalog` | references/design-to-sdf.md |
407
+ | Defining `fieldValidation` in an RDF payload | `codegen_get_field_validation_catalog` | references/field-validation.md |
408
+ | Defining queries in an RDF payload | `codegen_get_query_declarative_catalog` | — |
409
+ | Defining a dashboard payload | `codegen_get_dashboard_catalog` | — |
410
+ | Defining UDF (frontend) | `designer_get_udf_catalog` | references/udf-catalog.md |
411
+ | Listing available frontend plugins | `designer_list_plugins` | references/udf-catalog.md § Plugins |
412
+ | Setting `db-connection.env` parameters | `setup_get_config_schema` | references/config-schema.md |
413
+
414
+ **Why this rule exists.** The catalog is the source of truth for valid options
415
+ in the *installed* platform version. Reasoning without it produces confident but
416
+ wrong output — field types that do not exist, constraints not applicable to a
417
+ type, or wrong semantics. Two concrete failure modes this rule prevents:
418
+
419
+ - **Inventing options.** Without grounding, an agent may write a made-up key
420
+ (e.g. `"toUpper": true`) that the validator rejects. The catalog gives the
421
+ exact key and value type.
422
+ - **Misreading semantics.** A constraint can mean something different from its
423
+ plain-English name. For example, `uppercase` on a `string` field is a
424
+ *normalization transform* (it forces the stored value to upper case), grouped
425
+ with `trim` and `lowercase` — it is **not** a validator that rejects
426
+ non-uppercase input. If the user wants rejection, the answer is `pattern`, not
427
+ `uppercase`; if they want database-level enforcement, that is an SDF check
428
+ constraint, not RDF `fieldValidation`. Grounding surfaces this distinction
429
+ before the agent commits to the wrong one.
430
+
431
+ The reference files help you *understand* the catalog; they do **not** replace
432
+ the tool. Call the tool to ground, produce, and validate — do not hand-produce
433
+ output a tool would generate. The live tool is authoritative; when a reference and
434
+ the tool disagree, trust the tool.
435
+
436
+ ---
437
+
438
+ ## Decision Points
439
+
440
+ Use these to pick the correct branch when the request is state-dependent. Each
441
+ branch still obeys the Grounding-First Rules above.
442
+
443
+ ### Schema (SDF)
444
+
445
+ - **DB does not exist** → `codegen_dbschema_init` (scaffold with audit columns)
446
+ or `codegen_dbschema_template` (minimal template, no DB connection required).
447
+ - **DB already exists** → `codegen_dbschema_introspect` to generate SDF from the
448
+ actual schema. Do not hand-write a schema that a real DB can describe.
449
+ - **Question about what the DB already contains** → `codegen_list_tables` (tables
450
+ and views) and `codegen_describe_table` (columns, primary key, foreign keys,
451
+ indexes of one table). Both are read-only live introspection; they are the
452
+ safe way to answer such a question without generating anything.
453
+ - **Starting from a UI design** (HTML mockup, screenshot, image, Figma export)
454
+ → first confirm the design is an entity to model, not a dashboard/analytics
455
+ screen (those map to the Dashboard RDF branch below, not to a new SDF table).
456
+ Then classify visible elements into stored / derived / relation / audit, draft
457
+ the SDF, and run `codegen_dbschema_validate`. The design shows presentation,
458
+ not storage — do not turn every visible label into a column.
459
+ → 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.
463
+
464
+ ### RDF Payload
465
+
466
+ - **No payload yet** → `codegen_generate_payload`.
467
+ - **Payload exists, edit is API-layer only** (e.g. add/adjust `fieldValidation`,
468
+ messages, or a query — no column added or dropped) → ground via the matching
469
+ catalog, edit `payload.json`, run `codegen_validate_payload`, then regenerate
470
+ with `codegen_create_endpoint`. No DB migration: the schema (SDF) is unchanged.
471
+ - **Payload exists, DB schema changed** → `codegen_diff_payload` first, then
472
+ `codegen_sync_payload` (non-breaking) or `codegen_migrate_payload` (breaking).
473
+ - **Custom query needed** → ground via `codegen_get_query_declarative_catalog`,
474
+ check the statement with `codegen_validate_sql` against the live database, then
475
+ set `datatablesQuery`, `viewQuery`, or `exportQuery` in the payload. External
476
+ SQL files use the `file:` prefix
477
+ (e.g. `"datatablesQuery": "file:sql/orders.sql"`). Validating first turns a
478
+ runtime 500 into an error message before the payload is even written.
479
+
480
+ > **"Add an uppercase / case constraint" is ambiguous — disambiguate first.**
481
+ > In RESTForge `uppercase` is an RDF `fieldValidation` *normalization transform*
482
+ > (forces the stored value to upper case), not a reject-if-not-uppercase
483
+ > validator. If the user wants rejection, use `pattern`. If the user wants the
484
+ > database to enforce it, that is an SDF check constraint, not RDF. Confirm which
485
+ > one is meant before editing — see Grounding-First Rules § Misreading semantics.
486
+
487
+ ### Backend module type
488
+
489
+ - **Standard CRUD** → `codegen_create_endpoint`. One payload = one module.
490
+ - **Analytic dashboard** → `codegen_validate_dashboard_payload`, then
491
+ `codegen_create_dashboard`. Payload must have `widgets` (not `tableName`); page
492
+ name must be prefixed `dash-`; the payload argument keeps its `.json`
493
+ extension.
494
+ - **Background job** → `codegen_create_processor`.
495
+ - **Kafka event consumer** → `codegen_create_kafka_consumer`; requires
496
+ `KAFKA_ENABLED=true` in config. The consumer runtime is a separate process:
497
+ `runtime_generate_consumer_launcher` prepares it (host scripts or PM2 deploy
498
+ files) and the user starts it.
499
+ - **JavaScript client for a generated project** → `project_sdk_generate`. Run it
500
+ after the endpoints exist, and after `project_auth` when the project needs
501
+ auth, so `client.auth` is included.
502
+ - **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.
505
+ → references/rdf-advanced.md § Workflow
506
+ - **Master-detail (composite CRUD)** → add `details[]` to the RDF payload;
507
+ generates `/create-composite`, `/update-composite`, `/read-composite`.
508
+ → references/rdf-advanced.md § Master-Detail
509
+ - **Excel export** → `/export` works by default (falls back to
510
+ `SELECT {fields} FROM tableName`); customise the columns/filter with
511
+ `exportQuery` in the RDF payload. Tune `EXPORT_FILE_EXPIRY` / `EXPORT_CHUNK_SIZE`
512
+ in config. Ground `exportQuery` via `codegen_get_query_declarative_catalog`.
513
+ → 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
518
+ - Activate on an existing project: edit the payload to add `importConfig`
519
+ (and/or `exportQuery`) → `codegen_validate_payload` → `codegen_create_endpoint`.
520
+
521
+ ### Soft-delete vs hard-delete
522
+
523
+ - Use soft-delete when deleted rows must be audited or recoverable. Declare
524
+ `softDelete: { enabled: true }` in SDF and add the three contract columns
525
+ (`is_deleted`, `deleted_at`, `deleted_by`).
526
+ - Soft-delete is supported on PostgreSQL only (Phase 1).
527
+ - Tables with composite UNIQUE constraints are incompatible with soft-delete.
528
+
529
+ ### Data seeding / migration (rows, not schema)
530
+
531
+ Move table **rows** through SDF-driven envelope files. This is for data, never
532
+ for schema — use the dbschema tools for structure.
533
+
534
+ **Default output location:** `data-storage/<schema>/<table>.json`, relative to the
535
+ project cwd. The `data-storage` folder is the default of the `storagePath` param
536
+ (CLI `--storage-path <folder>`); override it to write elsewhere. The SDF read from
537
+ is `schemaPath` (CLI `--schema-path`, default `schema`).
538
+
539
+ - **Export / dump / snapshot / back up rows** → `data_pull`. Scope is exactly one
540
+ of `table`, `schema`, or `allSchemas`. Only tables registered in the SDF can be
541
+ pulled. `force: true` overwrites existing envelope files. Optional `limit`,
542
+ `batchSize`, `config` (falls back to the default set via `config set-default`,
543
+ i.e. `.restforge/defaults.json`), `schemaPath`, `storagePath`.
544
+ - **Import / load / seed / restore rows** → `data_push`. Same file names as
545
+ `data_pull`, so pulled files push back directly. Scope is exactly one of `table`,
546
+ `schema`, or `allSchemas`; for `schema`/`allSchemas` tables load in FK
547
+ parent→child order.
548
+ - **Move data between databases** → `data_pull` from the source, then `data_push`
549
+ into the target (`config` selects the env per side).
550
+ - ⚠ `data_push` is **APPEND-ONLY** (batch INSERT, no upsert/replace). Running it
551
+ twice inserts the rows twice. Confirm with the user before pushing into a
552
+ database that may already hold those rows.
553
+
554
+ ### Frontend page type
555
+
556
+ - **Standard CRUD page** → `pageType: "crud"` (default) with `apiPath`,
557
+ `primaryKey`, `displayField`, and `fields[]`.
558
+ - **Dashboard page** → `pageType: "dashboard"` with `dataSources[]` and `rows[]`
559
+ containing widget columns.
560
+ → references/udf-catalog.md § Dashboard Page
561
+ - **Page with approval workflow** → add `workflow.statusField` and
562
+ `workflowActions[]` to the page.
563
+
564
+ ### Frontend plugin choice
565
+
566
+ - **No auth** → `vanilla-js-basic`.
567
+ - **Auth WITH RBAC, built into the app** → `vanilla-js-auth` or
568
+ `vanilla-js-custom` at `designer_init_project`. Use `noAuth: true` (`--no-auth`)
569
+ to get the plugin's UI without its auth.
570
+ - **Custom branding / new plugin** → `designer_scaffold_plugin`.
571
+ - **Bolt-on auth WITHOUT RBAC** → not a plugin; see Authentication below.
572
+ → references/udf-catalog.md § Plugins
573
+
574
+ ### Authentication
575
+
576
+ - **Needs RBAC** → plugin auth (`vanilla-js-auth` / `vanilla-js-custom`) at
577
+ `designer_init_project`. The extension below does **not** do RBAC.
578
+ - **Backend auth on an existing project (no RBAC)** → `project_auth` (after the
579
+ project and its endpoint exist, with an active DB).
580
+ - **Frontend auth on an app built WITHOUT plugin auth (no RBAC)** →
581
+ `designer_auth_create` (embedded `rfx_auth`).
582
+ - **Remove embedded frontend auth** → `designer_auth_remove` — destructive,
583
+ confirm first (see Guardrails).
584
+
585
+ ---
586
+
587
+ ## Guardrails
588
+
589
+ These are hard rules. They override convenience and override an eager reading of
590
+ the user's request. When a guardrail conflicts with finishing faster, the
591
+ guardrail wins.
592
+
593
+ **1. Confirm before destructive operations.**
594
+ The following require explicit user confirmation before execution:
595
+
596
+ - `codegen_dbschema_migrate` or `codegen_dbschema_apply` that drops a table or
597
+ column, or alters a column in a way that loses data.
598
+ - `project_delete` — permanent project deletion.
599
+ - `project_sdk_generate` with `force: true` — the SDK files are rewritten in
600
+ place with **no** archive backup, so hand edits inside the SDK folder are lost,
601
+ and resource files of endpoints that no longer exist are left behind.
602
+ - `setup_validate_config` with `autoCreateDb: true` — it runs CREATE DATABASE on
603
+ the database server. The default call is read-only.
604
+
605
+ `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
609
+ already exists: the endpoint command then stops at its confirmation question
610
+ without writing, and the dashboard command refuses with a clean error.
611
+
612
+ For schema changes, run `codegen_dbschema_diff` first, present a summary of the
613
+ destructive parts (dropped tables/columns, type narrowing), and wait for
614
+ confirmation before calling `codegen_dbschema_apply`. Never infer approval from
615
+ the original request — "update the schema" is not consent to drop a column.
616
+
617
+ **2. The agent does not run the server.**
618
+ The agent's last step on the backend track is `runtime_generate_launcher`. The
619
+ user executes the launcher in their own terminal. The agent never calls shell
620
+ commands to start, stop, or restart the server, and never assumes the server is
621
+ running — verify with `runtime_check_status` instead. The same rule covers the
622
+ Kafka consumer runtime: `runtime_generate_consumer_launcher` only writes the
623
+ scripts or the PM2 deploy files; starting the consumer belongs to the user. A
624
+ process spawned from an agent session dies with the session.
625
+
626
+ **3. The `validate_config` gate is mandatory.**
627
+ `setup_validate_config` must pass before any `codegen_*` operation starts. Do not
628
+ skip it "to save a step" — running codegen against an invalid config produces
629
+ uninformative errors that cost more time than the gate.
630
+
631
+ **4. Validate before generating.**
632
+ Always run `codegen_validate_payload` before `codegen_create_*`, and
633
+ `designer_validate_payload` before `designer_generate`. For a dashboard payload
634
+ the matching validator is `codegen_validate_dashboard_payload` — the general one
635
+ does not understand the `widgets` shape. Generation on an invalid payload
636
+ produces incomplete or broken output that looks like it succeeded.
637
+
638
+ **5. Stay inside the task scope.**
639
+ Do not modify files outside the requested task. If the change is a backend
640
+ payload edit, do not also "tidy up" the SDF, the runtime, or the frontend. If a
641
+ change genuinely requires touching another area (e.g. an RDF edit that needs a
642
+ new column, which is an SDF change), stop and report the cross-over, then ask
643
+ before expanding scope.
644
+
645
+ **6. Ground before defining — repeated here because it is a guardrail, not a
646
+ suggestion.** Never write SDF fields, `fieldValidation`, queries, dashboard
647
+ widgets, or UDF content from memory. Call the matching catalog tool first (see
648
+ Grounding-First Rules). Inventing an option that "should" exist is the most
649
+ common way to produce confidently wrong output.
650
+
651
+ **7. Confirm before removing embedded auth.**
652
+ `designer_auth_remove` deletes the auth files (`login.html`, `signup.html`, the
653
+ forget-password overlay, `js/rfx_auth.js`) and strips the guard from existing
654
+ pages. Under MCP it runs with `--force` (no interactive prompt), so confirm the
655
+ project name and intent with the user **before** calling it.
656
+
657
+ **8. Execute through tools; never emulate them.** The bundled `references/` help
658
+ you *understand* options — they do not replace the tools. When a tool can produce
659
+ or validate an artifact (`codegen_dbschema_template`/`init`,
660
+ `codegen_generate_payload`, any `*_validate_*`), **call it**; do not hand-write its
661
+ output by reading a reference. Emulating the generator is slower, loses
662
+ determinism, and drifts from what the installed version emits. If the tool is not
663
+ available, stop (see Preflight) rather than improvising from the references.
664
+
665
+ ---
666
+
667
+ ## Tools outside this skill's workflows
668
+
669
+ These MCP tools exist and are callable, but they are not steps of the backend or
670
+ frontend pipeline. They are listed here so their absence from the pipelines reads
671
+ as a decision, not an omission — call them when the user asks for exactly that,
672
+ not as part of a generation run.
673
+
674
+ | Tool | Why it is outside the pipeline |
675
+ |---|---|
676
+ | `health_ping` | Transport smoke test — answers "is the MCP server itself responsive", touches nothing in RESTForge |
677
+ | `key_generate`, `key_list`, `key_revoke` | API key bookkeeping inside `.env` files; independent of definition files and code generation |
678
+ | `project_list` | Registry inventory (endpoint count, database type, creation date) — useful for orientation, never a prerequisite of a later step |
679
+
680
+ `license deactivate` has no MCP tool at all, on purpose: it frees a machine slot
681
+ across machines, so the user runs it manually. `license_info` (read-only) is the
682
+ wrapped half of that pair.
683
+
684
+ ---
685
+
686
+ ## Prerequisites and Common Errors
687
+
688
+ ### Environment prerequisites
689
+
690
+ - Node.js ≥ 18.
691
+ - A reachable database matching the configured `DB_TYPE` (PostgreSQL, MySQL,
692
+ Oracle, or SQLite).
693
+ - A valid RESTForge license for `codegen_*`, `runtime_*`, and
694
+ `setup_validate_config`. Designer tools do not require a license.
695
+ - The RESTForge MCP server registered in the client
696
+ (`npm install -g @restforgejs/mcp-server`, then registered as the `restforge`
697
+ MCP server). Without it, none of the tools below exist.
698
+ - Redis if using cache, distributed lock, or live sync.
699
+ - Kafka if using a Kafka consumer (`KAFKA_ENABLED=true`).
700
+
701
+ ### Required backend config parameters
702
+
703
+ Nine of the full parameter set are mandatory before `setup_validate_config` can
704
+ pass:
705
+
706
+ `LICENSE`, `SERVER_ADDRESS`, `SERVER_PORT`, `DB_TYPE`, `DB_HOST`, `DB_PORT`,
707
+ `DB_USER`, `DB_PASSWORD`, `DB_NAME`.
708
+
709
+ → references/config-schema.md for the full parameter list, and
710
+ `setup_get_config_schema` for the live version of it.
711
+
712
+ ### Tools that depend on the installed platform version
713
+
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:
716
+
717
+ | Tool | Requirement | Symptom on an older platform |
718
+ |---|---|---|
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 |
721
+
722
+ When `codegen_validate_dashboard_payload` is unavailable, the fallback is
723
+ `codegen_create_dashboard` itself — it runs the same validator before writing.
724
+
725
+ ### Common error patterns
726
+
727
+ | Symptom | Cause | Recovery |
728
+ |---|---|---|
729
+ | Tool not found / no `codegen_*` tools available | MCP server not registered in the client | Install `@restforgejs/mcp-server`, register it as the `restforge` MCP server, restart the client |
730
+ | "authenticity check failed" / HTTP 401 | License not active or expired | Set `LICENSE` in `config/db-connection.env`, run `setup_validate_config` |
731
+ | HTTP 429 from license server | Rate limit (10 req/min/IP) | Expected since v5.1.15 — the client falls back to cache; wait or retry |
732
+ | DB connection failed | Wrong DB config or DB not running | Check `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`; verify the DB is running |
733
+ | "softDelete contract violation" | Contract columns missing or wrong type | Fix the SDF declaration, run `codegen_dbschema_validate` |
734
+ | "Widget uses undeclared placeholder" | `:paramName` in SQL not in `params` | Add the entry to `params` in the dashboard payload |
735
+ | "tableName and widgets conflict" | Payload contains both | Dashboard uses `widgets`; CRUD uses `tableName` — remove the wrong one |
736
+ | 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 |
737
+
738
+ When an error is not in this table, do not guess a fix. Re-run the relevant
739
+ `*_validate_*` tool, read its message, and ground against the catalog before
740
+ changing the definition.