@jskit-ai/agent-docs 0.1.70 → 0.1.71

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.
@@ -490,7 +490,7 @@ The first new place to inspect is `package.json`:
490
490
  }
491
491
  ```
492
492
 
493
- Three things are worth noticing immediately.
493
+ Four things are worth noticing immediately.
494
494
 
495
495
  - `auth-core` owns the provider-neutral contract, shared actions, policy hooks, and capability normalization.
496
496
  - `auth-provider-local-core` is the selected provider-specific runtime.
@@ -508,7 +508,91 @@ AUTH_LOCAL_BACKEND=file
508
508
 
509
509
  The backend selection is intentionally local-provider-specific. `auth.local.backend` is the public server container token for replacing the file store later; Supabase and other external providers do not use it. A custom local backend must expose a single `withTransaction(callback)` method. JSKIT calls that method for register, login, recovery, password reset, profile update, session revocation, and security operations, and the callback receives transactional `users`, `sessions`, and `recovery` repositories.
510
510
 
511
- The built-in file backend is for low-friction local development, first deploys with one persistent Node instance, and simple apps that accept that storage model. It writes `.jskit/auth/*.passwd` files behind a store-level lock. Do not treat it as horizontally scalable or serverless-safe storage; when the app needs replicated auth storage, register a custom `auth.local.backend` that uses the app's chosen database runtime.
511
+ The built-in file backend is for low-friction local development, first deploys with one persistent Node instance, and simple apps that accept that storage model. It writes `.jskit/auth/*.passwd` files behind a store-level lock. Do not treat it as horizontally scalable or serverless-safe storage; when the app needs replicated auth storage, install the DB-backed local auth package or register a custom `auth.local.backend`.
512
+
513
+ That DB-backed local auth storage is not the same thing as the `users-core` profile tables. `users-core` creates app-owned `users` and `user_settings` rows later. DB-backed local auth stores the provider-owned auth state that the file backend would otherwise keep in `.jskit/auth/`.
514
+
515
+ The batteries-included DB package is `@jskit-ai/auth-provider-local-db-core`. It uses JSKIT's database runtime and owns three auth-local tables:
516
+
517
+ - `auth_local_users` for provider auth identities: normalized email, display name, disabled flag, password algorithm/version/salt/hash, and timestamps.
518
+ - `auth_local_sessions` for refresh sessions: session id, auth-local user id, refresh-token hash, session purpose such as `normal` or `recovery`, expiry, revocation, and timestamps.
519
+ - `auth_local_recovery` for password recovery: recovery token id, auth-local user id, recovery-token hash, expiry, used-at timestamp, and timestamps.
520
+
521
+ To use it, install a JSKIT database runtime and driver, install `auth-provider-local-db-core`, run migrations, and use `AUTH_LOCAL_BACKEND=db`. The package registers `auth.local.backend` for DB mode. If `AUTH_LOCAL_BACKEND=db` is set without the DB backend package, local auth fails instead of falling back to file storage.
522
+
523
+ **Summary: Adding Database-Backed Users**
524
+
525
+ There are two database-backed paths, and they solve different problems.
526
+
527
+ For normal app users and account settings, install the database runtime, install `users-web`, then run the migrations. That gives the app the `users` and `user_settings` tables through `users-core`, plus the `auth.profile.projector` bridge that projects a provider identity into a persistent JSKIT user profile.
528
+
529
+ For local auth credentials and sessions in SQL, keep `AUTH_PROVIDER=local`, install `auth-provider-local-db-core`, set `AUTH_LOCAL_BACKEND=db`, and run migrations. That package owns `auth_local_users`, `auth_local_sessions`, and `auth_local_recovery`, and registers the transactional `auth.local.backend` implementation.
530
+
531
+ The first path makes authenticated people real JSKIT users. The second path moves local auth's passwords, refresh sessions, and recovery tokens out of `.jskit/auth/` and into the database. Many apps need the first path before they need the second.
532
+
533
+ Apps that need audit logs, login counters, MFA records, or password history should add sidecar tables that reference `auth_local_users.id`; do not edit the package-owned auth-local migrations or add app-specific columns to those tables. Apps with different table names, external KMS, non-SQL storage, or unusual tenancy partitioning should replace the backend by registering their own `auth.local.backend`.
534
+
535
+ Local auth also applies the shared auth-service decorator registry from `auth-core`. Use that registry when an app or package needs to wrap provider behavior without owning the local auth tables. The local package exports a narrow helper for after-register work:
536
+
537
+ ```js
538
+ import { registerAuthServiceDecorator } from "@jskit-ai/auth-core/server/authServiceDecoratorRegistry";
539
+ import { createLocalAuthRegisterHookDecorator } from "@jskit-ai/auth-provider-local-core/server/lib/index";
540
+
541
+ registerAuthServiceDecorator(app, "app.auth.local.permissions", (scope) => {
542
+ const permissionsService = scope.make("permissionsService");
543
+
544
+ return createLocalAuthRegisterHookDecorator({
545
+ decoratorId: "app.auth.local.permissions",
546
+ order: 10,
547
+ hook: {
548
+ hookId: "permissions",
549
+ blocking: true,
550
+ async handle({ actor, profile }) {
551
+ await permissionsService.createDefaultsForUser({
552
+ userId: actor.id,
553
+ email: actor.email,
554
+ displayName: profile.displayName
555
+ });
556
+ }
557
+ }
558
+ });
559
+ });
560
+ ```
561
+
562
+ The hook must declare `blocking: true` or `blocking: false`. A blocking hook is awaited and its failure rejects the register call, which fits permission provisioning or other work the app needs before treating registration as complete. A non-blocking hook is scheduled after registration and logs failures, which fits audit logging or metrics. This helper runs after local auth registration and profile projection have succeeded; it does not share the local auth backend transaction. If the extension must be transaction-coupled with credential storage, wrap or replace `auth.local.backend` instead.
563
+
564
+ The local provider also has a separate password strategy seam. Use `auth.local.backend` to change where local auth records are stored. Use `auth.local.passwordStrategy` only when the app needs to change how passwords are hashed or verified, such as during a migration from an existing user table with existing password hashes.
565
+
566
+ Register `auth.local.passwordStrategy` before `AuthLocalServiceProvider` starts:
567
+
568
+ ```js
569
+ import bcrypt from "bcryptjs";
570
+ import { verifyPassword as verifyScryptPassword } from "@jskit-ai/auth-provider-local-core/server/lib/index";
571
+
572
+ app.singleton("auth.local.passwordStrategy", () => ({
573
+ async verifyPassword(password, record) {
574
+ if (typeof record === "string" && /^\$2[aby]\$/.test(record)) {
575
+ return bcrypt.compare(password, record);
576
+ }
577
+
578
+ return verifyScryptPassword(password, record);
579
+ }
580
+ }));
581
+ ```
582
+
583
+ The strategy object can provide `hashPassword(password)`, `verifyPassword(password, storedPasswordRecord)`, or both. Missing methods fall back to the local provider's default scrypt implementation, so a migration verifier can accept old hashes while new registrations, resets, and password changes continue to write default JSKIT password records. JSKIT validates provided methods as functions and calls them with `this` bound to the strategy object.
584
+
585
+ Custom service callers can pass the same object directly:
586
+
587
+ ```js
588
+ createLocalAuthService({
589
+ backend,
590
+ config,
591
+ passwordStrategy
592
+ });
593
+ ```
594
+
595
+ JSKIT core does not install bcrypt or any legacy password dependency. If an app needs a legacy verifier, the app owns that dependency and keeps the backend as storage only.
512
596
 
513
597
  If you later configure local SMTP password recovery, also set `APP_PUBLIC_URL` so reset links point back to the browser URL for this app.
514
598
 
@@ -680,7 +764,9 @@ For ordinary Vue component code there is usually no advantage to writing it this
680
764
 
681
765
  The most important thing to understand is that the browser talks to **your app**, and the app talks to the **selected auth provider** through the provider-neutral `authService` contract.
682
766
 
683
- With the local provider, the selected provider is in the same Node process. It verifies passwords, writes sessions, and stores local auth state through `auth.local.backend`. The default backend writes the `.jskit/auth/*.passwd` files; a custom backend can use a database later without changing the login UI or the shared auth routes.
767
+ With the local provider, the selected provider is in the same Node process. It verifies passwords, writes sessions, and stores local auth state through `auth.local.backend`. The default backend writes the `.jskit/auth/*.passwd` files; `auth-provider-local-db-core` moves that storage into package-owned database tables without changing the login UI or the shared auth routes.
768
+
769
+ If `users-core` or another package registers `auth.profile.projector`, local auth now resolves that projector lazily when it actually builds an auth payload for register, login, session refresh, or request authentication. That keeps local auth boot independent from the projector's own dependencies, such as repositories behind `internal.json-rest-api`.
684
770
 
685
771
  That means there are two actors in the first-app flow:
686
772
 
@@ -718,11 +718,16 @@ Inside the local provider, auth only projects provider identities into the app u
718
718
 
719
719
  ```js
720
720
  const profileProjector = scope.has("auth.profile.projector")
721
- ? scope.make("auth.profile.projector")
721
+ ? {
722
+ async syncIdentityProfile(profile, options = {}) {
723
+ const projector = scope.make("auth.profile.projector");
724
+ return projector.syncIdentityProfile(profile, options);
725
+ }
726
+ }
722
727
  : null;
723
728
  ```
724
729
 
725
- That snippet explains the whole consequence of this chapter.
730
+ That snippet explains the whole consequence of this chapter. The provider checks whether the token exists, but it does not resolve the real projector until an auth payload actually needs profile projection.
726
731
 
727
732
  - The auth provider can authenticate users without an app database.
728
733
  - Nothing in `database-runtime-mysql` registers `auth.profile.projector`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.70",
3
+ "version": "0.1.71",
4
4
  "description": "Distributed JSKIT agent references, prompts, guides, and generated reference maps.",
5
5
  "type": "module",
6
6
  "files": [
@@ -13,6 +13,7 @@ Startup navigation stays in `KERNEL_MAP.md`.
13
13
  - [assistant-runtime](/packages/agent-docs/reference/autogen/packages/assistant-runtime.md)
14
14
  - [auth-core](/packages/agent-docs/reference/autogen/packages/auth-core.md)
15
15
  - [auth-provider-local-core](/packages/agent-docs/reference/autogen/packages/auth-provider-local-core.md)
16
+ - [auth-provider-local-db-core](/packages/agent-docs/reference/autogen/packages/auth-provider-local-db-core.md)
16
17
  - [auth-provider-supabase-core](/packages/agent-docs/reference/autogen/packages/auth-provider-supabase-core.md)
17
18
  - [auth-web](/packages/agent-docs/reference/autogen/packages/auth-web.md)
18
19
  - [console-core](/packages/agent-docs/reference/autogen/packages/console-core.md)
@@ -65,6 +65,7 @@ Local functions
65
65
  ### `src/server/authServiceDecoratorRegistry.js`
66
66
  Exports
67
67
  - `AUTH_SERVICE_DECORATOR_TAG`
68
+ - `applyAuthServiceDecorators(scope, authService)`
68
69
  - `registerAuthServiceDecorator(app, token, factory)`
69
70
  - `resolveAuthServiceDecorators(scope)`
70
71
  Local functions
@@ -47,6 +47,8 @@ Local functions
47
47
  Exports
48
48
  - `createLocalAuthService`
49
49
  - `createLocalFileBackend`
50
+ - `LOCAL_AUTH_USER_REGISTERED_EVENT`
51
+ - `createLocalAuthRegisterHookDecorator`
50
52
  - `hashPassword`
51
53
  - `normalizePasswordStrategy`
52
54
  - `verifyPassword`
@@ -60,6 +62,16 @@ Local functions
60
62
  - `base64url(buffer)`
61
63
  - `fromBase64url(value)`
62
64
 
65
+ ### `src/server/lib/registerHookDecorator.js`
66
+ Exports
67
+ - `LOCAL_AUTH_USER_REGISTERED_EVENT`
68
+ - `createLocalAuthRegisterHookDecorator({ decoratorId = "auth.local.registerHook", order = 0, logger = null, hook = null } = {})`
69
+ Local functions
70
+ - `assertBlockingMode(hook)`
71
+ - `normalizeRegisterHook(hook = null)`
72
+ - `logNonBlockingHookFailure({ logger, hook, error } = {})`
73
+ - `runRegisterHook({ hook, result, logger })`
74
+
63
75
  ### `src/server/lib/service.js`
64
76
  Exports
65
77
  - `createLocalAuthService({ backend, config, profileProjector = null, passwordStrategy = null, invitationContextResolver = null })`
@@ -96,6 +108,7 @@ Local functions
96
108
  ### `src/server/providers/AuthLocalServiceProvider.js`
97
109
  Exports
98
110
  - `AuthLocalServiceProvider`
111
+ - `resolveLocalBackendMode(scope)`
99
112
  Local functions
100
113
  - `parseBoolean(value, fallback = false)`
101
114
  - `resolveRuntimeEnv(scope)`
@@ -0,0 +1,56 @@
1
+ # packages/auth-provider-local-db-core
2
+
3
+ Generated by `npm run agent-docs:build`.
4
+ Do not edit manually.
5
+
6
+ Generated inventory for `packages/auth-provider-local-db-core`.
7
+ Use this on demand; do not load the full index at startup.
8
+
9
+ ## Scope
10
+ - Source: `packages/auth-provider-local-db-core/**/*{.js,.mjs,.cjs,.vue}`
11
+ - Excludes: `test/`, `tests/`, `__tests__/`, `*.test.*`, `*.spec.*`, `*.vitest.*`, `node_modules/`, `dist/`, `coverage/`, `docs/`, `LEGACY/`, `.vitepress/cache/`, `.vitepress/dist/`
12
+
13
+ ## Sections
14
+
15
+ ### src
16
+
17
+ ### `src/server/lib/dbBackend.js`
18
+ Exports
19
+ - `LOCAL_AUTH_DB_TABLES`
20
+ - `createLocalDbBackend({ knex, transactionManager } = {})`
21
+ Local functions
22
+ - `nowIso()`
23
+ - `toDate(value)`
24
+ - `requiredDateTime(value, fallback = nowIso())`
25
+ - `optionalDateTime(value)`
26
+ - `readDateTime(value, fallback = "")`
27
+ - `readPassword(row)`
28
+ - `writePassword(password = {})`
29
+ - `mapUser(row)`
30
+ - `mapSession(row)`
31
+ - `mapRecovery(row)`
32
+ - `userInsert(input = {})`
33
+ - `sessionInsert(input = {})`
34
+ - `recoveryInsert(input = {})`
35
+ - `assertBackendDependencies({ knex, transactionManager } = {})`
36
+
37
+ ### `src/server/lib/index.js`
38
+ Exports
39
+ - `createLocalDbBackend`
40
+ - `LOCAL_AUTH_DB_TABLES`
41
+
42
+ ### `src/server/providers/AuthLocalDbBackendServiceProvider.js`
43
+ Exports
44
+ - `AuthLocalDbBackendServiceProvider`
45
+
46
+ ### templates
47
+
48
+ ### `templates/migrations/auth_local_db_initial.cjs`
49
+ Exports
50
+ - None
51
+
52
+ ### root
53
+
54
+ ### `package.descriptor.mjs`
55
+ Exports
56
+ - None
@@ -243,7 +243,6 @@ Local functions
243
243
  - `assertSelectedAuthProvider(env)`
244
244
  - `resolveOptionalRepositories(scope)`
245
245
  - `isDeferredJsonRestBootGap(app, error)`
246
- - `applyAuthServiceDecorators(scope, authService)`
247
246
 
248
247
  ### root
249
248