@jskit-ai/agent-docs 0.1.1

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 (73) hide show
  1. package/DISTR_AGENT.md +25 -0
  2. package/guide/agent/app-extras/assistant.md +636 -0
  3. package/guide/agent/app-extras/realtime.md +223 -0
  4. package/guide/agent/app-setup/a-more-interesting-shell.md +643 -0
  5. package/guide/agent/app-setup/authentication.md +948 -0
  6. package/guide/agent/app-setup/console.md +316 -0
  7. package/guide/agent/app-setup/database-layer.md +775 -0
  8. package/guide/agent/app-setup/initial-scaffolding.md +714 -0
  9. package/guide/agent/app-setup/multi-homing.md +655 -0
  10. package/guide/agent/app-setup/users.md +355 -0
  11. package/guide/agent/app-setup/working-with-the-jskit-cli.md +983 -0
  12. package/guide/agent/generators/advanced-cruds.md +923 -0
  13. package/guide/agent/generators/crud-generators.md +556 -0
  14. package/guide/agent/generators/intro.md +63 -0
  15. package/guide/agent/generators/ui-generators.md +648 -0
  16. package/guide/agent/index.md +39 -0
  17. package/guide/human/app-extras/assistant.md +695 -0
  18. package/guide/human/app-extras/realtime.md +270 -0
  19. package/guide/human/app-setup/a-more-interesting-shell.md +734 -0
  20. package/guide/human/app-setup/authentication.md +963 -0
  21. package/guide/human/app-setup/console.md +352 -0
  22. package/guide/human/app-setup/database-layer.md +822 -0
  23. package/guide/human/app-setup/initial-scaffolding.md +738 -0
  24. package/guide/human/app-setup/multi-homing.md +795 -0
  25. package/guide/human/app-setup/users.md +404 -0
  26. package/guide/human/app-setup/working-with-the-jskit-cli.md +997 -0
  27. package/guide/human/generators/advanced-cruds.md +923 -0
  28. package/guide/human/generators/crud-generators.md +556 -0
  29. package/guide/human/generators/intro.md +109 -0
  30. package/guide/human/generators/ui-generators.md +665 -0
  31. package/guide/human/index.md +39 -0
  32. package/package.json +28 -0
  33. package/reference/autogen/KERNEL_MAP.md +536 -0
  34. package/reference/autogen/README.md +44 -0
  35. package/reference/autogen/packages/agent-docs.md +13 -0
  36. package/reference/autogen/packages/assistant-core.md +310 -0
  37. package/reference/autogen/packages/assistant-runtime.md +219 -0
  38. package/reference/autogen/packages/assistant.md +73 -0
  39. package/reference/autogen/packages/auth-core.md +352 -0
  40. package/reference/autogen/packages/auth-provider-supabase-core.md +223 -0
  41. package/reference/autogen/packages/auth-web.md +267 -0
  42. package/reference/autogen/packages/console-core.md +116 -0
  43. package/reference/autogen/packages/console-web.md +37 -0
  44. package/reference/autogen/packages/crud-core.md +283 -0
  45. package/reference/autogen/packages/crud-server-generator.md +220 -0
  46. package/reference/autogen/packages/crud-ui-generator.md +154 -0
  47. package/reference/autogen/packages/database-runtime-mysql.md +61 -0
  48. package/reference/autogen/packages/database-runtime-postgres.md +39 -0
  49. package/reference/autogen/packages/database-runtime.md +216 -0
  50. package/reference/autogen/packages/http-runtime.md +213 -0
  51. package/reference/autogen/packages/kernel.md +1350 -0
  52. package/reference/autogen/packages/realtime.md +95 -0
  53. package/reference/autogen/packages/shell-web.md +349 -0
  54. package/reference/autogen/packages/storage-runtime.md +39 -0
  55. package/reference/autogen/packages/ui-generator.md +101 -0
  56. package/reference/autogen/packages/uploads-image-web.md +76 -0
  57. package/reference/autogen/packages/uploads-runtime.md +85 -0
  58. package/reference/autogen/packages/users-core.md +307 -0
  59. package/reference/autogen/packages/users-web.md +473 -0
  60. package/reference/autogen/packages/workspaces-core.md +415 -0
  61. package/reference/autogen/packages/workspaces-web.md +372 -0
  62. package/reference/autogen/tooling/config-eslint.md +52 -0
  63. package/reference/autogen/tooling/create-app.md +194 -0
  64. package/reference/autogen/tooling/jskit-catalog.md +27 -0
  65. package/reference/autogen/tooling/jskit-cli.md +624 -0
  66. package/reference/autogen/tooling/test-support.md +27 -0
  67. package/reference/autogen/tooling/testUtils.md +31 -0
  68. package/templates/APP_BLUEPRINT.md +57 -0
  69. package/workflow/app-state.md +33 -0
  70. package/workflow/bootstrap.md +24 -0
  71. package/workflow/feature-delivery.md +21 -0
  72. package/workflow/review.md +22 -0
  73. package/workflow/scoping.md +26 -0
@@ -0,0 +1,404 @@
1
+ <!-- Generated by `npm run agent-docs:build` from `docs/guide/app-setup/users.md`. Do not edit manually. -->
2
+
3
+ # Users
4
+
5
+ At the end of the previous chapter, the app had a real database runtime, but it still did not have JSKIT's own persistent users layer. Authentication worked, but the app-side profile mirror was still only the temporary fallback from the auth chapter.
6
+
7
+ This chapter is where that changes. We install `users-web`, run the new migrations, and let JSKIT start treating authenticated people as persistent app users rather than only as Supabase identities.
8
+
9
+ `users-web` sounds like a UI package, but it is actually the point where several layers arrive together:
10
+
11
+ - the persistent users/account data model from `users-core`
12
+ - the account surface and account settings UI
13
+ - the switch from standalone auth profile sync to users-backed auth profile sync
14
+
15
+ This is also the first chapter where the difference between "JSKIT wrote migration files into the app" and "Knex applied those files to the database" becomes important in practice.
16
+
17
+ ## Recap from previous chapters
18
+
19
+ To get back to the same starting point as the end of the previous chapter, run:
20
+
21
+ ```bash
22
+ SUPABASE_URL=...
23
+ SUPABASE_KEY=...
24
+ DB_HOST=127.0.0.1
25
+ DB_PORT=3306
26
+ DB_NAME=exampleapp
27
+ DB_USER=exampleapp
28
+ DB_PASSWORD=secret
29
+
30
+ npx @jskit-ai/create-app exampleapp --tenancy-mode none
31
+ cd exampleapp
32
+ npm install
33
+
34
+ npx jskit add package shell-web
35
+ npx jskit add package auth-provider-supabase-core \
36
+ --auth-supabase-url "$SUPABASE_URL" \
37
+ --auth-supabase-publishable-key "$SUPABASE_KEY" \
38
+ --app-public-url "http://localhost:5173"
39
+ npx jskit add bundle auth-base
40
+ npx jskit add package database-runtime-mysql \
41
+ --db-host "$DB_HOST" \
42
+ --db-port "$DB_PORT" \
43
+ --db-name "$DB_NAME" \
44
+ --db-user "$DB_USER" \
45
+ --db-password "$DB_PASSWORD"
46
+ npm install
47
+ ```
48
+
49
+ If you are already continuing from the previous chapter, you are already in the right place and can skip that setup.
50
+
51
+ ## Installing `users-web`
52
+
53
+ From inside `exampleapp`, run:
54
+
55
+ ```bash
56
+ npx jskit add package users-web
57
+ npm install
58
+ npm run db:migrate
59
+ ```
60
+
61
+ The first command adds `users-web`, but the important part is what arrives with it through its dependency chain.
62
+
63
+ - `users-web` adds the account-facing UI and client runtime pieces
64
+ - `users-core` arrives as a dependency and adds the persistent users/account server layer and schema migrations
65
+
66
+ `npm install` downloads those new runtime packages and their dependencies. `npm run db:migrate` is the crucial step that makes the new tables real in MySQL.
67
+
68
+ In the normal install flow, JSKIT materializes the managed `users-core` migration files while the package install is being applied. Then `npm run db:migrate` is what actually runs those files against MySQL.
69
+
70
+ <DocsTerminalTip label="Important" title="Run The Migrations Before Testing Login">
71
+ This is the first chapter where the migration step is not just "nice to have."
72
+
73
+ `users-core` writes:
74
+
75
+ - `AUTH_PROFILE_MODE=users` into `.env`
76
+ - real users/account schema migrations into `migrations/`
77
+
78
+ That means the app is now expected to use the persistent users-backed profile sync service. If you skip `npm run db:migrate`, the code and routes are installed, but the required tables are still missing.
79
+
80
+ So the correct flow is:
81
+
82
+ 1. add `users-web`
83
+ 2. run `npm install`
84
+ 3. if you need JSKIT to refresh the managed migration files, run `npx jskit migrations changed`
85
+ 4. run `npm run db:migrate`
86
+ 5. only then start the app and sign in
87
+
88
+ Most of the time, step 3 is not needed because `jskit add package users-web` already wrote the managed migration files. But the distinction still matters:
89
+
90
+ - `jskit migrations changed` writes or refreshes JSKIT-managed migration files in `migrations/`
91
+ - `npm run db:migrate` actually applies pending migrations to MySQL
92
+ </DocsTerminalTip>
93
+
94
+ ## What changes now
95
+
96
+ This chapter is the real transition from "authentication exists" to "the app knows about users."
97
+
98
+ ### Authentication becomes users-backed
99
+
100
+ In the database chapter, JSKIT still used the standalone in-memory profile mirror. After installing `users-web`, that changes. JSKIT now expects to synchronize authenticated users into real JSKIT tables.
101
+
102
+ That is the biggest architectural change in this chapter.
103
+
104
+ - Supabase still owns the real auth identity and session
105
+ - JSKIT now also owns a persistent users/account data model in MySQL
106
+
107
+ So after this chapter, a signed-in user is no longer only "someone Supabase knows about." They are also a persistent JSKIT-side user with settings and profile state in the app database.
108
+
109
+ ### The app gets an authenticated account surface
110
+
111
+ The app now has a new authenticated surface at `/account`.
112
+
113
+ This is where the starter account settings UI lives. It already has real sections for:
114
+
115
+ - profile
116
+ - preferences
117
+ - notifications
118
+
119
+ Later chapters can extend this account screen with more sections. For example, the multi-homing chapter adds workspace invitation UI through `workspaces-web`, not through `users-web` itself.
120
+
121
+ The important point is that this is no longer just a placeholder route. It is the first app-owned screen that assumes there is a real persistent user model behind it.
122
+
123
+ ### The shell changes for signed-in users
124
+
125
+ Once a user is signed in, the shell becomes noticeably richer.
126
+
127
+ - the profile menu gets a `Settings` entry that leads to `/account`
128
+ - the home surface gets a small users tools widget in the top-right area
129
+ - the auth bootstrap payload now includes persistent user settings instead of only the fallback mirror data
130
+
131
+ So this chapter is also the first one where logging in changes more than just "guest vs signed in." It now changes what persistent user-facing surfaces the app can expose.
132
+
133
+ <figure class="docs-browser-shot">
134
+ <div class="docs-browser-shot__bar">
135
+ <div class="docs-browser-shot__dots" aria-hidden="true">
136
+ <span></span>
137
+ <span></span>
138
+ <span></span>
139
+ </div>
140
+ <div class="docs-browser-shot__address">http://localhost:5173/home</div>
141
+ </div>
142
+ <img
143
+ src="/images/guide/users/users-shell-signed-in.png"
144
+ alt="Example app home surface after the users chapter, showing the signed-in shell with the Settings profile-menu entry"
145
+ />
146
+ </figure>
147
+
148
+ ## What to look at in the browser
149
+
150
+ Start both processes again:
151
+
152
+ ```bash
153
+ npm run dev
154
+ npm run server
155
+ ```
156
+
157
+ Then sign in through `http://localhost:5173/auth/login`.
158
+
159
+ After a successful sign-in, you should notice three concrete differences compared with the previous chapter:
160
+
161
+ - the profile menu now contains `Settings`
162
+ - the top-right area now also has a small users tools widget
163
+ - `/account` now exists and is authenticated
164
+
165
+ This is the first chapter where the app starts to feel like it has a real user model behind it.
166
+
167
+ ## What `users-web` adds to the app
168
+
169
+ The most interesting files now are spread across config, migrations, routing, and the app-owned account UI.
170
+
171
+ ### `.env` flips auth into users mode
172
+
173
+ The most important new line in `.env` is:
174
+
175
+ ```dotenv
176
+ AUTH_PROFILE_MODE=users
177
+ ```
178
+
179
+ That one line explains the deepest change in the chapter.
180
+
181
+ Before this chapter, auth used the standalone fallback profile sync service. After this chapter, auth is told to use the persistent users-backed profile sync flow instead.
182
+
183
+ That only works because `users-core` also installs the required repositories, services, and tables.
184
+
185
+ ### `migrations/` stops being mostly empty
186
+
187
+ After `users-web`, the app gets real schema files such as:
188
+
189
+ ```text
190
+ migrations/
191
+ 2026..._users-core-generic-initial-schema.cjs
192
+ 2026..._users-core-profile-username-schema.cjs
193
+ ```
194
+
195
+ These files are the first real database schema in the guide.
196
+
197
+ The important initial migration creates:
198
+
199
+ - `users`
200
+ - `user_settings`
201
+
202
+ That is why this chapter needs `npm run db:migrate` in a much more serious way than the previous one did.
203
+
204
+ ### `config/public.js` gains one new authenticated surface
205
+
206
+ After the install, `config/public.js` grows one important surface definition:
207
+
208
+ ```js
209
+ config.surfaceDefinitions.account = {
210
+ id: "account",
211
+ label: "Account",
212
+ pagesRoot: "account",
213
+ enabled: true,
214
+ requiresAuth: true,
215
+ requiresWorkspace: false,
216
+ origin: ""
217
+ };
218
+ ```
219
+
220
+ This chapter keeps the split simple:
221
+
222
+ - `account` is the normal authenticated user area
223
+ - operator surfaces such as `console` are introduced later, by packages that actually own them
224
+
225
+ ### `src/placement.js` grows account entries
226
+
227
+ The placement registry also becomes more interesting:
228
+
229
+ ```js
230
+ addPlacement({
231
+ id: "users.profile.menu.settings",
232
+ target: "auth-profile-menu:primary-menu",
233
+ surfaces: ["*"],
234
+ order: 500,
235
+ componentToken: "auth.web.profile.menu.link-item",
236
+ props: {
237
+ label: "Settings",
238
+ to: "/account"
239
+ },
240
+ when: ({ auth }) => Boolean(auth?.authenticated)
241
+ });
242
+ ```
243
+
244
+ This chapter is the first one where one package install adds meaningful authenticated shell entries and a real account surface.
245
+
246
+ ### `src/pages/account/index.vue` is a real authenticated route
247
+
248
+ The account route itself is very small:
249
+
250
+ ```vue
251
+ <route lang="json">
252
+ {
253
+ "meta": {
254
+ "guard": {
255
+ "policy": "authenticated"
256
+ }
257
+ }
258
+ }
259
+ </route>
260
+
261
+ <template>
262
+ <AccountSettingsClientElement />
263
+ </template>
264
+ ```
265
+
266
+ That is a very JSKIT-style file.
267
+
268
+ - the route policy is app-owned
269
+ - the page wrapper is app-owned
270
+ - the heavy UI is delegated to a reusable client element
271
+
272
+ So the route is simple, but it is already a real authenticated account screen rather than a placeholder card.
273
+
274
+ ### The account screen itself is scaffolded app-owned UI
275
+
276
+ The account page is backed by:
277
+
278
+ ```text
279
+ src/components/account/settings/
280
+ AccountSettingsClientElement.vue
281
+ AccountSettingsProfileSection.vue
282
+ AccountSettingsPreferencesSection.vue
283
+ AccountSettingsNotificationsSection.vue
284
+ ```
285
+
286
+ The top-level `AccountSettingsClientElement.vue` uses `useAccountSettingsRuntime()` from `users-web` and wires those sections into a tabbed settings experience.
287
+
288
+ That is worth noticing because the guide has now reached a new level of scaffolding:
289
+
290
+ - earlier chapters mostly introduced shells and routes
291
+ - this chapter introduces real app-owned feature UI that is already split into reusable sections
292
+
293
+ ## Under the hood
294
+
295
+ ### Why auth now behaves differently
296
+
297
+ In the previous chapter, auth still defaulted to the standalone profile sync fallback. The core logic in `AuthSupabaseServiceProvider` looks like this:
298
+
299
+ ```js
300
+ const authProfileMode = resolveAuthProfileMode(env);
301
+ let userProfileSyncService = fallbackStandaloneProfileSyncService;
302
+
303
+ if (authProfileMode === AUTH_PROFILE_MODE_USERS) {
304
+ if (!scope.has("users.profile.sync.service")) {
305
+ throw new Error(
306
+ "AuthSupabaseServiceProvider requires users.profile.sync.service when AUTH_PROFILE_MODE=users."
307
+ );
308
+ }
309
+ userProfileSyncService = scope.make("users.profile.sync.service");
310
+ }
311
+ ```
312
+
313
+ The important part is no longer hypothetical.
314
+
315
+ After `users-web`:
316
+
317
+ - `.env` sets `AUTH_PROFILE_MODE=users`
318
+ - `users-core` supplies the users-backed sync service
319
+ - the migrations supply the required tables
320
+
321
+ So auth now has everything it needs to stop using the fallback mirror and start using the persistent users-backed one.
322
+
323
+ That is the true point of this chapter. The app is no longer just authenticated. It now has a real users layer.
324
+
325
+ ### `users-core` also owns the profile-sync lifecycle registry
326
+
327
+ There is one more seam worth noticing here because later packages depend on it.
328
+
329
+ The important thing to understand is that the public extension API is:
330
+
331
+ ```js
332
+ registerProfileSyncLifecycleContributor(...)
333
+ ```
334
+
335
+ That is the function another server package uses when it wants to run logic after JSKIT has created or synchronized a user record.
336
+
337
+ If you were writing another server package and wanted to run some logic every time a JSKIT user is synchronized, you would register a contributor during package boot:
338
+
339
+ ```js
340
+ import { registerProfileSyncLifecycleContributor } from "@jskit-ai/users-core/server/profileSyncLifecycleContributorRegistry";
341
+
342
+ function registerExampleCore(app) {
343
+ registerProfileSyncLifecycleContributor(app, "example.core.profileSyncLogger", () => {
344
+ return {
345
+ contributorId: "example.core.profileSyncLogger",
346
+ order: 0,
347
+ async afterIdentityProfileSynced({ profile, created } = {}) {
348
+ if (!profile) {
349
+ return;
350
+ }
351
+
352
+ if (created) {
353
+ console.log("Created JSKIT user:", profile.id, profile.email);
354
+ return;
355
+ }
356
+
357
+ console.log("Synchronized existing JSKIT user:", profile.id, profile.email);
358
+ }
359
+ };
360
+ });
361
+ }
362
+ ```
363
+
364
+ That example is deliberately simple, but it shows the real usage pattern:
365
+
366
+ - import `registerProfileSyncLifecycleContributor(...)`
367
+ - call it from your package's server registration code
368
+ - implement `afterIdentityProfileSynced(...)`
369
+ - use `created` to tell "brand-new user" apart from "existing user synchronized again"
370
+
371
+ In a real package, the same seam is useful for things like:
372
+
373
+ - provisioning related rows when a user is created
374
+ - seeding package-owned settings
375
+ - writing audit events
376
+ - attaching app-owned resources to the new user
377
+
378
+ This runs on the server, inside the same overall sync flow. So if your contributor throws, the sync fails too. That is intentional: the seam is for real lifecycle work, not best-effort UI decoration.
379
+
380
+ Under the hood, `users-core` wires those contributors into the users-backed profile sync service. `registerUsersCore()` resolves the registered contributors when it builds `users.profile.sync.service`, and then `authProfileSyncService.syncIdentityProfile()` runs them after the user row and settings row have been synchronized.
381
+
382
+ - `users-core` owns the tagged registry and the execution point
383
+ - auth still only calls one service: `users.profile.sync.service`
384
+ - other packages extend the post-sync lifecycle by registering contributors
385
+
386
+ The next chapter uses exactly that pattern. `workspaces-core` registers a contributor so the workspace layer can react when a new user enters the system.
387
+
388
+ ## Summary
389
+
390
+ This chapter is where the app stopped treating signed-in people as only Supabase identities and started treating them as real JSKIT users.
391
+
392
+ - `users-core` installed the persistent users/account schema and server layer
393
+ - `users-web` installed the first real account surface and account settings UI
394
+ - auth switched from the standalone fallback mirror to the users-backed sync flow
395
+
396
+ That is why this chapter feels bigger than a normal page install. It changes both the browser experience and the server-side meaning of "a signed-in user."
397
+
398
+ At the end of this chapter, the app now has:
399
+
400
+ - real JSKIT-side `users` and `user_settings` tables
401
+ - a real authenticated `/account` surface
402
+ - a shell that can expose user settings and account tools
403
+
404
+ The next chapter adds a different kind of surface: not a personal account area, but a privileged operator console.