@jskit-ai/agent-docs 0.1.283 → 0.1.285

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/guide/agent/app-extras/assistant.md +14 -2
  2. package/guide/agent/app-extras/realtime.md +38 -1
  3. package/guide/agent/app-setup/authentication.md +76 -14
  4. package/guide/agent/app-setup/console.md +8 -0
  5. package/guide/agent/app-setup/database-layer.md +23 -103
  6. package/guide/agent/app-setup/existing-application-migration.md +134 -72
  7. package/guide/agent/app-setup/multi-homing.md +94 -32
  8. package/guide/agent/app-setup/quickstart.md +1 -1
  9. package/guide/agent/app-setup/run-an-accounts-hub.md +1 -1
  10. package/guide/agent/app-setup/upgrading-jskit.md +17 -3
  11. package/guide/agent/app-setup/users.md +8 -5
  12. package/guide/agent/framework/application-operations.md +1 -1
  13. package/guide/agent/framework/crud-operations.md +63 -45
  14. package/guide/agent/framework/data-access.md +1207 -0
  15. package/guide/agent/framework/sanity-checks.md +26 -27
  16. package/guide/agent/framework/typed-features.md +117 -248
  17. package/guide/agent/index.md +2 -0
  18. package/package.json +6 -3
  19. package/patterns/feature-package/PATTERN.md +25 -17
  20. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  21. package/patterns/feature-package/example/variations/InvoiceRollupFeature.js +6 -7
  22. package/patterns/feature-package/example/variations/invoiceResource.js +15 -0
  23. package/patterns/feature-package/example/variations/invoiceRollupActions.js +4 -4
  24. package/patterns/feature-package/example/variations/ownedTableRepository.js +27 -0
  25. package/patterns/feature-package/example/variations/types.js +1 -1
  26. package/patterns/minimal-foundation/example/AGENTS.md +4 -0
  27. package/patterns/minimal-foundation/example/package.json +4 -4
  28. package/patterns/minimal-foundation/example/server.js +4 -1
  29. package/patterns/shell-foundation/example/AGENTS.md +4 -0
  30. package/patterns/shell-foundation/example/package.json +5 -5
  31. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  32. package/patterns/shell-foundation/example/server.js +4 -1
  33. package/reference/autogen/KERNEL_MAP.md +3 -1
  34. package/reference/autogen/PATTERN_INDEX.md +70 -59
  35. package/reference/autogen/README.md +1 -1
  36. package/reference/autogen/packages/agent-docs.md +7 -3
  37. package/reference/autogen/packages/agent-runtime.md +48 -11
  38. package/reference/autogen/packages/architecture-inspector.md +6 -2
  39. package/reference/autogen/packages/assistant-core.md +4 -4
  40. package/reference/autogen/packages/assistant-runtime.md +33 -13
  41. package/reference/autogen/packages/auth-provider-local-core.md +3 -1
  42. package/reference/autogen/packages/auth-provider-local-db-core.md +69 -14
  43. package/reference/autogen/packages/auth-provider-oidc-core.md +5 -1
  44. package/reference/autogen/packages/auth-provider-supabase-core.md +1 -1
  45. package/reference/autogen/packages/connectors-core.md +22 -2
  46. package/reference/autogen/packages/console-core.md +9 -5
  47. package/reference/autogen/packages/crud-core.md +45 -175
  48. package/reference/autogen/packages/database-runtime-mysql.md +0 -26
  49. package/reference/autogen/packages/database-runtime.md +11 -33
  50. package/reference/autogen/packages/http-runtime.md +3 -3
  51. package/reference/autogen/packages/http-web.md +12 -0
  52. package/reference/autogen/packages/kernel.md +27 -2
  53. package/reference/autogen/packages/oidc-issuer-core.md +4 -0
  54. package/reference/autogen/packages/payments-core.md +28 -6
  55. package/reference/autogen/packages/realtime.md +15 -6
  56. package/reference/autogen/packages/resource-core.md +32 -5
  57. package/reference/autogen/packages/resource-crud-core.md +30 -34
  58. package/reference/autogen/packages/resource-runtime.md +220 -0
  59. package/reference/autogen/packages/rewarded-core.md +16 -10
  60. package/reference/autogen/packages/shell-web.md +1 -0
  61. package/reference/autogen/packages/users-core.md +33 -14
  62. package/reference/autogen/packages/workspaces-core.md +17 -10
  63. package/reference/autogen/tooling/config-eslint.md +74 -0
  64. package/reference/autogen/tooling/jskit-catalog.md +50 -1
  65. package/reference/autogen/tooling/jskit-release.md +5 -0
  66. package/skills/jskit/SKILL.md +4 -1
  67. package/skills/jskit/references/app-operations.md +1 -1
  68. package/skills/jskit/references/crud-operations.md +62 -44
  69. package/skills/jskit/references/data-access.md +1202 -0
  70. package/skills/jskit/references/database-layer.md +411 -0
  71. package/skills/jskit/references/existing-application-migration.md +134 -72
  72. package/skills/jskit/references/heuristics/INDEX.md +6 -4
  73. package/skills/jskit/references/heuristics/crud-authoring.md +26 -15
  74. package/skills/jskit/references/heuristics/data-access.md +19 -0
  75. package/skills/jskit/references/heuristics/filters.md +6 -6
  76. package/skills/jskit/references/heuristics/row-policies.md +40 -16
  77. package/skills/jskit/references/heuristics/server-search.md +30 -42
  78. package/skills/jskit/references/heuristics/table-resource-fields.md +78 -0
  79. package/skills/jskit/references/heuristics/typed-features.md +3 -3
  80. package/skills/jskit/references/multi-homing.md +94 -32
  81. package/skills/jskit/references/pattern-index.md +70 -59
  82. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +4 -0
  83. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +4 -4
  84. package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +4 -1
  85. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +4 -0
  86. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +5 -5
  87. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  88. package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +4 -1
  89. package/skills/jskit/references/patterns/assistant/assistant-surface/PATTERN.md +5 -2
  90. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +3 -2
  91. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +15 -0
  92. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  93. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  94. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  95. package/skills/jskit/references/patterns/crud/crud-contract/PATTERN.md +133 -0
  96. package/skills/jskit/references/patterns/crud/crud-contract/example/bookResource.js +74 -0
  97. package/skills/jskit/references/patterns/crud/{json-api-resource-package → crud-feature-package}/PATTERN.md +69 -37
  98. package/skills/jskit/references/patterns/crud/{json-api-resource-package → crud-feature-package}/example/packages/books/package.json +5 -4
  99. package/skills/jskit/references/patterns/crud/crud-feature-package/example/packages/books/src/server/BooksFeature.js +13 -0
  100. package/skills/jskit/references/patterns/crud/crud-feature-package/example/packages/books/src/shared/bookResource.js +74 -0
  101. package/skills/jskit/references/patterns/crud/crud-feature-package/example/packages/books/src/shared/index.js +1 -0
  102. package/skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md +26 -8
  103. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookEditPage.vue +2 -2
  104. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookListPage.vue +2 -2
  105. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookNewPage.vue +2 -2
  106. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookViewPage.vue +3 -3
  107. package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +9 -4
  108. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +2 -1
  109. package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +8 -0
  110. package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +8 -4
  111. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +2 -1
  112. package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +8 -0
  113. package/skills/jskit/references/patterns/database/table-resource/PATTERN.md +120 -0
  114. package/skills/jskit/references/patterns/database/table-resource/example/orderResource.js +25 -0
  115. package/skills/jskit/references/patterns/realtime/realtime-application/PATTERN.md +7 -0
  116. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  117. package/skills/jskit/references/patterns/rewards/google-rewarded/PATTERN.md +1 -1
  118. package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +25 -17
  119. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
  120. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupFeature.js +6 -7
  121. package/skills/jskit/references/patterns/server/feature-package/example/variations/invoiceResource.js +15 -0
  122. package/skills/jskit/references/patterns/server/feature-package/example/variations/invoiceRollupActions.js +4 -4
  123. package/skills/jskit/references/patterns/server/feature-package/example/variations/ownedTableRepository.js +27 -0
  124. package/skills/jskit/references/patterns/server/feature-package/example/variations/types.js +1 -1
  125. package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +63 -10
  126. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +5 -4
  127. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/UsersFeature.js +7 -5
  128. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/index.js +1 -1
  129. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/userCrud.js +21 -0
  130. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +11 -5
  131. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +14 -5
  132. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/workspaceMembersOnly.js +52 -0
  133. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/index.js +1 -1
  134. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/userCrud.js +21 -0
  135. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +9 -9
  136. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/PATTERN.md +16 -0
  137. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/home/workspaces/index.vue +2 -0
  138. package/skills/jskit/references/sanity-checks.md +27 -28
  139. package/skills/jskit/references/typed-features.md +117 -248
  140. package/patterns/feature-package/example/variations/customKnexRepository.js +0 -40
  141. package/reference/autogen/packages/json-rest-api-core.md +0 -66
  142. package/skills/jskit/references/heuristics/crud-repository-mapping.md +0 -140
  143. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/BooksFeature.js +0 -13
  144. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/bookResource.js +0 -83
  145. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/index.js +0 -1
  146. package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +0 -155
  147. package/skills/jskit/references/patterns/crud/resource-contract/example/bookResource.js +0 -87
  148. package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +0 -40
  149. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/userResource.js +0 -69
  150. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/userResource.js +0 -56
  151. /package/skills/jskit/references/patterns/crud/{json-api-resource-package → crud-feature-package}/example/migrations/20260815000000_books.cjs +0 -0
  152. /package/skills/jskit/references/patterns/crud/{json-api-resource-package → crud-feature-package}/example/packages/books/src/server/types.js +0 -0
@@ -49,7 +49,7 @@ Exports
49
49
  ### `scripts/browser-tests.mjs`
50
50
  Exports
51
51
  - `SETTINGS_VARIABLE`
52
- - `browserTestConfig({ testDir = "./tests/e2e", port = DEFAULT_PORT, server = "node ./bin/server.js", build = "npm run build", prepare = "", signIn = "", env = {}, health = "/api/health", globalTimeout = GLOBAL_TIMEOUT_MS, environment = process.env, cwd = process.cwd() } = {})`
52
+ - `browserTestConfig({ testDir = "./tests/e2e", port = DEFAULT_PORT, server = "node ./bin/server.js", build = "npm run build", prepare = "", signIn = "", env = {}, health = "/api/health", globalTimeout = GLOBAL_TIMEOUT_MS, actionTimeout = ACTION_TIMEOUT_MS, navigationTimeout = NAVIGATION_TIMEOUT_MS, environment = process.env, cwd = process.cwd() } = {})`
53
53
  - `browserTestWorkers({ env = process.env, argv = process.argv } = {})`
54
54
  Local functions
55
55
  - `positiveInteger(value)`
@@ -66,6 +66,49 @@ Local functions
66
66
  - `buildCatalog({ repoRoot, packagesRoot, outputPath })`
67
67
  - `main()`
68
68
 
69
+ ### `scripts/data-access.mjs`
70
+ Exports
71
+ - `checkDataAccess({ projectRoot = process.cwd() } = {})`
72
+ - `formatDataAccessReport(result)`
73
+ - `readTableResourceSources({ projectRoot = process.cwd() } = {})`
74
+ Local functions
75
+ - `escapeRegExp(text)`
76
+ - `skipsDirectory(name)`
77
+ - `blank(text)`
78
+ - `maskStrings(code)`
79
+ - `closingOffset(masked, start)`
80
+ - `nextCodeOffset(text, offset)`
81
+ - `constantValue(code, name)`
82
+ - `readValue(code, masked, offset)`
83
+ - `topLevelKeys(masked, start, end, names)`
84
+ - `objectArgument(masked, callOffset, matchLength)`
85
+ - `keyValue(code, masked, keys, key)`
86
+ - `readSourceFile(source)`
87
+ - `objectKeys(masked, start, end)`
88
+ - `objectAt(masked, offset)`
89
+ - `readSchemaFields(code, masked, keys, ownership)`
90
+ - `readTableResources(file, { code, masked, position })`
91
+ - `readCrudContracts({ code, masked })`
92
+ - `unnamedFields(resources, contracts)`
93
+ - `ownsSystemContextName(source, masked)`
94
+ - `readSystemScopes(file, { source, code, masked, position })`
95
+ - `readInfrastructureExcuses(file, source)`
96
+ - `isDataAccessRule(rule)`
97
+ - `blockComments(source)`
98
+ - `readLintDisables(file, source, position)`
99
+ - `readRuntimeCapabilities(file, { code, masked, position })`
100
+ - `isError(setting)`
101
+ - `appEslint(root)`
102
+ - `checkLintConfig(root, files, baseline, report)`
103
+ - `checkCapabilities(baseline, uses, report)`
104
+ - `readBaseline(root, report)`
105
+ - `checkBaseline(baseline, excuses, scopes, report)`
106
+ - `walk(root, directory, files)`
107
+ - `frameworkPackages(root)`
108
+ - `checkTables(resources, report)`
109
+ - `checkSystemScopes(scopes, report)`
110
+ - `sourceFiles(root)`
111
+
69
112
  ### `scripts/files.mjs`
70
113
  Exports
71
114
  - `fileExists(absolutePath)`
@@ -278,6 +321,8 @@ Local functions
278
321
  - `removeJskitDependencyRecords(dependencies = {}, localPackageNames = new Set())`
279
322
  - `alignLockManifestRecord(lockRecord, manifest, localPackageNames)`
280
323
  - `preparePackageLockForInstall(projectRoot, manifests, packageLockPath)`
324
+ - `findImports(root, packageIds)`
325
+ - `installedPackageMigrations(root)`
281
326
 
282
327
  ### `scripts/test-budget.mjs`
283
328
  Exports
@@ -300,9 +345,12 @@ Local functions
300
345
  ### `scripts/test-databases.mjs`
301
346
  Exports
302
347
  - `DATABASES_OPTION`
348
+ - `foreignKeyCheckFor(cwd)`
303
349
  - `testDatabaseRunFor(count, cwd = process.cwd())`
304
350
  Local functions
305
351
  - `withOwnEnvironment(load)`
352
+ - `exportedTableResources(namespace, isTableResource)`
353
+ - `keyText({ tableName, columns, referencedTableName, referencedColumns })`
306
354
 
307
355
  ### `scripts/test-file-stop.mjs`
308
356
  Exports
@@ -341,6 +389,7 @@ Local functions
341
389
  ### `scripts/verify-packages.mjs`
342
390
  Exports
343
391
  - `main()`
392
+ - `validateApiSummarySurfaces(packageJson)`
344
393
  - `validateCapabilityClosure(packages, { builtinCapabilities = BUILTIN_CAPABILITIES } = {})`
345
394
  - `validateMigrations(packageRecord, migrationOwners)`
346
395
  - `validateProviderExport(value, label)`
@@ -17,6 +17,7 @@ Use this on demand; do not load the full index at startup.
17
17
  ### `src/manifests.mjs`
18
18
  Exports
19
19
  - `DEPENDENCY_FIELDS`
20
+ - `assertNoOutsidePathDependencies(records, repoRoot)`
20
21
  - `bumpPatch(version)`
21
22
  - `collectPatternPackageJsonPaths(packageRoot, nestedManifests = ["patterns", "examples"])`
22
23
  - `collectPublishDependencies(packageJson, localNames)`
@@ -37,6 +38,7 @@ Exports
37
38
  Local functions
38
39
  - `followVersion(declared, version)`
39
40
  - `expandWorkspacePattern(repoRoot, pattern)`
41
+ - `localDependencyPath(spec)`
40
42
  - `versionFilePaths(record)`
41
43
 
42
44
  ### `src/npm-publication.mjs`
@@ -54,6 +56,7 @@ Local functions
54
56
 
55
57
  ### `src/release.mjs`
56
58
  Exports
59
+ - `assertNoOutsidePathDependencies`
57
60
  - `assertReleaseCheckout(repoRoot, { allowAhead = false, branch = "main" } = {})`
58
61
  - `bumpPatch`
59
62
  - `collectPublishDependencies`
@@ -81,6 +84,8 @@ Local functions
81
84
  - `git(repoRoot, args)`
82
85
  - `commitAll(repoRoot, message)`
83
86
  - `releaseCommitMessage(entries)`
87
+ - `catalogPins(record, entry)`
88
+ - `waitUntilServedAsLatest(pins, inspection, { attempts = Number(process.env.JSKIT_RELEASE_SERVE_ATTEMPTS || 20), delayMs = Number(process.env.JSKIT_RELEASE_RETRY_DELAY_MS || 30_000) } = {})`
84
89
  - `publishRelease(records, { cwd: repoRoot, registry })`
85
90
  - `publishCommand(options)`
86
91
  - `forgetPinnedLockEntries(repoRoot, names)`
@@ -43,13 +43,16 @@ manifests, migrations, tests, and runtime behaviour are the evidence.
43
43
  4. Load only relevant references:
44
44
  - [port guide](references/existing-application-migration.md) for existing apps.
45
45
  - [heuristics index](references/heuristics/INDEX.md) for recurring traps.
46
+ - Before code that reads or writes a database table, read
47
+ [data access](references/data-access.md) completely; for connections,
48
+ migrations and test databases, [database layer](references/database-layer.md).
46
49
  - Before writing server code, read [typed features](references/typed-features.md) and its heuristic; client code, [client features](references/client-features.md). `npm run lint` checks both.
47
50
  - [multi-homing](references/multi-homing.md) for workspaces or invitations.
48
51
  - [translation](references/translation.md) for languages, translated texts
49
52
  or error codes.
50
53
  - For creation, foundation patterns, or package selection, read
51
54
  [application operations](references/app-operations.md).
52
- - Before database, schema, CRUD, repository, or persistence work, read
55
+ - Before schema, CRUD or screen work on a table, also read
53
56
  [CRUD operations](references/crud-operations.md) completely; for custom
54
57
  form actions, also [form actions](references/crud-form-actions.md).
55
58
  - For routes, placements, user-facing UI, or browser verification, read
@@ -96,7 +96,7 @@ normal order is:
96
96
 
97
97
  1. confirm the product resource, ownership, operations, and fields
98
98
  2. author a migration as normal application source
99
- 3. author the shared resource contract through `resource-crud-core`
99
+ 3. define the table resource (`defineTableResource`) and, for screens, its CRUD contract (`defineCrudContract`)
100
100
  4. use framework APIs for standard repository/service/action/route mechanics
101
101
  5. author product-specific screens from the relevant UI pattern
102
102
  6. run migrations and direct verification
@@ -8,9 +8,14 @@ Take database, surface, access, ownership, operations, and fields from product
8
8
  intent and current source. Ask when a material choice is missing. Do not
9
9
  translate the work into generator options.
10
10
 
11
- Read the narrow package-owned pattern in the [bundled source pattern index](pattern-index.md): `crud/resource-contract` for the resource,
12
- `crud/json-api-resource-package` for the server, and `crud/crud-screen-set`
13
- for routed UI. Child-resource and row-policy patterns own those variations.
11
+ Read the package-owned pattern in the [bundled source pattern index](pattern-index.md): `database/table-resource` for the table,
12
+ `crud/crud-contract` for its HTTP surface,
13
+ `crud/crud-feature-package` for the server, and `crud/crud-screen-set`
14
+ for routed UI; the [row
15
+ policies](heuristics/row-policies.md)
16
+ and [child
17
+ CRUDs](heuristics/child-cruds.md)
18
+ heuristics cover those variations.
14
19
 
15
20
  Normal CRUD tables use one non-null integer primary key. Foreign keys are
16
21
  single-column; composite unique indexes are business constraints, not
@@ -20,26 +25,38 @@ Match visibility to real ownership and test allowed plus cross-owner cases.
20
25
  ## Author the resource normally
21
26
 
22
27
  1. Write an immutable app-owned migration.
23
- 2. Define the shared resource contract through `defineCrudResource()`.
24
- 3. Use `defineCrudJsonApiFeature()` for standard repository, service, action,
25
- permission, resource-host, and route mechanics.
28
+ 2. Define the table resource with `defineTableResource()` and its HTTP surface
29
+ with `defineCrudContract()`, which names its `namespace`: the routes',
30
+ messages' and events' public name, never taken from the resource.
31
+ 3. Use `defineCrudFeature()` for standard table ownership, service, action,
32
+ permission, and route mechanics.
26
33
  4. Customize through `decorateRepository`, `decorateService`,
27
34
  `operationLifecycle`, and named `actions`; do not copy the standard CRUD
28
35
  repository/action/route stack.
29
36
  5. Build routed screens from the matching `http-web`/CRUD UI pattern.
30
37
 
31
- The resource is canonical for fields, operations, validation, transport,
32
- messages, and route parameters. Do not duplicate its schema or serializers.
38
+ The table resource is canonical for fields, columns, ownership and search; the
39
+ CRUD contract for operations, validation, transport, messages and route
40
+ parameters. A contract shows and accepts only the fields its `fields` names (stored
41
+ `createdAt` and `updatedAt` show without an entry; `createdAt: { output:
42
+ false }` hides one), so a column added later stays out of every API until a
43
+ contract names it. A CRUD feature's answers follow the same rule: an unnamed
44
+ relationship is left out, and an included record shows only its id, its
45
+ relation's `labelKey` and the fields the including contract lists in that
46
+ field's `output.includeFields` (`{ breed: ["name"] }` in the list shows a
47
+ record it links to, as deep as listed), never another contract's output.
48
+ A package with a CRUD feature lists `crud.contracts` in its descriptor's
49
+ `capabilities.requires`. Do not duplicate their schema or serializers.
33
50
  Prefer `useCrudListScreen()`, `useCrudViewScreen()`, and
34
51
  `useCrudAddEditScreen()`; use `useCommand()` or `useEndpointResource()` for
35
52
  non-standard operations.
36
53
 
37
54
  Add resource service methods with `decorateService`; expose commands such as
38
- `confirm`, `publish`, or `cancel` through named `actions`. With `operationLifecycle`, mutation `before`,
39
- `execute`, and `after` share one repository transaction, `execute` receives
40
- `standard(nextInput)`, and `afterCommit` follows commit. Repositories persist;
41
- services and hooks orchestrate. Use a transactional outbox for durable
42
- external work.
55
+ `confirm` or `cancel` through named `actions`. With `operationLifecycle`, mutation `before`,
56
+ `execute`, and `after` share one transaction, rerun on deadlock, so they touch
57
+ only the database; `execute` receives `standard(nextInput)`. Outside effects go
58
+ in `afterCommit`, run once after commit, or an outbox when durable.
59
+ Repositories persist; services and hooks orchestrate.
43
60
 
44
61
  ## Choose ownership, API access and client access independently
45
62
 
@@ -47,37 +64,31 @@ These controls answer different questions:
47
64
 
48
65
  | Control | Purpose | Public records | Owner-scoped records |
49
66
  | --- | --- | --- | --- |
50
- | Resource `autofilter` | Which rows belong to the request scope | `"public"`; no ownership column | `"user"`; real non-null `userId` column |
51
- | Resource `apiAccess` | Who may call the API | `"public"` | `"authenticated"` |
52
- | Feature `ownershipFilter` | Server route/action ownership scope | `"public"` | `"user"` |
67
+ | Table resource `ownership` | Which rows belong to the request scope | `"public"`; no ownership column | `"user"`; real non-null `userId` column |
68
+ | CRUD contract `apiAccess` | Who may call the API | `"public"` | `"authenticated"` |
69
+ | Feature route visibility | Server route/action scope: the table's `ownership` unless the feature names `visibility` | `"public"` | `"user"` |
53
70
  | Client `access` | Whether to require bootstrap permissions | Default `"auto"` with no permission requirements | Default `"auto"`; declare permissions when required |
54
71
 
55
- `access` accepts `auto`, `always`, or `never`, not `public`. With `auto`, a
56
- screen with no permission requirements does not require a permissions bootstrap.
57
- `always` does require it. Do not add authentication or workspace machinery to
58
- compensate for an unnecessary `always` override. Server access and ownership
72
+ `access` accepts `auto`, `always`, or `never`, not `public`. `auto` requires a
73
+ permissions bootstrap only for a screen with permission requirements; `always`
74
+ always does. Do not add authentication or workspace machinery to
75
+ make up for an unneeded `always` override. Server access and ownership
59
76
  remain authoritative.
60
77
 
61
- The Books source patterns demonstrate user ownership. For an intentionally
62
- public create/list resource, use the same patterns with this resource contract:
78
+ The Books source patterns show user ownership. For a public create/list
79
+ resource, use them with this table resource and CRUD contract:
63
80
 
64
81
  ```js
65
- const bookResource = defineCrudResource({
66
- namespace: "books",
82
+ const bookResource = defineTableResource({
83
+ name: "books",
67
84
  tableName: "books",
68
- apiAccess: "public",
69
- autofilter: "public",
70
- crudOperations: ["list", "view", "create"],
85
+ ownership: "public",
71
86
  schema: {
72
87
  title: {
73
88
  type: "string",
74
89
  required: true,
75
90
  minLength: 1,
76
- maxLength: 255,
77
- operations: {
78
- output: { required: true },
79
- create: { required: true }
80
- }
91
+ maxLength: 255
81
92
  }
82
93
  },
83
94
  searchSchema: {
@@ -90,20 +101,27 @@ const bookResource = defineCrudResource({
90
101
  }
91
102
  }
92
103
  });
104
+
105
+ const bookCrud = defineCrudContract(bookResource, {
106
+ namespace: "books",
107
+ apiAccess: "public",
108
+ operations: ["list", "view", "create"],
109
+ fields: { title: { output: "required", create: "required" } }
110
+ });
93
111
  ```
94
112
 
95
- Import `defineCrudResource` from
96
- `@jskit-ai/resource-crud-core/shared/crudResource`. Its app-owned migration
97
- creates `books` with an integer primary key `id` and non-null `title`; omit
98
- `userId` and its foreign key for this public variant. `list` requires `view`
99
- in the shared resource contract, even when the UI has no detail page. A create
100
- response uses the resource output contract. Keep operation names such as
101
- `list`, `view` and `create`; do not invent output-operation aliases.
102
-
103
- Bind `defineCrudJsonApiFeature()` with this resource, `ownershipFilter:
104
- "public"`, `relativePath: "/books"` and the application's configured public
105
- surface. Keep the existing package/provider and migration registration from
106
- `crud/json-api-resource-package`.
113
+ Import `defineTableResource` from `@jskit-ai/resource-core/shared/tableResource`
114
+ and `defineCrudContract` from `@jskit-ai/resource-crud-core/shared/crudContract`.
115
+ Its migration creates `books` with an integer `id` and non-null `title`; omit
116
+ `userId` and its foreign key.
117
+ `list` requires `view` in the CRUD contract, even when the UI has no detail
118
+ page. A create response uses the CRUD contract's output. Keep operation names
119
+ such as `list`, `view` and `create`; do not invent output-operation aliases.
120
+
121
+ Bind `defineCrudFeature()` with `crud: bookCrud`, `relativePath: "/books"`
122
+ and the application's configured public surface; the table's `"public"`
123
+ ownership makes its routes public. Keep the existing package/provider and migration registration from
124
+ `crud/crud-feature-package`.
107
125
 
108
126
  For the list, keep `BookListPage.vue` thin: use `resourceNamespace: "books"`
109
127
  in `useCrudListScreen()` on the configured public surface, remove unsupported