@jskit-ai/agent-docs 0.1.125 → 0.1.127

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.
@@ -577,6 +577,8 @@ Request connectivity failures use a separate shell recovery path. Generated apps
577
577
 
578
578
  That recovery path is intentionally a safe `GET`/`HEAD` read refetch system, not a general HTTP replay system. User-visible reads should go through Query-backed JSKIT primitives such as `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, or generated CRUD screen composables. Those primitives mark Query entries with `jskit.requestRecoveryMethod`, so the shell only offers Retry for safe reads. Do not catch raw `fetch(...)` failures in each panel just to call the shell recovery runtime manually.
579
579
 
580
+ These neutral request and CRUD client APIs are exported by `@jskit-ai/http-web`. They do not require the users, authentication, uploads, storage, or database products.
581
+
580
582
  For a custom endpoint read, attach the recovery label to the Query-backed resource:
581
583
 
582
584
  ```js
@@ -611,9 +613,9 @@ Writes are different. JSKIT does not automatically replay `POST`, `PATCH`, `PUT`
611
613
  Some apps need API URLs to be scoped by the active route before the browser request is sent. Configure that once at app startup instead of replacing `fetchImpl` in a local transport wrapper:
612
614
 
613
615
  ```js
614
- import { configureUsersWebHttpClient } from "@jskit-ai/users-web/client/lib/httpClient";
616
+ import { configureHttpWebClient } from "@jskit-ai/http-web/client/lib/httpClient";
615
617
 
616
- configureUsersWebHttpClient({
618
+ configureHttpWebClient({
617
619
  csrf: {
618
620
  enabled: false
619
621
  },
@@ -628,7 +630,7 @@ configureUsersWebHttpClient({
628
630
  });
629
631
  ```
630
632
 
631
- Call `configureUsersWebHttpClient()` before Vue mounts or before JSKIT composables are created. The resolver can close over the app router/store when it needs route data, and the `context` argument carries request details such as `originalUrl`, `method`, `requestOptions`, and whether the request is a stream. After configuration, normal `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, and `useCommand()` calls use the configured client. `resolveRequestUrl` runs after JSKIT adds query strings and before the underlying browser `fetch`, so request recovery metadata, JSON:API transport, credentials, CSRF, and command feedback stay on the standard path.
633
+ Call `configureHttpWebClient()` before Vue mounts or before JSKIT composables are created. The resolver can close over the app router/store when it needs route data, and the `context` argument carries request details such as `originalUrl`, `method`, `requestOptions`, and whether the request is a stream. After configuration, normal `useEndpointResource()`, `useList()`, `useView()`, `useAddEdit()`, and `useCommand()` calls use the configured client. `resolveRequestUrl` runs after JSKIT adds query strings and before the underlying browser `fetch`, so request recovery metadata, JSON:API transport, credentials, CSRF, and command feedback stay on the standard path.
632
634
 
633
635
  For packages that create their own client, use the same lower-level hook directly:
634
636
 
@@ -95,7 +95,99 @@ npm ls
95
95
 
96
96
  Resolve npm peer or capability errors as package-graph errors. Do not add overrides that mix Beta 1 and Final Release packages.
97
97
 
98
- ## 7. Generate deterministic projections
98
+ ## 7. Move neutral web operations out of users-web
99
+
100
+ Final Release owns browser request, command, list, view, add/edit, permission,
101
+ paging, and generated CRUD UI APIs in `@jskit-ai/http-web`. There are no
102
+ `users-web` compatibility exports.
103
+
104
+ Add the coordinated `@jskit-ai/http-web` version to every application or
105
+ workspace that uses these APIs. Keep `@jskit-ai/users-web` only where the code
106
+ actually uses account, profile, or user-specific shell UI.
107
+
108
+ Update imports as follows:
109
+
110
+ | Beta 1 import or API | Final Release import or API |
111
+ | --- | --- |
112
+ | `@jskit-ai/users-web/client/composables/useCommand` | `@jskit-ai/http-web/client/composables/useCommand` |
113
+ | `@jskit-ai/users-web/client/composables/useEndpointResource` | `@jskit-ai/http-web/client/composables/useEndpointResource` |
114
+ | `@jskit-ai/users-web/client/composables/useList` | `@jskit-ai/http-web/client/composables/useList` |
115
+ | `@jskit-ai/users-web/client/composables/useView` | `@jskit-ai/http-web/client/composables/useView` |
116
+ | `@jskit-ai/users-web/client/composables/useAddEdit` | `@jskit-ai/http-web/client/composables/useAddEdit` |
117
+ | `@jskit-ai/users-web/client/composables/useAccess` | `@jskit-ai/http-web/client/composables/useAccess` |
118
+ | `@jskit-ai/users-web/client/composables/usePagedCollection` | `@jskit-ai/http-web/client/composables/usePagedCollection` |
119
+ | `@jskit-ai/users-web/client/composables/useRealtimeQueryInvalidation` | `@jskit-ai/http-web/client/composables/useRealtimeQueryInvalidation` |
120
+ | `@jskit-ai/users-web/client/composables/runtime/useUiFeedback` | `@jskit-ai/http-web/client/composables/useUiFeedback` |
121
+ | `@jskit-ai/users-web/client/composables/useCrud*` | `@jskit-ai/http-web/client/composables/useCrud*` |
122
+ | `@jskit-ai/users-web/client/components/Crud*` | `@jskit-ai/http-web/client/components/Crud*` |
123
+ | `@jskit-ai/users-web/client/filters` | `@jskit-ai/http-web/client/filters` |
124
+ | `@jskit-ai/users-web/client/bulkActions` | `@jskit-ai/http-web/client/bulkActions` |
125
+ | `@jskit-ai/users-web/client/rowActions` | `@jskit-ai/http-web/client/rowActions` |
126
+ | `@jskit-ai/users-web/client/lib/permissions` | `@jskit-ai/http-web/client/lib/permissions` |
127
+ | `@jskit-ai/users-web/client/support/contractGuards` | `@jskit-ai/http-web/client/support/contractGuards` |
128
+ | `configureUsersWebHttpClient(...)` | `configureHttpWebClient(...)` from `@jskit-ai/http-web/client/lib/httpClient` |
129
+ | `usersWebHttpClient` | `httpWebClient` from `@jskit-ai/http-web/client/lib/httpClient` |
130
+
131
+ Search every application workspace, generated route tree, test fixture, and
132
+ app bootstrap. An application that leaves even one removed import will fail at
133
+ module resolution; this is intentional because Final Release contains no
134
+ forwarding bridge.
135
+
136
+ `crud-ui-generator` now installs `@jskit-ai/http-web`. `ui-generator` installs
137
+ no users product. Existing generated files are application-owned, so update
138
+ their imports directly or deliberately regenerate them and review the diff.
139
+
140
+ After all imports are updated, remove `@jskit-ai/users-web` from any workspace
141
+ that used it only for neutral client APIs. This prevents those applications
142
+ from activating users, authentication, uploads, storage, or database
143
+ capabilities accidentally.
144
+
145
+ ## 8. Use the separated CRUD package boundaries
146
+
147
+ Final Release separates shared resource contracts, browser CRUD, and
148
+ database-backed CRUD:
149
+
150
+ - `@jskit-ai/resource-crud-core` owns environment-neutral CRUD resource,
151
+ field, lookup, namespace, and list-filter contracts;
152
+ - `@jskit-ai/http-web` owns browser request runtimes and generated CRUD UI;
153
+ - `@jskit-ai/crud-core` owns database-backed server CRUD services and
154
+ repositories.
155
+
156
+ Update shared-contract imports as follows:
157
+
158
+ | Beta 1 import | Final Release import |
159
+ | --- | --- |
160
+ | `@jskit-ai/kernel/shared/support/crudFieldContract` | `@jskit-ai/resource-crud-core/shared/crudFieldContract` |
161
+ | `@jskit-ai/kernel/shared/support/crudLookup` | `@jskit-ai/resource-crud-core/shared/crudLookup` |
162
+ | `@jskit-ai/kernel/shared/support/crudListFilters` | `@jskit-ai/resource-crud-core/shared/crudListFilters` |
163
+ | `@jskit-ai/crud-core/shared/crudResource` | `@jskit-ai/resource-crud-core/shared/crudResource` |
164
+ | `@jskit-ai/crud-core/shared/crudNamespaceSupport` | `@jskit-ai/resource-crud-core/shared/crudNamespaceSupport` |
165
+ | `checkCrudLookupFormControl` from `@jskit-ai/crud-core/shared/crudFieldSupport` | `checkCrudLookupFormControl` from `@jskit-ai/resource-crud-core/shared/crudFieldContract` |
166
+ | `isCrudRuntimeOutputOnlyFieldKey` from `@jskit-ai/crud-core/shared/crudFieldSupport` | `isCrudRuntimeOutputOnlyFieldKey` from `@jskit-ai/resource-crud-core/shared/crudLookup` |
167
+
168
+ There is no `@jskit-ai/crud-core/client` surface. Replace browser imports from
169
+ that surface with the corresponding `@jskit-ai/http-web` API. Add
170
+ `@jskit-ai/resource-crud-core` directly wherever application code imports its
171
+ contracts. Remove `@jskit-ai/crud-core` from client-only and generator-only
172
+ workspaces; retain it only where database-backed server CRUD is used.
173
+
174
+ The current CRUD UI templates import `@jskit-ai/http-web`, and the CRUD UI
175
+ generator no longer installs the server CRUD runtime. Existing generated files
176
+ are application-owned, so update their imports directly or deliberately
177
+ regenerate them and review the diff.
178
+
179
+ If application tests or package tooling refer to workspaces-web mutation IDs,
180
+ rename the `users-web-*` prefix on workspaces-web-owned mutations to
181
+ `workspaces-web-*`. Package-internal `UsersWorkspace*` component paths are not
182
+ public APIs; remove any direct imports and use the exported workspaces-web
183
+ provider surface.
184
+
185
+ If application code imported repository persistence helpers from
186
+ `@jskit-ai/assistant-core/server`, keep those helpers with the repository that
187
+ uses them or use the matching database-runtime primitive. Assistant core no
188
+ longer owns database persistence utilities.
189
+
190
+ ## 9. Generate deterministic projections
99
191
 
100
192
  Synchronize package migration files without applying them:
101
193
 
@@ -118,7 +210,7 @@ npx jskit ci generate
118
210
 
119
211
  Move application-specific CI into separate workflow files. The generated JSKIT workflow is replaced in full whenever this command runs.
120
212
 
121
- ## 8. Verify the application
213
+ ## 10. Verify the application
122
214
 
123
215
  ```bash
124
216
  npx jskit lint-packages
@@ -138,7 +230,7 @@ npm run db:migrate
138
230
 
139
231
  Commit package manifests, `package-lock.json`, synchronized migrations, generated CI, and required application changes together.
140
232
 
141
- ## 9. Update strict resource boundaries
233
+ ## 11. Update strict resource boundaries
142
234
 
143
235
  Applications that pass JavaScript `Date` objects into resource validation must convert them to strings. `date` uses `YYYY-MM-DD`; `time` uses offset-free `HH:MM[:SS[.fraction]]`; and `dateTime` uses RFC 3339 with seconds and a `Z` or numeric offset. Select `epochMilliseconds` or `epochSeconds` explicitly for numeric epochs and preserve `temporalPrecision`.
144
236
 
@@ -25,7 +25,7 @@ npm run db:migrate
25
25
 
26
26
  The first command adds `users-web`, but the important part is what arrives with it through its dependency chain.
27
27
 
28
- - `users-web` adds the account-facing UI and client runtime pieces
28
+ - `users-web` adds account, profile, and user-specific shell UI
29
29
  - `users-core` arrives as a dependency and adds the persistent users/account server layer and schema migrations
30
30
 
31
31
  `jskit add` installs those runtime packages and their dependencies. `npm run db:migrate` is the separate step that makes the new tables real in MySQL.
@@ -49,7 +49,9 @@ After those two commands, the important thing to understand is ownership:
49
49
 
50
50
  - `crud-server-generator` creates a runtime package that your app owns locally
51
51
  - `crud-ui-generator` creates route files that your app owns locally
52
- - `crud-core`, `users-web`, and the other runtime packages provide the machinery underneath those files
52
+ - `crud-core` provides the server CRUD runtime, `resource-crud-core` owns shared
53
+ CRUD contracts, and `http-web` provides browser operations and generated
54
+ screen components
53
55
 
54
56
  The generated pages are intentionally thin. Most of the heavy lifting lives uphill in shared runtime composables, action execution, validation, lookup hydration, and repository helpers.
55
57
 
@@ -480,7 +482,8 @@ Its job is usually to:
480
482
  - resolve list/view/edit/new URLs
481
483
  - pass route query state through when navigating deeper
482
484
 
483
- The actual list machinery lives in `users-web` shared screen composables and the shared resource contract.
485
+ The actual list machinery lives in `http-web` screen composables and the shared
486
+ resource contract lives in `resource-crud-core`.
484
487
 
485
488
  ### `[contactId]/index.vue`
486
489
 
@@ -703,17 +706,19 @@ Why this is the standard JSKIT shape:
703
706
 
704
707
  - `useCommand()` resolves the correct scoped API path for the current route and surface.
705
708
  - The higher-level list, view, add/edit, and command runtimes send requests through the standard HTTP runtime instead of ad hoc request code.
706
- - The default client runtime uses `usersWebHttpClient`, which already handles credentials and CSRF token behavior.
709
+ - The default client runtime uses `httpWebClient`, which already handles credentials and CSRF token behavior.
707
710
  - `useEndpointResource()` gives the shared endpoint primitive for loading, saving, and standard load/save error handling. Higher-level runtimes like `useCommand()` and `useAddEdit()` layer UI feedback and field-error behavior on top of that primitive.
708
711
  - `shell-web` observes the shared TanStack Query client for recoverable transport failures. Generated CRUD reads and custom reads built with `useEndpointResource()`, `useList()`, `useView()`, or `useAddEdit()` get the shell recovery banner with a Retry action that refetches the failed query.
709
712
  - Automatic shell request recovery is only for safe `GET`/`HEAD` read refetches. JSKIT read composables mark Query entries with `jskit.requestRecoveryMethod`, and the shell ignores unmarked or unsafe methods. Do not rely on it to replay `POST`, `PATCH`, `PUT`, or `DELETE`; mutation screens own save state, field errors, and user feedback.
710
713
 
711
- When an app needs all JSKIT reads and commands to rewrite API URLs before fetch, configure the users-web HTTP client once instead of passing custom paths or replacing `fetchImpl` in each local helper:
714
+ The request composables and generated CRUD client surfaces above come from `@jskit-ai/http-web`. That package is neutral: installing it does not install users, authentication, uploads, storage, or a database.
715
+
716
+ When an app needs all JSKIT reads and commands to rewrite API URLs before fetch, configure the http-web client once instead of passing custom paths or replacing `fetchImpl` in each local helper:
712
717
 
713
718
  ```js
714
- import { configureUsersWebHttpClient } from "@jskit-ai/users-web/client/lib/httpClient";
719
+ import { configureHttpWebClient } from "@jskit-ai/http-web/client/lib/httpClient";
715
720
 
716
- configureUsersWebHttpClient({
721
+ configureHttpWebClient({
717
722
  csrf: {
718
723
  enabled: false
719
724
  },
@@ -787,7 +792,7 @@ The safe mental model is:
787
792
  - do not raw `fetch(...)` for normal app work
788
793
  - do not invent ad hoc local AJAX helpers
789
794
  - use the operation/runtime composable that matches the UI interaction
790
- - drop to `usersWebHttpClient.request(...)` only for exceptional low-level cases
795
+ - drop to `httpWebClient.request(...)` only for exceptional low-level cases
791
796
  - use `usePaths().api(...)` when you need a custom scoped API path and the higher-level runtime does not already resolve it for you
792
797
  - keep `apiUrlTemplate` path-only and put endpoint query strings in `requestQueryParams`
793
798
 
@@ -800,7 +805,7 @@ It owns:
800
805
  - which set of generated form fields is rendered in `new` vs `edit`
801
806
  - lookup field prop forwarding into those fields
802
807
 
803
- It does **not** own persistence logic or the shared screen chrome. `CrudAddEditScreen` from `users-web` owns the common title, load state, retry action, save/cancel action row, and form surface.
808
+ It does **not** own persistence logic or the shared screen chrome. `CrudAddEditScreen` from `@jskit-ai/http-web` owns the common title, load state, retry action, save/cancel action row, and form surface.
804
809
 
805
810
  ### `src/components/.../CrudAddEditFormFields.js`
806
811
 
@@ -824,7 +829,7 @@ That is navigation wiring, not CRUD logic.
824
829
  A generated CRUD works because several layers cooperate:
825
830
 
826
831
  1. the route page calls `useCrudListScreen()`, `useCrudViewScreen()`, or `useCrudAddEditScreen()`
827
- 2. those screen composables configure the lower-level list/view/add-edit runtimes from `users-web`
832
+ 2. those screen composables configure the lower-level list/view/add-edit runtimes from `@jskit-ai/http-web`
828
833
  3. the request hits the HTTP route from `registerRoutes.js`
829
834
  4. the route executes an action from `actions.js`
830
835
  5. the action delegates to the service in `service.js`
@@ -847,7 +852,7 @@ Use this rule of thumb when deciding where to edit:
847
852
  | Change SQL, joins, parent filters, or advanced search | `repository.js` | This is the data-access layer |
848
853
  | Add mandatory SQL visibility that must run before count and pagination | server policy module plus the provider's `createJsonRestResourceScopeOptions(..., { rowPolicy })` call | The internal JSON REST host applies the policy to every storage query for that resource |
849
854
  | Add cross-record or domain rules on save/delete | `service.js` | This is business logic |
850
- | Change shared CRUD screen chrome, load states, or retry behavior | `users-web` shared screen components | Generated pages consume the shared screen contract |
855
+ | Change shared CRUD screen chrome, load states, or retry behavior | `http-web` shared screen components | Generated pages consume the shared screen contract |
851
856
  | Add per-row commands to a generated list page | page-local `listRowActions.js`, usually calling `useCommand()`-backed composables | The shared list screen renders action chrome; the page owns explicit mutation behavior |
852
857
  | Add non-CRUD display rows to a generated list page | route page `syntheticRows` input | Synthetic rows are presentation rows, not repository records |
853
858
  | Change page-specific display behavior | the route pages, generated slots, and app-owned composables | This is presentation |
@@ -869,7 +874,7 @@ That is the right direction of growth:
869
874
  - server customizations stay in the CRUD package
870
875
  - presentation and page-specific UI state stay in app-owned client files
871
876
  - shared structured list filters live best in a CRUD-package shared module that both server and client can import
872
- - shared generated screen chrome stays in `users-web`; adapted pages feed it definitions, slots, and explicit command handlers
877
+ - shared generated screen chrome stays in `http-web`; adapted pages feed it definitions, slots, and explicit command handlers
873
878
 
874
879
  ### Shared screen read options and detail slots
875
880
 
@@ -1191,7 +1196,7 @@ Instead:
1191
1196
  For example, a generated page-local filter-definition module can look like this:
1192
1197
 
1193
1198
  ```js
1194
- import { defineCrudListFilters } from "@jskit-ai/users-web/client/filters";
1199
+ import { defineCrudListFilters } from "@jskit-ai/http-web/client/filters";
1195
1200
 
1196
1201
  const listFilters = defineCrudListFilters({
1197
1202
  onlyStaff: {
@@ -1222,7 +1227,7 @@ Use this first when adding selected-record actions. JSKIT does not invent server
1222
1227
  For example:
1223
1228
 
1224
1229
  ```js
1225
- import { defineCrudListBulkActions } from "@jskit-ai/users-web/client/bulkActions";
1230
+ import { defineCrudListBulkActions } from "@jskit-ai/http-web/client/bulkActions";
1226
1231
 
1227
1232
  const listBulkActions = defineCrudListBulkActions([
1228
1233
  {
@@ -1259,7 +1264,7 @@ Use row actions for explicit commands on one record. JSKIT renders the action me
1259
1264
  For example:
1260
1265
 
1261
1266
  ```js
1262
- import { defineCrudListRowActions } from "@jskit-ai/users-web/client/rowActions";
1267
+ import { defineCrudListRowActions } from "@jskit-ai/http-web/client/rowActions";
1263
1268
 
1264
1269
  const listRowActions = defineCrudListRowActions([
1265
1270
  {
@@ -510,7 +510,7 @@ route after success. It supports custom `--id-param` names.
510
510
 
511
511
  The generator rejects this option when list or view is omitted, or when the
512
512
  shared resource has no `DELETE` operation. Without the flag, no delete control
513
- is generated. Do not substitute raw `fetch()` or import private `users-web`
513
+ is generated. Do not substitute raw `fetch()` or import private `http-web`
514
514
  modules.
515
515
 
516
516
  Generated list, view, and lookup reads use the resource contract as their
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.125",
3
+ "version": "0.1.127",
4
4
  "description": "Distributed JSKIT agent references, prompts, guides, and generated reference maps.",
5
5
  "type": "module",
6
6
  "files": [
package/patterns/INDEX.md CHANGED
@@ -26,7 +26,7 @@ How to use it:
26
26
  - `page-redirects.md`
27
27
  - live actions, checkbox, toggle, patch button, delete confirmation, destructive action, inline action, `useCommand()`, `useCrudDeleteAction()`
28
28
  - `live-actions.md`
29
- - ajax, fetch, API call, request, endpoint, HTTP client, `useCrudListScreen()`, `useCrudViewScreen()`, `useCrudAddEditScreen()`, `useList()`, `useView()`, `useAddEdit()`, `useEndpointResource()`, `usersWebHttpClient`
29
+ - ajax, fetch, API call, request, endpoint, HTTP client, `useCrudListScreen()`, `useCrudViewScreen()`, `useCrudAddEditScreen()`, `useList()`, `useView()`, `useAddEdit()`, `useEndpointResource()`, `httpWebClient`
30
30
  - `client-requests.md`
31
31
  - playwright, browser test, e2e, ui verification, baseline test, authenticated ui test, test auth, dev login as, dev auth bypass
32
32
  - `ui-testing.md`
@@ -14,7 +14,7 @@ Rules:
14
14
  - Do not hand-roll local AJAX helpers when an existing JSKIT runtime already fits.
15
15
  - Do not use raw `fetch(...)` for normal app work.
16
16
  - Use `usePaths().api(...)` from `@jskit-ai/shell-web/client/navigation/usePaths` for custom scoped API paths instead of concatenating route params into URLs by hand.
17
- - Drop to `usersWebHttpClient.request(...)` only for exceptional low-level cases.
17
+ - Drop to `httpWebClient.request(...)` only for exceptional low-level cases.
18
18
 
19
19
  Choose the function like this:
20
20
 
@@ -64,13 +64,13 @@ Use the CRUD wrappers when they fit:
64
64
  CRUD hook transport defaults:
65
65
 
66
66
  - CRUD hooks derive the standard JSON:API transport from the shared CRUD `resource` automatically.
67
- - Do not pass `transport` to CRUD hooks. If you need a non-standard wire contract, drop to `useList()`, `useView()`, `useAddEdit()`, or `usersWebHttpClient.request(...)` instead of the CRUD wrappers.
67
+ - Do not pass `transport` to CRUD hooks. If you need a non-standard wire contract, drop to `useList()`, `useView()`, `useAddEdit()`, or `httpWebClient.request(...)` instead of the CRUD wrappers.
68
68
 
69
69
  Why this is the standard JSKIT shape:
70
70
 
71
71
  - `useCommand()` resolves the scoped API path for the current route and surface.
72
72
  - The higher-level list, view, add/edit, and command runtimes send requests through the shared HTTP runtime.
73
- - `usersWebHttpClient` already handles credentials and CSRF behavior.
73
+ - `httpWebClient` already handles credentials and CSRF behavior.
74
74
  - `useEndpointResource()` is the shared endpoint primitive for loading, saving, and standard load/save error handling. Higher-level runtimes add UI feedback and field-error handling on top.
75
75
  - Use `requestQueryParams` for endpoint query strings on list, view, and add/edit runtimes.
76
76
  - Generated CRUD and lookup reads use all resource-defined output fields by default. Hydrated relationships use the target resource's output contract. Generated pages and lookup controls do not repeat those definitions as request fieldsets.
@@ -79,7 +79,9 @@ Why this is the standard JSKIT shape:
79
79
  - Sparse fieldsets are a serialization boundary, not an authorization mechanism. Server resources reject unknown fields, never serialize hidden fields, and preserve the fields needed internally for relationship linkage.
80
80
  - Fields that must never be exposed do not belong in the resource output schema.
81
81
  - Keep `apiUrlTemplate` path-only. Do not put `?include=...` or other query strings in URL templates.
82
- - If an app needs route-aware API URL rewriting, configure the users-web client once with `configureUsersWebHttpClient({ resolveRequestUrl })` before mounting the app. Do not replace `fetchImpl` just to rewrite paths.
82
+ - Import neutral request and CRUD client APIs from `@jskit-ai/http-web`. `users-web` owns only account, profile, and user-specific shell UI.
83
+ - Keep shared CRUD resource, field, lookup, namespace, and filter contracts in `@jskit-ai/resource-crud-core`; keep database-backed CRUD services and repositories in `@jskit-ai/crud-core`.
84
+ - If an app needs route-aware API URL rewriting, configure the http-web client once with `configureHttpWebClient({ resolveRequestUrl })` before mounting the app. Do not replace `fetchImpl` just to rewrite paths.
83
85
  - `resolveRequestUrl` belongs at the HTTP client boundary. It runs after JSKIT encodes query params and before browser `fetch`, so reads, commands, request recovery metadata, JSON:API transport, credentials, and CSRF behavior stay on the standard path.
84
86
 
85
87
  Error presentation rules:
@@ -38,7 +38,7 @@ Generated JSKIT apps should feel like real adaptive apps by default, not framewo
38
38
  - [x] `npm test --workspace @jskit-ai/ui-generator`
39
39
  - [x] `npm test --workspace @jskit-ai/crud-ui-generator`
40
40
  - [x] `npm test --workspace @jskit-ai/shell-web`
41
- - [x] `npm test --workspace @jskit-ai/users-web`
41
+ - [x] `npm test --workspace @jskit-ai/http-web`
42
42
  - [x] `npm test --workspace @jskit-ai/workspaces-web`
43
43
  - [x] `npm test --workspace @jskit-ai/jskit-cli`
44
44
  - [x] `npm test --workspace @jskit-ai/create-app`
@@ -59,7 +59,7 @@ Generated JSKIT apps should feel like real adaptive apps by default, not framewo
59
59
  - CRUD bulk actions are client-side by default: generated list pages create a page-local `listBulkActions.js` and pass it into `useCrudListScreen(...)`; the shared list screen wires `useCrudListBulkActions(...)` and keeps selection controls hidden until actions are declared.
60
60
  - CRUD row actions are client-side by default: generated list pages can create a page-local `listRowActions.js` with `defineCrudListRowActions(...)` and pass it into `useCrudListScreen(...)`; the shared list screen renders per-row actions in card and table layouts while action handlers stay explicit and page-owned.
61
61
  - CRUD synthetic rows are display-only: pass `syntheticRows` into `useCrudListScreen(...)` for owner/master rows that are not repository records. Synthetic rows render through the shared list screen, skip standard Open/Edit links, and are excluded from bulk selection unless explicitly marked selectable.
62
- - Generated CRUD page templates delegate their screen chrome to shared `users-web` screen components (`CrudListScreen`, `CrudViewScreen`, and `CrudAddEditScreen`) so list/view/form load states, retry actions, responsive shell layout, filters, bulk actions, row actions, and detail slots do not drift across generated pages.
62
+ - Generated CRUD page templates delegate their screen chrome to shared `http-web` screen components (`CrudListScreen`, `CrudViewScreen`, and `CrudAddEditScreen`) so list/view/form load states, retry actions, responsive shell layout, filters, bulk actions, row actions, and detail slots do not drift across generated pages.
63
63
  - Generated CRUD list pages should use `useCrudListScreen({ requestQueryParams, readEnabled })` for list read pass-throughs instead of replacing the shared list chrome for includes or permission-gated reads.
64
64
  - Generated CRUD detail pages should use `useCrudViewScreen({ requestQueryParams, readEnabled, queryKeyFactory })` for read pass-throughs and `CrudViewScreen` slots (`before-fields`, `fields`, `after-fields`, `supporting-content`) for domain sections instead of replacing the shared detail chrome.
65
65
  - Routine resource-load errors stay local to the generated screen and retry affordance. Action feedback uses the shell error policy through `action-feedback`.
@@ -50,6 +50,6 @@ Examples:
50
50
  Avoid:
51
51
 
52
52
  - manually hand-rolling fetch logic for a standard live action when `useCommand()` fits
53
- - inspecting private `users-web` internals or creating a page-local transport
53
+ - inspecting private `http-web` internals or creating a page-local transport
54
54
  for generated record deletion
55
55
  - pushing derived write rules into the client just because the action is small
@@ -25,99 +25,6 @@ For the full repo inventory, read `reference/autogen/README.md` and the package
25
25
  Exports
26
26
  - `isContainerToken(value)`
27
27
 
28
- ### `support/crudFieldContract.js`
29
- Exports
30
- - `CRUD_FIELD_STORAGE_COLUMN`
31
- - `CRUD_FIELD_STORAGE_VIRTUAL`
32
- - `CRUD_FIELD_WRITE_SERIALIZER_DATETIME_UTC`
33
- - `CRUD_LOOKUP_FORM_CONTROL_AUTOCOMPLETE`
34
- - `CRUD_LOOKUP_FORM_CONTROL_SELECT`
35
- - `checkCrudLookupFormControl(value, { context = "crud field ui.formControl", defaultValue = CRUD_LOOKUP_FORM_CONTROL_AUTOCOMPLETE } = {})`
36
- - `resolveCrudFieldSchemaProperties(value, { context = "crud resource field definitions" } = {})`
37
- - `normalizeCrudFieldStorageConfig(fieldDefinition = {}, { context = "crud field storage", fieldKey = "" } = {})`
38
- - `buildCrudOperationSchemaFields(fields = {}, operationName = "")`
39
- - `buildCrudFieldContractMap(resource = {}, { context = "crud resource field contract" } = {})`
40
- - `resolveCrudFieldContractEntry(resource = {}, fieldKey = "", options = {})`
41
- Local functions
42
- - `cloneStructuredFieldMetadata(value = {})`
43
- - `mergeFieldContractEntry(target, source, { context = "crud field contract", fieldKey = "" } = {})`
44
-
45
- ### `support/crudListFilters.js`
46
- Exports
47
- - `CRUD_LIST_FILTER_TYPE_FLAG`
48
- - `CRUD_LIST_FILTER_TYPE_ENUM`
49
- - `CRUD_LIST_FILTER_TYPE_ENUM_MANY`
50
- - `CRUD_LIST_FILTER_TYPE_RECORD_ID`
51
- - `CRUD_LIST_FILTER_TYPE_RECORD_ID_MANY`
52
- - `CRUD_LIST_FILTER_TYPE_DATE`
53
- - `CRUD_LIST_FILTER_TYPE_DATE_RANGE`
54
- - `CRUD_LIST_FILTER_TYPE_NUMBER_RANGE`
55
- - `CRUD_LIST_FILTER_TYPE_PRESENCE`
56
- - `CRUD_LIST_FILTER_TYPES`
57
- - `CRUD_LIST_FILTER_PRESENCE_PRESENT`
58
- - `CRUD_LIST_FILTER_PRESENCE_MISSING`
59
- - `CRUD_LIST_FILTER_PRESENCE_OPTIONS`
60
- - `CRUD_LIST_FILTER_INVALID_VALUES_REJECT`
61
- - `CRUD_LIST_FILTER_INVALID_VALUES_DISCARD`
62
- - `INVALID_CRUD_LIST_FILTER_QUERY_VALUE`
63
- - `normalizeCrudListFilterInvalidValues(value = "")`
64
- - `parseCrudListRangeQueryExpression(value = null)`
65
- - `formatCrudListRangeQueryExpression(startValue = "", endValue = "", { collapseExact = false } = {})`
66
- - `defineCrudListFilters(definitions = {})`
67
- - `createCrudListFilterEmptyValue(filter = {})`
68
- - `createCrudListFilterInitialValue(filter = {})`
69
- - `isCrudListFilterMultiValue(filter = {})`
70
- - `isCrudListFilterStructuredValue(filter = {})`
71
- - `normalizeCrudListFilterUiValue(filter = {}, rawValue)`
72
- - `areCrudListFilterUiValuesEqual(filter = {}, currentValue, expectedValue)`
73
- - `hasCrudListFilterUiValue(filter = {}, rawValue)`
74
- - `listCrudListFilterChipValues(filter = {}, rawValue)`
75
- - `formatCrudListFilterDefaultChipLabel(filter = {}, rawValue, { resolveAtomicValue = null } = {})`
76
- - `formatCrudListFilterQueryValue(filter = {}, value)`
77
- - `parseCrudListFilterQueryValue(filter = {}, value, { invalidValues = CRUD_LIST_FILTER_INVALID_VALUES_REJECT } = {})`
78
- - `resolveCrudListFilterQueryKeys(definition = {})`
79
- - `resolveCrudListFilterOptionLabel(definition = {}, value = "", { fallback = "" } = {})`
80
- Local functions
81
- - `firstCrudListFilterValue(value)`
82
- - `isPrimitiveCrudListFilterInput(value)`
83
- - `isPrimitiveOrPrimitiveArrayCrudListFilterInput(value)`
84
- - `normalizeDateFilterText(value)`
85
- - `normalizeCanonicalRecordIdList(value)`
86
- - `normalizeFiniteFilterNumber(value)`
87
- - `normalizeAllowedFilterTextValue(value, allowedValues = new Set())`
88
- - `normalizeAllowedFilterTextValues(value, allowedValues = new Set())`
89
- - `resolveCrudListFilterAllowedValues(filter = {})`
90
- - `normalizeCrudListDateRangeUiValue(rawValue)`
91
- - `normalizeCrudListNumberRangeUiValue(rawValue)`
92
- - `matchCrudListFilterValues(currentValue, expectedValue)`
93
- - `rejectInvalidCrudListFilterValue({ invalidValues = CRUD_LIST_FILTER_INVALID_VALUES_REJECT } = {})`
94
- - `normalizeCrudListDateRangeQueryValue(value)`
95
- - `normalizeCrudListNumberRangeQueryValue(value)`
96
- - `normalizeCrudListFilterType(value = "")`
97
- - `normalizeCrudListFilterOption(rawOption = null, { context = "filter option" } = {})`
98
- - `normalizeCrudListFilterOptions(rawOptions = [], { context = "filter options" } = {})`
99
- - `normalizeCrudListFilterPresenceOptions(rawOptions = [])`
100
- - `normalizeCrudListFilterLookup(rawLookup = null)`
101
- - `resolveCrudListFilterOptionSet(rawDefinition = {}, type = "")`
102
- - `normalizeCrudListFilterDefinition(rawKey = "", rawDefinition = null)`
103
-
104
- ### `support/crudLookup.js`
105
- Exports
106
- - `DEFAULT_CRUD_LOOKUP_CONTAINER_KEY`
107
- - `normalizeCrudLookupApiPath(value = "")`
108
- - `normalizeCrudLookupNamespace(value = "")`
109
- - `resolveCrudLookupApiPathFromNamespace(value = "")`
110
- - `resolveCrudResourceScopeName(value = "")`
111
- - `normalizeCrudLookupContainerKey(value, { defaultValue = DEFAULT_CRUD_LOOKUP_CONTAINER_KEY, context = "crud lookup container key" } = {})`
112
- - `resolveCrudLookupContainerKey(resource = {}, options = {})`
113
- - `resolveCrudLookupFieldKeys(resource = {}, { allowKeys = [] } = {})`
114
- - `resolveCrudParentFilterKeys(resource = {})`
115
- - `resolveCrudLookupFieldKeyFromRouteParam(resource = {}, routeParamKey = "", { allowKeys = [] } = {})`
116
- - `resolveCrudParentFilterFieldKeyFromRouteParam(resource = {}, routeParamKey = "")`
117
- Local functions
118
- - `resolveCrudLookupFieldEntries(resource = {}, { allowKeys = [] } = {})`
119
- - `resolveCrudLookupCreateSchemaKeys(resource = {})`
120
-
121
28
  ### `support/deepFreeze.js`
122
29
  Exports
123
30
  - `deepFreeze(value, seen = new WeakSet())`
@@ -28,6 +28,7 @@ Startup navigation stays in `KERNEL_MAP.md`.
28
28
  - [google-rewarded-core](/packages/agent-docs/reference/autogen/packages/google-rewarded-core.md)
29
29
  - [google-rewarded-web](/packages/agent-docs/reference/autogen/packages/google-rewarded-web.md)
30
30
  - [http-runtime](/packages/agent-docs/reference/autogen/packages/http-runtime.md)
31
+ - [http-web](/packages/agent-docs/reference/autogen/packages/http-web.md)
31
32
  - [json-rest-api-core](/packages/agent-docs/reference/autogen/packages/json-rest-api-core.md)
32
33
  - [kernel](/packages/agent-docs/reference/autogen/packages/kernel.md)
33
34
  - [mobile-capacitor](/packages/agent-docs/reference/autogen/packages/mobile-capacitor.md)
@@ -100,10 +100,6 @@ Exports
100
100
  - `writeNdjson`
101
101
  - `resolveWorkspaceSlug`
102
102
  - `createServiceToolCatalog`
103
- - `parseJsonObject`
104
- - `resolveInsertedId`
105
- - `stringifyJsonObject`
106
- - `toIso`
107
103
 
108
104
  ### `src/server/lib/aiClient.js`
109
105
  Exports
@@ -189,13 +185,6 @@ Local functions
189
185
  - `resolveActionBackedToolEntries(scope)`
190
186
  - `resolveActionToolEntries(scope, { barredActionIds = [], skipActionPrefixes = [] } = {})`
191
187
 
192
- ### `src/server/repositories/repositoryPersistenceUtils.js`
193
- Exports
194
- - `parseJsonObject`
195
- - `stringifyJsonObject(value)`
196
- - `toIso(value)`
197
- - `resolveInsertedId(insertResult)`
198
-
199
188
  ### `src/shared/assistantPaths.js`
200
189
  Exports
201
190
  - `ASSISTANT_API_RELATIVE_PATH`
@@ -141,6 +141,13 @@ Local functions
141
141
  - `normalizePagination(pagination = {}, { defaultPage = 1, defaultPageSize = 200, maxPageSize = 500 } = {})`
142
142
  - `resolveNextSequence(client, conversationId)`
143
143
 
144
+ ### `src/server/repositories/repositoryPersistenceUtils.js`
145
+ Exports
146
+ - `parseJsonObject`
147
+ - `stringifyJsonObject(value)`
148
+ - `toIso(value)`
149
+ - `resolveInsertedId(insertResult)`
150
+
144
151
  ### `src/server/services/assistantConfigService.js`
145
152
  Exports
146
153
  - `createService({ assistantConfigRepository, consoleService = null, appConfig = {}, resolveAppConfig = null, workspaceScopeSupport = null } = {})`
@@ -14,60 +14,6 @@ Use this on demand; do not load the full index at startup.
14
14
 
15
15
  ### src
16
16
 
17
- ### `src/client/composables/createCrudClientSupport.js`
18
- Exports
19
- - `useCrudClientContext(source = {})`
20
- - `useCrudListRuntime(source = {})`
21
- - `useCrudCreateRuntime(source = {})`
22
- - `useCrudRecordRuntime(source = {}, { recordIdParam = "recordId" } = {})`
23
- - `createCrudClientSupport(source = {})`
24
- Local functions
25
- - `normalizeText(value = "")`
26
- - `normalizeRouteParams(params = {})`
27
- - `normalizePathTemplate(value = "")`
28
- - `resolvePathTemplate(pathTemplate = "", { routeParams = {}, params = {}, context = "resolvePathTemplate" } = {})`
29
-
30
- ### `src/client/composables/crudClientSupportHelpers.js`
31
- Exports
32
- - `DEFAULT_CRUD_OWNERSHIP_FILTER`
33
- - `requireCrudNamespace`
34
- - `resolveCrudClientConfig(source = {})`
35
- - `formatDateTime`
36
- - `resolveCrudRecordChangedEvent`
37
- - `crudScopeQueryKey(namespace = "")`
38
- - `invalidateCrudQueries(queryClient, namespace = "")`
39
- - `crudListQueryKey(surfaceId = "", workspaceSlug = "", namespace = "")`
40
- - `crudViewQueryKey(surfaceId = "", workspaceSlug = "", recordId = "", namespace = "")`
41
- - `toRouteRecordId(value)`
42
- - `normalizeCrudRouteParamName(value, { context = "normalizeCrudRouteParamName" } = {})`
43
- - `resolveCrudRecordPathTemplates(relativePath = "", recordIdParam = "recordId")`
44
- - `resolveCrudRecordPathParams(recordIdLike = "", recordIdParam = "recordId")`
45
- Local functions
46
- - `normalizeRelativePath(value, { context = "resolveCrudClientConfig" } = {})`
47
-
48
- ### `src/client/composables/useCrudRealtimeInvalidation.js`
49
- Exports
50
- - `useCrudRealtimeInvalidation(namespace = "", { event = "", enabled = true, matches = null, queryKey = null } = {})`
51
-
52
- ### `src/client/index.js`
53
- Exports
54
- - `DEFAULT_CRUD_OWNERSHIP_FILTER`
55
- - `resolveCrudClientConfig`
56
- - `crudListQueryKey`
57
- - `crudViewQueryKey`
58
- - `crudScopeQueryKey`
59
- - `invalidateCrudQueries`
60
- - `formatDateTime`
61
- - `resolveCrudRecordChangedEvent`
62
- - `toRouteRecordId`
63
- - `requireCrudNamespace`
64
- - `useCrudClientContext`
65
- - `useCrudListRuntime`
66
- - `useCrudCreateRuntime`
67
- - `useCrudRecordRuntime`
68
- - `createCrudClientSupport`
69
- - `useCrudRealtimeInvalidation`
70
-
71
17
  ### `src/server/createCrudServiceFromResource.js`
72
18
  Exports
73
19
  - `createCrudServiceFromResource(resource = {}, { context = "crudService" } = {})`
@@ -353,21 +299,3 @@ Exports
353
299
  Local functions
354
300
  - `requireCrudServiceRepository(runtime = {}, repository = null)`
355
301
  - `splitCrudListRepositoryCall(query = {}, options = {})`
356
-
357
- ### `src/shared/crudFieldSupport.js`
358
- Exports
359
- - `CRUD_LOOKUP_FORM_CONTROL_AUTOCOMPLETE`
360
- - `CRUD_LOOKUP_FORM_CONTROL_SELECT`
361
- - `CRUD_RUNTIME_LOOKUPS_FIELD_KEY`
362
- - `checkCrudLookupFormControl(value, { context = "crud field ui.formControl", defaultValue = CRUD_LOOKUP_FORM_CONTROL_AUTOCOMPLETE } = {})`
363
- - `isCrudRuntimeOutputOnlyFieldKey(value = "", { lookupContainerKey = CRUD_RUNTIME_LOOKUPS_FIELD_KEY } = {})`
364
-
365
- ### `src/shared/crudNamespaceSupport.js`
366
- Exports
367
- - `normalizeCrudNamespace`
368
- - `requireCrudNamespace`
369
- - `resolveCrudRecordChangedEvent`
370
-
371
- ### `src/shared/crudResource.js`
372
- Exports
373
- - `defineCrudResource`