@jskit-ai/agent-docs 0.1.95 → 0.1.97

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.
@@ -196,14 +196,14 @@ The most important parts look like this:
196
196
  "@jskit-ai/jskit-cli": "0.x",
197
197
  "@playwright/test": "1.61.1",
198
198
  "@vitejs/plugin-vue": "^6.0.7",
199
- "eslint": "^9.39.4",
199
+ "eslint": "^10.8.0",
200
200
  "vite": "^8.0.16",
201
201
  "vitest": "^4.1.9"
202
202
  }
203
203
  }
204
204
  ```
205
205
 
206
- Published JSKIT libraries and tooling support Node.js 22 from 22.12.0 onward, Node.js 24, and Node.js 26. Newly generated applications deliberately require Node 26: their app-level `engines` contract, `.nvmrc`, and JSKIT-managed verification workflow all name that runtime. The app-level contract is the runtime boundary for the app and its installed JSKIT runtime packages, while independently consumed JSKIT CLI and tooling packages retain the wider supported range. The dependency on `@local/main` points at `file:packages/main`, which means your app already contains its own local JSKIT package. The maintenance scripts are also useful to notice early, because they show an important ownership boundary in JSKIT.
206
+ Published JSKIT libraries and tooling support Node.js 22 from 22.13.0 onward, Node.js 24, and Node.js 26. Newly generated applications deliberately require Node 26: their app-level `engines` contract, `.nvmrc`, and JSKIT-managed verification workflow all name that runtime. The app-level contract is the runtime boundary for the app and its installed JSKIT runtime packages, while independently consumed JSKIT CLI and tooling packages retain the wider supported range. The dependency on `@local/main` points at `file:packages/main`, which means your app already contains its own local JSKIT package. The maintenance scripts are also useful to notice early, because they show an important ownership boundary in JSKIT.
207
207
 
208
208
  `verify`, `jskit:update`, and `release` are intentionally thin wrappers. They stay in `package.json` because they are convenient app-local shortcuts, but the real implementation lives in `jskit app ...`, not in copied scaffold scripts.
209
209
 
@@ -78,7 +78,7 @@ This gives you a clean ownership split:
78
78
 
79
79
  That split is worth keeping in mind through the rest of the guide. When you see `npm run verify`, read it as "run the app's JSKIT baseline verification policy, then any app-specific extra verification hook".
80
80
 
81
- The starter scaffold also includes `.github/workflows/jskit-verify.yml`. This is a JSKIT-managed projection, not a static template. Installed package descriptors can contribute CI environment values, services, and preparation steps through their top-level `ci` contract. Published JSKIT libraries and tooling support Node.js 22 from 22.12.0 onward, Node.js 24, and Node.js 26, while newly generated applications require Node 26. The managed workflow enforces that application runtime for dependency installation and verification. JSKIT composes the contributions and renders the workflow in this order: checkout, Node 26 setup, `npm ci`, package-contributed `before-verify` steps, and `npm run verify`.
81
+ The starter scaffold also includes `.github/workflows/jskit-verify.yml`. This is a JSKIT-managed projection, not a static template. Installed package descriptors can contribute CI environment values, services, and preparation steps through their top-level `ci` contract. Published JSKIT libraries and tooling support Node.js 22 from 22.13.0 onward, Node.js 24, and Node.js 26, while newly generated applications require Node 26. The managed workflow enforces that application runtime for dependency installation and verification. JSKIT composes the contributions and renders the workflow in this order: checkout, Node 26 setup, `npm ci`, package-contributed `before-verify` steps, and `npm run verify`.
82
82
 
83
83
  For example, `database-runtime` contributes the `database-migrations` step. Its MySQL driver contributes a MariaDB service with `DB_CLIENT=mysql2`, while its Postgres driver contributes a Postgres service with `DB_CLIENT=pg`. Each driver supplies matching synthetic CI-only `DB_*` values; local `.env` values are never copied into the workflow.
84
84
 
@@ -230,6 +230,24 @@ w/[workspaceSlug]/admin/...
230
230
 
231
231
  then `workspace` is usually the normal default. If you are generating a CRUD for a global operator or account area, `public` or `user` may make more sense.
232
232
 
233
+ ## Schema contract for generated CRUD
234
+
235
+ Generated CRUD tables use one single-column integer primary key, normally
236
+ `id`. Each foreign key must also be single-column and must reference the target
237
+ table's single-column primary key. Composite indexes remain useful for business
238
+ uniqueness such as `(workspace_id, slug)`, but they are never relationship
239
+ targets.
240
+
241
+ Tenant isolation comes from a direct `workspace_id` and/or `user_id` ownership
242
+ column, the exactly matching generated ownership filter, scoped service
243
+ lookups, and cross-tenant tests. Do not encode ownership into a composite
244
+ foreign key such as `(workspace_id, parent_id) -> (workspace_id, id)`.
245
+
246
+ The generator rejects unsupported key shapes. If an approved application truly
247
+ needs a different persistence model, record the durable decision in
248
+ `.jskit/APP_BLUEPRINT.md` and use the explicit table-ownership exception path
249
+ instead of modifying generated CRUD files.
250
+
233
251
  ## Example 1: `contacts`
234
252
 
235
253
  This is the baseline pattern. If you understand this example, the rest of the chapter becomes much easier.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.95",
3
+ "version": "0.1.97",
4
4
  "description": "Distributed JSKIT agent references, prompts, guides, and generated reference maps.",
5
5
  "type": "module",
6
6
  "files": [
@@ -14,7 +14,7 @@
14
14
  "test": "node --test"
15
15
  },
16
16
  "engines": {
17
- "node": "^22.12.0 || ^24.0.0 || ^26.0.0"
17
+ "node": "^22.13.0 || ^24.0.0 || ^26.0.0"
18
18
  },
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -14,9 +14,38 @@ Check first:
14
14
  - `jskit show crud-server-generator --details`
15
15
  - whether the request is server-only CRUD or server-plus-UI CRUD
16
16
 
17
+ ## Non-negotiable database contract
18
+
19
+ Before database, schema, CRUD, repository, or persistence work, read this
20
+ pattern completely. Use the database selected for this app's development
21
+ runtime; never alter a production, legacy, historical, or other valuable
22
+ database to develop or verify schema changes. Prove the complete migration
23
+ chain against a fresh disposable database before reporting completion.
24
+
25
+ For normal app-owned CRUD tables:
26
+
27
+ - use exactly one non-null integer primary-key column, normally
28
+ `id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY`
29
+ - make every foreign key single-column and point it directly to the referenced
30
+ table's single-column primary key
31
+ - use multi-column unique indexes only for business uniqueness, never as
32
+ relationship targets
33
+ - use only direct `workspace_id` and/or `user_id` columns for generated JSKIT
34
+ ownership, and select the ownership filter that matches those columns exactly
35
+ - express tenant-safe relationships as direct ownership plus a normal
36
+ `parent_id -> parent.id` relationship; resolve related IDs through the
37
+ workspace-scoped service and test both allowed and cross-workspace cases
38
+
39
+ Do not use composite primary keys or composite foreign keys to encode tenant
40
+ ownership, target a business key from a foreign key, or duplicate parent
41
+ identity when the related row ID already identifies it. Stop before generation
42
+ if the proposed table violates these constraints.
43
+
17
44
  Rules:
18
45
 
19
- - For a CRUD-backed entity, start with `jskit generate crud-server-generator scaffold ...`.
46
+ - For a CRUD-backed entity, create the validated table in the managed
47
+ development database first. Then make
48
+ `jskit generate crud-server-generator scaffold ...` the first JSKIT scaffold.
20
49
  - Unless the table is already owned by a JSKIT baseline package or is an explicit narrow exception recorded in `.jskit/table-ownership.json`, every persisted app-owned table must go through that server CRUD step first.
21
50
  - That server scaffold is the crucial first step even if no CRUD UI will be created yet.
22
51
  - If the table should already be CRUD-owned but should not expose public CRUD HTTP routes yet, scaffold it with `jskit generate crud-server-generator scaffold ... --internal` instead of dropping to direct knex or a hand-built pseudo-repository.
@@ -64,6 +93,19 @@ When a weird-custom persistence lane is proposed:
64
93
  - Record the exact approval and the approved exception in `.jskit/WORKBOARD.md` before coding.
65
94
  - If that exception changes the durable architecture rather than only the current chunk, record it in `.jskit/APP_BLUEPRINT.md` too.
66
95
  - Without that explicit approval record, do not take the weird-custom persistence path.
96
+ - Record durable, approved schema exceptions in `.jskit/APP_BLUEPRINT.md` as
97
+ well as the table-ownership exception; an exception must not silently weaken
98
+ the normal generated CRUD contract.
99
+
100
+ Before reporting completion:
101
+
102
+ - verify there are no composite primary or foreign keys in the generated CRUD
103
+ tables
104
+ - verify every generated CRUD foreign key targets a single-column primary key
105
+ - apply the generated migrations from zero to a fresh disposable database
106
+ - compare the recreated schema with the intended development schema
107
+ - run positive and negative cross-workspace relationship tests where ownership
108
+ applies, then run JSKIT Doctor and the project's normal verifier
67
109
 
68
110
  Avoid:
69
111
 
@@ -68,6 +68,7 @@ Local functions
68
68
  - `renderJsonRestSearchSchemaLines(columns = [])`
69
69
  - `renderJsonRestDefaultSortLine(columns = [])`
70
70
  - `renderResourceDefaultSortLiteral(columns = [])`
71
+ - `renderCurrentTimestampExpression(expression, column)`
71
72
  - `renderMigrationDefaultClause(column)`
72
73
  - `renderMigrationSpecificStringType(column, { tableCollation = "" } = {})`
73
74
  - `renderTemporalColumnBuilder(column, methodName)`
@@ -44,15 +44,19 @@ Local functions
44
44
  - `toBoolean(value)`
45
45
  - `toNullableNumber(value)`
46
46
  - `normalizeColumnDefault(value)`
47
+ - `normalizeCurrentTimestampExpression(value)`
48
+ - `normalizeOnUpdateExpression(value)`
47
49
  - `parseEnumValues(columnType = "")`
48
50
  - `resolveTypeKind(column)`
49
51
  - `normalizeColumn(row = {})`
50
52
  - `normalizePrimaryKeyColumns(rows = [])`
53
+ - `normalizePrimaryKeyColumnsByTable(rows = [])`
51
54
  - `normalizeIndexes(rows = [])`
52
55
  - `normalizeForeignKeys(rows = [])`
53
56
  - `normalizeCheckConstraints(rows = [])`
54
57
  - `requireIdColumn(columns, idColumn)`
55
58
  - `requirePrimaryKeyContainsId(primaryKeyColumns, idColumn)`
59
+ - `requireSupportedForeignKeys(foreignKeys, primaryKeyColumnsByTable)`
56
60
 
57
61
  ### root
58
62
 
@@ -353,6 +353,8 @@ Exports
353
353
  ### `templates/src/surfaces/admin/index.vue`
354
354
  Exports
355
355
  - None
356
+ Local functions
357
+ - `adminChildPath(suffix = "")`
356
358
 
357
359
  ### `templates/src/surfaces/admin/root.vue`
358
360
  Exports
@@ -465,7 +465,7 @@ Exports
465
465
  - `isSensitiveManagedTextRecord({ packageEntry = {}, record = {} } = {})`
466
466
  - `isSensitivePackageOption(packageEntry = {}, optionName = "")`
467
467
  - `isSensitiveTextMutation({ packageEntry = {}, mutation = {}, resolvedKey = "" } = {})`
468
- - `resolveSensitiveOptionEnvFallbacks({ packageEntry = {}, appRoot = "", optionInput = {}, readFileBufferIfExists } = {})`
468
+ - `resolveSensitiveOptionEnvFallbacks({ packageEntry = {}, appRoot = "", optionInput = {}, readFileBufferIfExists, environment = process.env } = {})`
469
469
  - `sanitizeInstalledPackageRecordForLock(record = {}, packageEntry = {})`
470
470
  - `sanitizeLockSecretsForWrite(lock = {}, packageRegistry = null)`
471
471
  - `sanitizeManagedTextForLock(packageEntry = {}, managedText = {})`
@@ -550,8 +550,9 @@ Local functions
550
550
  - `cookieHeader(setCookie = [])`
551
551
  - `responsePayload(response = {})`
552
552
  - `upstreamError(payload = {}, response = {}, extra = {})`
553
+ - `request(fetchImpl, href, options)`
553
554
  - `postJson(fetchImpl, href, body, headers = {})`
554
- - `readSession(fetchImpl, targetOrigin, setCookie = [])`
555
+ - `readSession(fetchImpl, targetOrigin)`
555
556
  - `logout(fetchImpl, targetOrigin, session)`
556
557
  - `login(fetchImpl, targetOrigin, identity, secret, session)`
557
558
 
@@ -7,4 +7,7 @@ Recommended references:
7
7
  - `node_modules/@jskit-ai/agent-docs/guide/agent/index.md`
8
8
  - `node_modules/@jskit-ai/agent-docs/patterns/INDEX.md`
9
9
 
10
+ Before database, schema, CRUD, repository, or persistence work, read and follow
11
+ `node_modules/@jskit-ai/agent-docs/patterns/crud-scaffolding.md`.
12
+
10
13
  Keep changes scoped to the user request and verify runtime behavior with tests or explicit checks.