@jskit-ai/agent-docs 0.1.126 → 0.1.128

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.
@@ -47,7 +47,7 @@ So the first visible value of the package is not a whole new screen. It is a tin
47
47
 
48
48
  The app already had a browser dev server on `5173` and a backend runtime on `3000`.
49
49
 
50
- `realtime` extends that setup by writing a websocket proxy entry into `.jskit/vite.dev.proxy.json` for `/socket.io`. That matters because the browser should still talk to the frontend dev server on `5173`, while Vite quietly forwards websocket traffic to the backend runtime on `3000`.
50
+ `realtime` declares a websocket proxy for `/socket.io` in its published `package.json.jskit` metadata. The JSKIT Vite plugin reads that declaration from the installed npm graph and forwards websocket traffic from the frontend dev server on `5173` to the backend runtime on `3000`.
51
51
 
52
52
  So one of the main values of this package is that you do **not** have to hand-edit Vite config just to make socket.io work in local development.
53
53
 
@@ -210,26 +210,26 @@ REALTIME_REDIS_URL=
210
210
 
211
211
  That empty value is deliberate. It means the app can start with the in-memory adapter locally, and you can fill in a real Redis URL later if you need cross-instance fan-out.
212
212
 
213
- ### `.jskit/vite.dev.proxy.json` gains a websocket proxy entry
213
+ ### Package metadata declares the websocket proxy
214
214
 
215
- After the install, the app has:
215
+ The installed `@jskit-ai/realtime` package declares:
216
216
 
217
217
  ```json
218
218
  {
219
- "version": 1,
220
- "entries": [
221
- {
222
- "packageId": "@jskit-ai/realtime",
223
- "id": "realtime-socket-io",
224
- "path": "/socket.io",
225
- "changeOrigin": true,
226
- "ws": true
219
+ "jskit": {
220
+ "vite": {
221
+ "proxy": {
222
+ "/socket.io": {
223
+ "changeOrigin": true,
224
+ "ws": true
225
+ }
226
+ }
227
227
  }
228
- ]
228
+ }
229
229
  }
230
230
  ```
231
231
 
232
- That one entry is what lets the browser dev server proxy websocket traffic correctly during local development.
232
+ `createJskitClientBootstrapPlugin({ proxyTarget })` reads that metadata directly. The application owns only its normal Vite config and proxy target; installing or removing the npm package changes the active proxy on the next Vite start without generated project state.
233
233
 
234
234
  ### `src/placement.js` includes the shell status placement
235
235
 
@@ -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
 
@@ -54,7 +54,7 @@ Move every package relationship from `jskit.dependsOn` to the appropriate standa
54
54
 
55
55
  Pin `@jskit-ai/*` packages to exact versions. Remove `jskit.dependsOn` completely.
56
56
 
57
- Keep provider-class `static dependsOn` declarations. Those order providers inside the runtime container and are not npm package relationships.
57
+ Rename provider-class `static dependsOn` to `static startsAfter`, then audit every entry. Keep only providers whose registration or boot must complete before the declaring provider reaches the same phase. JSKIT completes registration for the entire graph before beginning any boot method, so a lazily consumed service does not justify an ordering edge.
58
58
 
59
59
  ## 4. Remove Beta 1 project state
60
60
 
@@ -63,11 +63,22 @@ Delete these paths from the application:
63
63
  ```text
64
64
  .jskit/lock.json
65
65
  .jskit/verification/
66
+ .jskit/vite.dev.proxy.json
66
67
  ```
67
68
 
68
69
  Remove ignore rules created solely for `.jskit/verification/`.
69
70
 
70
- Do not translate either file into a replacement. Final Release derives package state from `package.json`, `package-lock.json`, installed package manifests, application config, migration files, and generated CI.
71
+ Do not translate these paths into replacements. Final Release derives package state from `package.json`, `package-lock.json`, installed package manifests, application config, migration files, and generated CI.
72
+
73
+ Delete the app-local Vite proxy loader and any `vite.shared.mjs` file used only for that generated JSON. Pass the application's API target to the standard plugin instead:
74
+
75
+ ```js
76
+ createJskitClientBootstrapPlugin({
77
+ proxyTarget: apiProxyTarget
78
+ })
79
+ ```
80
+
81
+ Installed packages now declare development proxies in `package.json.jskit.vite.proxy`, and the plugin derives the active proxy table directly whenever Vite starts.
71
82
 
72
83
  ## 5. Replace command usage
73
84
 
@@ -95,7 +106,99 @@ npm ls
95
106
 
96
107
  Resolve npm peer or capability errors as package-graph errors. Do not add overrides that mix Beta 1 and Final Release packages.
97
108
 
98
- ## 7. Generate deterministic projections
109
+ ## 7. Move neutral web operations out of users-web
110
+
111
+ Final Release owns browser request, command, list, view, add/edit, permission,
112
+ paging, and generated CRUD UI APIs in `@jskit-ai/http-web`. There are no
113
+ `users-web` compatibility exports.
114
+
115
+ Add the coordinated `@jskit-ai/http-web` version to every application or
116
+ workspace that uses these APIs. Keep `@jskit-ai/users-web` only where the code
117
+ actually uses account, profile, or user-specific shell UI.
118
+
119
+ Update imports as follows:
120
+
121
+ | Beta 1 import or API | Final Release import or API |
122
+ | --- | --- |
123
+ | `@jskit-ai/users-web/client/composables/useCommand` | `@jskit-ai/http-web/client/composables/useCommand` |
124
+ | `@jskit-ai/users-web/client/composables/useEndpointResource` | `@jskit-ai/http-web/client/composables/useEndpointResource` |
125
+ | `@jskit-ai/users-web/client/composables/useList` | `@jskit-ai/http-web/client/composables/useList` |
126
+ | `@jskit-ai/users-web/client/composables/useView` | `@jskit-ai/http-web/client/composables/useView` |
127
+ | `@jskit-ai/users-web/client/composables/useAddEdit` | `@jskit-ai/http-web/client/composables/useAddEdit` |
128
+ | `@jskit-ai/users-web/client/composables/useAccess` | `@jskit-ai/http-web/client/composables/useAccess` |
129
+ | `@jskit-ai/users-web/client/composables/usePagedCollection` | `@jskit-ai/http-web/client/composables/usePagedCollection` |
130
+ | `@jskit-ai/users-web/client/composables/useRealtimeQueryInvalidation` | `@jskit-ai/http-web/client/composables/useRealtimeQueryInvalidation` |
131
+ | `@jskit-ai/users-web/client/composables/runtime/useUiFeedback` | `@jskit-ai/http-web/client/composables/useUiFeedback` |
132
+ | `@jskit-ai/users-web/client/composables/useCrud*` | `@jskit-ai/http-web/client/composables/useCrud*` |
133
+ | `@jskit-ai/users-web/client/components/Crud*` | `@jskit-ai/http-web/client/components/Crud*` |
134
+ | `@jskit-ai/users-web/client/filters` | `@jskit-ai/http-web/client/filters` |
135
+ | `@jskit-ai/users-web/client/bulkActions` | `@jskit-ai/http-web/client/bulkActions` |
136
+ | `@jskit-ai/users-web/client/rowActions` | `@jskit-ai/http-web/client/rowActions` |
137
+ | `@jskit-ai/users-web/client/lib/permissions` | `@jskit-ai/http-web/client/lib/permissions` |
138
+ | `@jskit-ai/users-web/client/support/contractGuards` | `@jskit-ai/http-web/client/support/contractGuards` |
139
+ | `configureUsersWebHttpClient(...)` | `configureHttpWebClient(...)` from `@jskit-ai/http-web/client/lib/httpClient` |
140
+ | `usersWebHttpClient` | `httpWebClient` from `@jskit-ai/http-web/client/lib/httpClient` |
141
+
142
+ Search every application workspace, generated route tree, test fixture, and
143
+ app bootstrap. An application that leaves even one removed import will fail at
144
+ module resolution; this is intentional because Final Release contains no
145
+ forwarding bridge.
146
+
147
+ `crud-ui-generator` now installs `@jskit-ai/http-web`. `ui-generator` installs
148
+ no users product. Existing generated files are application-owned, so update
149
+ their imports directly or deliberately regenerate them and review the diff.
150
+
151
+ After all imports are updated, remove `@jskit-ai/users-web` from any workspace
152
+ that used it only for neutral client APIs. This prevents those applications
153
+ from activating users, authentication, uploads, storage, or database
154
+ capabilities accidentally.
155
+
156
+ ## 8. Use the separated CRUD package boundaries
157
+
158
+ Final Release separates shared resource contracts, browser CRUD, and
159
+ database-backed CRUD:
160
+
161
+ - `@jskit-ai/resource-crud-core` owns environment-neutral CRUD resource,
162
+ field, lookup, namespace, and list-filter contracts;
163
+ - `@jskit-ai/http-web` owns browser request runtimes and generated CRUD UI;
164
+ - `@jskit-ai/crud-core` owns database-backed server CRUD services and
165
+ repositories.
166
+
167
+ Update shared-contract imports as follows:
168
+
169
+ | Beta 1 import | Final Release import |
170
+ | --- | --- |
171
+ | `@jskit-ai/kernel/shared/support/crudFieldContract` | `@jskit-ai/resource-crud-core/shared/crudFieldContract` |
172
+ | `@jskit-ai/kernel/shared/support/crudLookup` | `@jskit-ai/resource-crud-core/shared/crudLookup` |
173
+ | `@jskit-ai/kernel/shared/support/crudListFilters` | `@jskit-ai/resource-crud-core/shared/crudListFilters` |
174
+ | `@jskit-ai/crud-core/shared/crudResource` | `@jskit-ai/resource-crud-core/shared/crudResource` |
175
+ | `@jskit-ai/crud-core/shared/crudNamespaceSupport` | `@jskit-ai/resource-crud-core/shared/crudNamespaceSupport` |
176
+ | `checkCrudLookupFormControl` from `@jskit-ai/crud-core/shared/crudFieldSupport` | `checkCrudLookupFormControl` from `@jskit-ai/resource-crud-core/shared/crudFieldContract` |
177
+ | `isCrudRuntimeOutputOnlyFieldKey` from `@jskit-ai/crud-core/shared/crudFieldSupport` | `isCrudRuntimeOutputOnlyFieldKey` from `@jskit-ai/resource-crud-core/shared/crudLookup` |
178
+
179
+ There is no `@jskit-ai/crud-core/client` surface. Replace browser imports from
180
+ that surface with the corresponding `@jskit-ai/http-web` API. Add
181
+ `@jskit-ai/resource-crud-core` directly wherever application code imports its
182
+ contracts. Remove `@jskit-ai/crud-core` from client-only and generator-only
183
+ workspaces; retain it only where database-backed server CRUD is used.
184
+
185
+ The current CRUD UI templates import `@jskit-ai/http-web`, and the CRUD UI
186
+ generator no longer installs the server CRUD runtime. Existing generated files
187
+ are application-owned, so update their imports directly or deliberately
188
+ regenerate them and review the diff.
189
+
190
+ If application tests or package tooling refer to workspaces-web mutation IDs,
191
+ rename the `users-web-*` prefix on workspaces-web-owned mutations to
192
+ `workspaces-web-*`. Package-internal `UsersWorkspace*` component paths are not
193
+ public APIs; remove any direct imports and use the exported workspaces-web
194
+ provider surface.
195
+
196
+ If application code imported repository persistence helpers from
197
+ `@jskit-ai/assistant-core/server`, keep those helpers with the repository that
198
+ uses them or use the matching database-runtime primitive. Assistant core no
199
+ longer owns database persistence utilities.
200
+
201
+ ## 9. Generate deterministic projections
99
202
 
100
203
  Synchronize package migration files without applying them:
101
204
 
@@ -118,7 +221,7 @@ npx jskit ci generate
118
221
 
119
222
  Move application-specific CI into separate workflow files. The generated JSKIT workflow is replaced in full whenever this command runs.
120
223
 
121
- ## 8. Verify the application
224
+ ## 10. Verify the application
122
225
 
123
226
  ```bash
124
227
  npx jskit lint-packages
@@ -138,7 +241,7 @@ npm run db:migrate
138
241
 
139
242
  Commit package manifests, `package-lock.json`, synchronized migrations, generated CI, and required application changes together.
140
243
 
141
- ## 9. Update strict resource boundaries
244
+ ## 11. Update strict resource boundaries
142
245
 
143
246
  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
247
 
@@ -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.
@@ -40,6 +40,9 @@ A JSKIT package is an ordinary npm package with a `jskit` object in `package.jso
40
40
  "providers": []
41
41
  }
42
42
  },
43
+ "vite": {
44
+ "proxy": {}
45
+ },
43
46
  "mutations": {
44
47
  "dependencies": {
45
48
  "runtime": {},
@@ -63,7 +66,9 @@ needed by generated application-owned source or application-level tooling. It
63
66
  does not declare relationships between JSKIT packages and does not affect
64
67
  package ordering.
65
68
 
66
- `runtime.server.providers` and `runtime.client.providers` declare runtime entrypoints. A provider class may use `static dependsOn` to order providers inside the runtime container; that is provider boot ordering, not package installation.
69
+ `runtime.server.providers` and `runtime.client.providers` declare runtime entrypoints. A provider class may use `static startsAfter` when its own registration or boot genuinely requires another provider to have completed the same lifecycle phase first. JSKIT registers every provider before booting any provider, so later service consumption does not require an ordering declaration.
70
+
71
+ `jskit.vite.proxy` declares development proxy requirements as path-keyed metadata. `createJskitClientBootstrapPlugin({ proxyTarget })` reads those declarations directly from the installed npm graph when Vite starts. Package installation does not generate an intermediate proxy file.
67
72
 
68
73
  Use exact versions for `@jskit-ai/*` dependencies. npm's `package-lock.json` remains the reproducible installation record.
69
74
 
@@ -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
@@ -251,13 +251,7 @@ The owning provider creates the visibility object during `register()` and consum
251
251
  class OrganisationUnitsProvider {
252
252
  static id = "crud.organisation_units";
253
253
 
254
- static dependsOn = [
255
- "runtime.actions",
256
- "runtime.database",
257
- "auth.policy.fastify",
258
- "local.main",
259
- "json-rest-api.core"
260
- ];
254
+ static startsAfter = ["json-rest-api.core", "local.main", "runtime.actions"];
261
255
 
262
256
  register(app) {
263
257
  app.instance(
@@ -345,8 +339,6 @@ The safety package depends on organisation-units and registers its grant:
345
339
  class SafetyProvider {
346
340
  static id = "safety.core";
347
341
 
348
- static dependsOn = ["crud.organisation_units"];
349
-
350
342
  register(app) {
351
343
  registerOrganisationUnitVisibility(app, {
352
344
  id: "safety-manager-descendants",
@@ -360,7 +352,7 @@ class SafetyProvider {
360
352
 
361
353
  The organisation-units package never imports safety. Installing safety adds the grant; omitting safety leaves that grant absent.
362
354
 
363
- The npm dependency must point in the same direction as the provider dependency: safety depends on organisation-units, and organisation-units does not depend on safety.
355
+ No provider start-order declaration is needed here. JSKIT completes every provider's `register()` phase before any provider begins `boot()`, so safety's contribution is present before organisation-units seals the registry. The normal npm dependency points from safety to organisation-units because safety imports its registration API.
364
356
 
365
357
  ## Descendant visibility with a recursive CTE
366
358
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.126",
3
+ "version": "0.1.128",
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