@molecule/app-auth 3.0.2 → 3.2.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.
package/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-10-26T04:14:38.335Z
6
+ Generated: 2026-11-02T07:28:20.788Z
7
7
  -->
8
8
 
9
9
  # @molecule/app-auth
@@ -17,19 +17,54 @@ client; `setClient`/`getClient` bond it; `login`/`logout`/`register`/
17
17
  bindings (e.g. `AuthProvider`/`useAuth` in `@molecule/app-react`) wrap the
18
18
  same client.
19
19
 
20
- **In a scaffolded app, wire it by hand — the sandbox cannot run `mlcl add`.**
21
- The package is already installed; create the client once at startup with
20
+ **What this client already handles**
21
+
22
+ - `getAccessToken()` returns a stored token immediately, even while restore is pending.
23
+ - Only 401/403 ends a session; network and 5xx restore failures retain it.
24
+ - `tokenKey`/`storagePrefix`, `authScheme`, `mapAuthResponse`,
25
+ `currentUserEndpoint`, and `profileEndpoint`/`profileUpdateMethod` adapt the API.
26
+ - `logout()` clears the local session even if revocation fails; `refresh()` and
27
+ optional auto-refresh use a stored refresh token.
28
+ - `AuthProvider` renders children immediately and gates nothing; only a route guard
29
+ chooses to wait for `status === 'loading'`.
30
+
31
+ A token nested in the user, a custom key and current-user route, a PUT update,
32
+ and `Authorization: Token <jwt>` need configuration, not another session layer:
33
+
34
+ ```typescript
35
+ import { createJWTAuthClient } from '@molecule/app-auth'
36
+ const client = createJWTAuthClient({
37
+ tokenKey: 'app.jwt',
38
+ authScheme: 'Token',
39
+ currentUserEndpoint: '/user',
40
+ profileEndpoint: '/user',
41
+ profileUpdateMethod: 'PUT',
42
+ mapAuthResponse: (data) => {
43
+ const { token, ...user } = (data as { user: { token: string; id: string } }).user
44
+ return { accessToken: token, user }
45
+ },
46
+ })
47
+ ```
48
+
49
+ **In a scaffolded app, keep the generated auth bond.** It already creates and
50
+ bonds one client from `authConfig`; adapt that config and read the session through
51
+ `MoleculeProvider`/`useAuth()` instead of adding another session layer. In an existing
52
+ app without that bond, create the client once at startup with
22
53
  `setClient(createJWTAuthClient({ baseURL, authScheme: 'Token', storage:
23
54
  createBrowserStorageAdapter() }))`, or `createDefaultAuthClient(authConfig)`
24
- from `@molecule/app-bonds-default-react` (which also registers
25
- `whenRestored()` as the HTTP gate), call `initialize()`, and read the session
26
- through `MoleculeProvider`/`useAuth()` in a React app.
27
-
28
- **`initialize()` restores the session BEFORE the first render, and no
29
- hand-rolled token store may replace it.** With the token AND user in the
30
- store the restore is synchronous and costs no request; with an httpOnly
31
- session cookie the API sets at login it restores through
32
- `currentUserEndpoint` (default `/users/me`). With only an access token,
55
+ from `@molecule/app-bonds-default-react`, then call `initialize()`. The bond's
56
+ HTTP-sync variants also register `whenRestored()` as the request gate.
57
+
58
+ **`initialize()` restores a cached token AND user BEFORE the first render.**
59
+ That restore is synchronous and costs no request. Cookie-only and token-only
60
+ restoration need an asynchronous current-user request. An HttpOnly
61
+ session cookie restores through `currentUserEndpoint` (default `/users/me`).
62
+ The default `cookieRestore: 'hint'` requires a readable `mol_auth=1` cookie
63
+ set by the API alongside the HttpOnly cookie. For an external cookie API
64
+ without that convention, configure `storage: 'memory'`,
65
+ `cookieRestore: 'always'`, and its `currentUserEndpoint`. Keep the HTTP
66
+ client's `withCredentials: true`. This explicit policy also probes anonymous
67
+ loads; a local sign-out suppresses further probes until sign-in succeeds. With only an access token,
33
68
  it loads and maps the profile from that endpoint once before deciding the
34
69
  session: 401/403 clears the token; network/5xx failures retain it as
35
70
  `unavailable`. `AuthClientConfig.storage` is
@@ -50,8 +85,8 @@ then stays on its loading branch).
50
85
  **Never fetch viewer-dependent data before the restore settles.** A
51
86
  component effect that runs on mount fires while `initialize()` is still
52
87
  restoring, so its request leaves without the `Authorization` header and the
53
- server answers for an anonymous viewer — a followed user renders "Follow", a
54
- saved item renders unsaved. On localhost the restore usually wins this race;
88
+ server answers for an anonymous viewer — saved preferences appear unset and
89
+ account-specific controls show anonymous defaults. On localhost the restore usually wins this race;
55
90
  over the network it does not, so the bug appears only on the deployed URL.
56
91
  Gate the fetch on the auth state being settled (`state.initialized`), or let
57
92
  the HTTP client do it: `@molecule/app-bonds-default-react` registers
@@ -71,8 +106,7 @@ mirrors the token into the bonded client.
71
106
  `initialize()` sets that state synchronously, before any request, and every
72
107
  verification settles behind that render. Never hold the first paint on
73
108
  `validateSession()` or a `/me` request of your own — a protected page then pays
74
- an API round trip on every navigation (~30 full page loads in one pagination
75
- spec put four tests at 15.0–15.9 s of a 15 s budget, and two timed out). Route
109
+ an API round trip on every navigation. Route
76
110
  guards read this same `status`: wait only while it is `'loading'` — that
77
111
  status means "no decision yet", so an auth request in flight
78
112
  (`state.loading`) keeps the decided status and does not unmount a
@@ -86,8 +120,9 @@ KEEPS the token and the user (`'unavailable'`, retryable; the 404 error names
86
120
  plus its own listener set is a second session store, and it drifts from the
87
121
  client's.
88
122
 
89
- **Only a 401/403 ENDS a session; no response at all never does.** Every path that
90
- clears the stored session (`validateSession`, the cookie restore, the initial
123
+ **Only a server 401/403 rejects a credential; no response never does.** Explicit
124
+ sign-out and an application restore predicate can also end the local session.
125
+ Every server-failure path that clears the stored session (`validateSession`, the cookie restore, the initial
91
126
  refresh, the background refresh timer) keys on the server REJECTING the
92
127
  credential. An aborted request, a dropped connection, or a 5xx arrives with no
93
128
  HTTP status (or `status: 0` from `@molecule/app-http`) and says nothing about the
@@ -105,10 +140,12 @@ whole parsed body is preserved, nested maps and arrays included, not just the
105
140
  `error`/`message` the message is built from, so a login form can render the
106
141
  API's own validation payload (`{ errors: { credentials: ['is invalid'] } }`)
107
142
  instead of re-implementing the call. A body that is not JSON arrives as `{}`;
108
- the key, message, fallback and rejection are unchanged.
143
+ the key, message, fallback and rejection are unchanged. That same rejection also
144
+ satisfies `isHttpError(err)` from `@molecule/app-http`, with
145
+ `response.data === body`, so an app-http error reader works without changing the
146
+ `I18nError` contract.
109
147
 
110
- **`autoRefresh` does nothing without a refresh token — and must never log the
111
- user out.** The client schedules a refresh only when `refresh()` could actually
148
+ **`autoRefresh` does nothing without a refresh token.** The client schedules a refresh only when `refresh()` could actually
112
149
  succeed, i.e. when a refresh token is stored. An API that issues none (the
113
150
  `@molecule/api-resource-user` model: login/register return `{ accessToken,
114
151
  user }` and the durable session is an httpOnly cookie the SERVER refreshes)
@@ -123,7 +160,8 @@ user, `setSession({ accessToken, user })` stores both and flips the client to
123
160
  (a form's own sign-in code wrote the token and the user with `setAccessToken`/`setUser`,
124
161
  which change their field only — the UI stays signed out and the browser assertions that
125
162
  expect it time out). `setAccessToken()` and `setUser()` are field setters, not a
126
- sign-in: neither sets `authenticated`.
163
+ sign-in: neither establishes an authenticated session. On a signed-in client,
164
+ `setUser(null)` instead ends the local session and clears its stored credentials.
127
165
 
128
166
  **A custom user profile is typed once and used everywhere: `AuthClientConfig<MyUser>`,
129
167
  `createJWTAuthClient<MyUser>` and `useAuth<MyUser>()`.** The config's generic makes
@@ -257,8 +295,8 @@ submission, the saved baseline and cache propagation. Use that composition
257
295
  for editable account forms instead of resetting every field on `user` changes.
258
296
 
259
297
  **A token another tool reads at its own key is a CONFIG field, not a mirror.**
260
- An e2e suite or host page that expects `localStorage.jwtToken` (the RealWorld
261
- specs do) is satisfied by `tokenKey: 'jwtToken'` — in a browser the client's
298
+ An e2e suite or host page that expects `localStorage.getItem('app.jwt')` is
299
+ satisfied by `tokenKey: 'app.jwt'` — in a browser the client's
262
300
  storage default is already `createBrowserStorageAdapter()`, so with an explicit
263
301
  `'memory'` store you must also pass
264
302
  `storage: createBrowserStorageAdapter()`. Writing the token into that key from a
@@ -294,35 +332,35 @@ await login({ email, password })
294
332
  if (isAuthenticated()) console.log(getUser()?.email)
295
333
  ```
296
334
 
297
- An API that wraps the payload and registers extra fields (RealWorld): type those
335
+ An API that wraps the payload and registers extra fields: type those
298
336
  fields with the factory's second generic, and `requestBody` receives exactly what
299
337
  the form passed — `{ user: { username, email, password } }` goes out as-is.
300
338
 
301
339
  ```typescript
302
340
  import { createJWTAuthClient } from '@molecule/app-auth'
303
341
 
304
- // RealWorld's user has no `id`. Name the shape the wire actually sends; the
342
+ // This account API's user has no `id`. Name the shape the wire actually sends; the
305
343
  // client reads no field of it, so nothing has to be invented for a base profile.
306
- interface RealWorldUser {
344
+ interface AccountProfile {
307
345
  username: string
308
346
  email: string
309
347
  bio: string
310
348
  image: string
311
349
  }
312
350
 
313
- const realWorldAuth = createJWTAuthClient<RealWorldUser, { username: string }>({
351
+ const accountAuth = createJWTAuthClient<AccountProfile, { username: string }>({
314
352
  baseURL: '/api',
315
353
  authScheme: 'Token',
316
354
  requestBody: (_kind, payload) => ({ user: payload }),
317
355
  mapAuthResponse: (data) => {
318
- const { user: wire } = data as { user: { token: string } & RealWorldUser }
356
+ const { user: wire } = data as { user: { token: string } & AccountProfile }
319
357
  // Keep every wire field; the bearer stays out of the cached profile.
320
358
  const { token, ...profile } = wire
321
359
  return { accessToken: token, user: profile }
322
360
  },
323
361
  })
324
362
 
325
- await realWorldAuth.register({ username: 'alice', email: 'alice@example.com', password: 's3cret' })
363
+ await accountAuth.register({ username: 'alice', email: 'alice@example.com', password: 's3cret' })
326
364
  ```
327
365
 
328
366
  ## Type
@@ -332,7 +370,7 @@ await realWorldAuth.register({ username: 'alice', email: 'alice@example.com', pa
332
370
  ## Installation
333
371
 
334
372
  ```bash
335
- npm install @molecule/app-auth @molecule/app-bond @molecule/app-i18n @molecule/app-logger
373
+ npm install @molecule/app-auth @molecule/app-bond @molecule/app-http @molecule/app-i18n @molecule/app-logger
336
374
  ```
337
375
 
338
376
  ## API
@@ -468,6 +506,21 @@ interface AuthResult<T = UserProfile> {
468
506
  }
469
507
  ```
470
508
 
509
+ #### `AuthChallenge`
510
+
511
+ A 206 challenge: control fields survive, but no authenticated session exists.
512
+
513
+ ```typescript
514
+ interface AuthChallenge {
515
+ twoFactorRequired: true
516
+ user?: never
517
+ accessToken?: never
518
+ refreshToken?: never
519
+ expiresAt?: never
520
+ [controlField: string]: unknown
521
+ }
522
+ ```
523
+
471
524
  #### `PasswordResetRequest`
472
525
 
473
526
  Password reset request data.
@@ -507,7 +560,10 @@ Reactive authentication state snapshot (initialized, authenticated, user, loadin
507
560
  interface AuthState<T = UserProfile> {
508
561
  /**
509
562
  * The session's state as one value — render from this instead of combining
510
- * `initialized`/`authenticated`/`loading`. See {@link AuthStatus}.
563
+ * `initialized`/`authenticated`/`loading`. `'loading'` is undecided, so wait
564
+ * and redirect only on `'unauthenticated'`; `'unavailable'` keeps the candidate
565
+ * for retry and can have a null profile. A restore failure other than 401/403
566
+ * never signs out. See {@link AuthStatus}.
511
567
  */
512
568
  status: AuthStatus
513
569
 
@@ -517,12 +573,15 @@ interface AuthState<T = UserProfile> {
517
573
  initialized: boolean
518
574
 
519
575
  /**
520
- * Whether the user is authenticated.
576
+ * Whether the client has an authenticated session. This is not a server
577
+ * confirmation flag: during `'unavailable'` it can be false for a retained
578
+ * token/cookie-only candidate with no cached profile. Use `status` for redirects.
521
579
  */
522
580
  authenticated: boolean
523
581
 
524
582
  /**
525
- * Current user (if authenticated).
583
+ * Current user, or null when none is cached. In particular, an `'unavailable'`
584
+ * token/cookie-only restore has a retained candidate but no profile yet.
526
585
  */
527
586
  user: T | null
528
587
 
@@ -555,6 +614,9 @@ to react to the server's own answer:
555
614
  map, a field map with arrays, or a top-level array of messages — without
556
615
  re-implementing the login call. A body that is not JSON (an HTML error
557
616
  page, an empty body) arrives as `{}`.
617
+ - `response`: the same failed-response view as `@molecule/app-http`, with
618
+ `response.data === body`, so `isHttpError` and `response.data` readers work
619
+ on this rejection too.
558
620
 
559
621
  ```typescript
560
622
  import { I18nError } from '@molecule/app-i18n'
@@ -580,6 +642,29 @@ interface AuthError extends I18nError {
580
642
  * maps and arrays included. `{}` when the body is not JSON.
581
643
  */
582
644
  body: unknown
645
+
646
+ /** The app-http-compatible view of the failed response. */
647
+ response: {
648
+ /** The same parsed value as {@link AuthError.body}. */
649
+ data: unknown
650
+ /** The same HTTP status as {@link AuthError.status}. */
651
+ status: number
652
+ /** HTTP status text supplied by the server or fetch implementation. */
653
+ statusText: string
654
+ /** Response headers as a plain object, with credential headers omitted. */
655
+ headers: Record<string, string>
656
+ /** Method and credential-redacted URL only; request bodies and headers are never retained. */
657
+ config: {
658
+ method: string
659
+ url: string
660
+ }
661
+ }
662
+
663
+ /** The same translation key as {@link I18nError.i18nKey}. */
664
+ errorKey: string
665
+
666
+ /** A server response was received, so a non-ok response is never an abort. */
667
+ aborted: false
583
668
  }
584
669
  ```
585
670
 
@@ -647,12 +732,23 @@ interface AuthClient<
647
732
  * Updates the cached user object (state + persistent storage) without
648
733
  * hitting the network. Intended for local refreshes after a per-app
649
734
  * mutation (e.g., the user just PATCHed their own profile and the
650
- * server returned the canonical row). Does NOT change tokens.
735
+ * server returned the canonical row). A non-null profile does NOT change
736
+ * tokens or sign the client in: `authenticated` and `status` are unchanged,
737
+ * so an anonymous client stays anonymous. Use {@link login} /
738
+ * {@link register} for a credential exchange, or {@link setSession} when
739
+ * the token was issued outside the client.
651
740
  *
652
- * This does not sign the client in: `authenticated` and `status` are
653
- * unchanged, so an anonymous client stays anonymous. Use
654
- * {@link login} / {@link register} for a credential exchange, or
655
- * {@link setSession} when the token was issued outside the client.
741
+ * Passing `null` on a signed-in client, or while any session operation is
742
+ * pending, ends the local session: it clears the access token, refresh token
743
+ * and cached user, stops automatic refresh, and settles `authenticated: false`
744
+ * with `status: 'unauthenticated'` in one notification. Every older operation
745
+ * loses session ownership, and a persistent sign-out marker prevents a reload
746
+ * from restoring its credentials or a late cookie. A late credential exchange
747
+ * is revoked best-effort when a logout endpoint is configured, without blocking
748
+ * the caller. This method does not otherwise call the server for a settled
749
+ * session; use {@link logout} for explicit server revocation. On a settled
750
+ * anonymous client, `null` only clears the cached profile and leaves tokens
751
+ * and auth state unchanged.
656
752
  */
657
753
  setUser(user: T | null): void
658
754
 
@@ -669,10 +765,13 @@ interface AuthClient<
669
765
  * which would violate the storage contract and make a stored bearer token
670
766
  * JS-readable (XSS-exfiltratable). Pass `null` to clear it.
671
767
  *
672
- * This changes token storage only; it does not sign the client in
673
- * (`authenticated` and `status` are unchanged). Use {@link login} /
674
- * {@link register} for a credential exchange, or call {@link setSession}
675
- * with the token and the user to establish an already-issued session.
768
+ * This changes token storage only: passing `null` does not by itself sign a
769
+ * signed-in client out, and a non-null token does not sign an anonymous
770
+ * client in (`authenticated` and `status` are unchanged). Use {@link logout}
771
+ * to end a session, or {@link setUser} with `null` for local-only sign-out.
772
+ * Use {@link login} / {@link register} for a credential exchange, or call
773
+ * {@link setSession} with the token and user to establish an already-issued
774
+ * session.
676
775
  */
677
776
  setAccessToken(token: string | null): void
678
777
 
@@ -701,7 +800,16 @@ interface AuthClient<
701
800
  login(credentials: LoginCredentials): Promise<AuthResult<T>>
702
801
 
703
802
  /**
704
- * Logs out the current user.
803
+ * Logs out the current user. The server request is best-effort: a missing
804
+ * logout route (404), any other HTTP failure, or a network error never makes
805
+ * this method reject. It always clears the access token, refresh token and
806
+ * cached user, stops automatic refresh, and publishes one settled
807
+ * `authenticated: false`, `status: 'unauthenticated'` transition. Every pending
808
+ * session operation loses ownership; a persistent marker prevents reload from
809
+ * restoring an older session, and late credentials are revoked best-effort.
810
+ *
811
+ * When the API has no logout route, set {@link AuthClientConfigOptions.logoutEndpoint}
812
+ * to `null` (or `''`) to skip the request. Local sign-out still happens.
705
813
  */
706
814
  logout(): Promise<void>
707
815
 
@@ -768,35 +876,6 @@ interface AuthClient<
768
876
 
769
877
  /**
770
878
  * Re-checks a restored session against the server, in the background — the
771
- * boot-time validation an app with a stored token needs when a revoked or
772
- * expired token must sign the user out. Call it AFTER the first render
773
- * (`initialize()` restores synchronously from storage; this costs one request).
774
- *
775
- * - The server confirms the user: the session is refreshed and {@link AuthState.status}
776
- * stays `'authenticated'`.
777
- * - The server answers 401 or 403: the token is dead — the stored session is
778
- * cleared and the status becomes `'unauthenticated'`.
779
- * - The server cannot confirm the session — a network failure, a 5xx, or a 404
780
- * from a misconfigured {@link AuthClientConfig.currentUserEndpoint}: the
781
- * session (token AND user) is KEPT and the status becomes `'unavailable'`, so
782
- * the app can retry instead of signing the user out over a bad connection or a
783
- * route that does not exist. The 404 error names `currentUserEndpoint`.
784
- *
785
- * Do not hand-write this beside the client: a parallel token/user store for a
786
- * "validating"/"unavailable" flag is the race this method removes.
787
- *
788
- * Optional: a provider with no restorable session has nothing to validate.
789
- */
790
- validateSession?(): Promise<void>
791
-
792
- /**
793
- * Resolves when the session restore started by `initialize()` has settled — the point
794
- * after which the client knows whether this visitor is signed in.
795
- *
796
- * Resolves IMMEDIATELY when no restore is in flight: before `initialize()` is ever
797
- * called, and after it has finished. A restore that failed resolves too (it settled the
798
- * question), so an HTTP client can await this before every request without risking one
799
- * held forever. That is what makes the fetch-before-restore race impossible: a page that
800
879
  // … truncated — the full declaration is in node_modules/@molecule/app-auth/dist/types.d.ts
801
880
  ```
802
881
 
@@ -833,9 +912,11 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
833
912
  loginEndpoint?: string
834
913
 
835
914
  /**
836
- * Logout endpoint.
915
+ * Logout endpoint. Defaults to `/users/logout`. Set to `null` (or `''`) when
916
+ * the API has no logout route: {@link AuthClient.logout} skips the request
917
+ * and still clears the local session.
837
918
  */
838
- logoutEndpoint?: string
919
+ logoutEndpoint?: string | null
839
920
 
840
921
  /**
841
922
  * Register endpoint.
@@ -878,6 +959,21 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
878
959
  */
879
960
  currentUserEndpoint?: string
880
961
 
962
+ /**
963
+ * When to probe {@link currentUserEndpoint} for an HttpOnly cookie session.
964
+ * The default `'hint'` probes only when the readable `mol_auth=1` cookie is
965
+ * present or this client already holds a cookie-session candidate. The API
966
+ * must set that presence hint alongside its HttpOnly cookie for automatic
967
+ * restoration after a full page load.
968
+ *
969
+ * Choose `'always'` for an external cookie API without that hint. Pair it with
970
+ * `storage: 'memory'` and the API's current-user endpoint; the request includes
971
+ * credentials. An anonymous load then makes a probe too. A local sign-out
972
+ * suppresses probes until a successful sign-in establishes another session.
973
+ * Network/5xx/404 failures leave a retryable candidate; 401/403 ends it.
974
+ */
975
+ cookieRestore?: 'hint' | 'always'
976
+
881
977
  /**
882
978
  * Storage key prefix.
883
979
  */
@@ -888,7 +984,7 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
888
984
  * `${storagePrefix}accessToken`).
889
985
  *
890
986
  * Set it when something outside this package reads the token at its own key —
891
- * an e2e suite's contract (RealWorld's specs read `localStorage.jwtToken`), a
987
+ * an e2e suite's contract (for example, `localStorage.getItem('app.jwt')`), a
892
988
  * second library, a host page — instead of mirroring the token into
893
989
  * `localStorage` beside the client. The refresh token and the cached user keep
894
990
  * the prefix.
@@ -915,8 +1011,8 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
915
1011
  * through `createJWTAuthClient<UserProfile, { username: string }>` — so the
916
1012
  * body can be sent as-is under the envelope the API wants.
917
1013
  *
918
- * RealWorld, for example, nests the payload under `user` and registers with
919
- * `{ user: { username, email, password } }`:
1014
+ * A nested-account API, for example, nests the payload under `user` and registers
1015
+ * with `{ user: { username, email, password } }`:
920
1016
  *
921
1017
  * ```typescript
922
1018
  * const client = createJWTAuthClient<UserProfile, { username: string }>({
@@ -939,7 +1035,7 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
939
1035
  /**
940
1036
  * Turn an answer that carries a user into the client's
941
1037
  * `{ accessToken, refreshToken?, user }` (default: the answer as given).
942
- * RealWorld, for example — keep the wire bearer OUT of the profile, because
1038
+ * For a nested user answer, keep the wire bearer OUT of the profile, because
943
1039
  * the client caches `user` in Web Storage where a token copy is readable by
944
1040
  * any script on the origin:
945
1041
  *
@@ -975,7 +1071,7 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
975
1071
  * @param data - The parsed response body.
976
1072
  * @returns The auth result.
977
1073
  */
978
- mapAuthResponse?: (data: unknown) => AuthResult<NoInfer<T>>
1074
+ mapAuthResponse?: (data: unknown) => AuthResult<NoInfer<T>> | AuthChallenge
979
1075
 
980
1076
  /**
981
1077
  * Where the access/refresh token and the cached user are kept — the field that
@@ -986,20 +1082,6 @@ interface AuthClientConfigOptions<T extends object = UserProfile> {
986
1082
  * (SSR, a Node test) the default is `'memory'`. Pass `'memory'` EXPLICITLY when
987
1083
  * the API sets an httpOnly session cookie and you do not want a script-readable
988
1084
  * copy: `'memory'` is a process-local store, and `initialize()` then restores
989
- * through {@link AuthClientConfig.currentUserEndpoint} — the strongest
990
- * configuration, because no script can read the cookie.
991
- *
992
- * **An app whose external contract requires the token at a specific key** — a
993
- * supplied e2e suite (the RealWorld specs read `localStorage.jwtToken` in
994
- * `SELECTORS.md`), a host page, a second library — sets `tokenKey: 'jwtToken'`;
995
- * in a browser that is enough, because the default store is Web Storage. The
996
- * session (token AND user) is then restored synchronously in `initialize()` —
997
- * with no store of your own. `tokenKey` places the access token at that exact
998
- * key; the refresh token and the cached user keep `storagePrefix`.
999
- *
1000
- * A bearer token in Web Storage is readable by any script on the origin, so an
1001
- * XSS can steal it; see {@link createBrowserStorageAdapter}'s `@remarks` for the
1002
- * trade and for the cookie alternative. Never answer a suite's storage key with a
1003
1085
  // … truncated — the full declaration is in node_modules/@molecule/app-auth/dist/types.d.ts
1004
1086
  ````
1005
1087
 
@@ -1160,8 +1242,8 @@ constraint is structural, so the app can name its own fields once and pass
1160
1242
  that type whole:
1161
1243
 
1162
1244
  ```typescript
1163
- interface RealWorldRegister { username: string }
1164
- const client = createJWTAuthClient<UserProfile, RealWorldRegister>({ … })
1245
+ interface RegistrationFields { username: string }
1246
+ const client = createJWTAuthClient<UserProfile, RegistrationFields>({ … })
1165
1247
  ```
1166
1248
 
1167
1249
  A custom field may not change a built-in field's type: `email` and
@@ -1198,15 +1280,21 @@ The single value an app renders the session from — the four states every auth
1198
1280
  UI needs, derived from {@link AuthState} so no caller has to combine
1199
1281
  `initialized`/`authenticated`/`loading`/`error` itself.
1200
1282
 
1283
+ `status === 'loading'` is undecided: wait for it and redirect only on
1284
+ `status === 'unauthenticated'`. `'unavailable'` keeps the session candidate
1285
+ for retry; its profile can still be null. A restore failure other than
1286
+ 401/403 never signs out.
1287
+
1201
1288
  - `'loading'`: no decision yet (before `initialize()` settles). An auth
1202
1289
  operation in flight is {@link AuthState.loading} and KEEPS the decided
1203
1290
  status, so a page guarded on `'loading'` stays mounted while a Login or
1204
1291
  Register request runs.
1205
1292
  - `'authenticated'`: a session exists.
1206
1293
  - `'unauthenticated'`: the client settled the question and nobody is signed in.
1207
- - `'unavailable'`: a stored session exists but the server could not confirm it
1208
- (a network or 5xx failure in {@link AuthClient.validateSession}); the session
1209
- is KEPT and the app can say "reconnecting" instead of signing the user out.
1294
+ - `'unavailable'`: a stored token or cookie-session candidate exists but the
1295
+ server could not confirm it (for example a network, 404, or 5xx failure);
1296
+ the candidate is KEPT and the app can say "reconnecting" instead of signing
1297
+ the user out.
1210
1298
 
1211
1299
  ```typescript
1212
1300
  type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated' | 'unavailable'
@@ -1536,15 +1624,36 @@ function register<
1536
1624
  Peer dependencies:
1537
1625
 
1538
1626
  - `@molecule/app-bond` ^1.0.1
1627
+ - `@molecule/app-http` ^1.5.2
1539
1628
  - `@molecule/app-i18n` ^1.0.1
1540
- - `@molecule/app-logger` ^1.0.1
1629
+ - `@molecule/app-logger` ^1.0.4
1541
1630
 
1542
1631
  ### Runtime Dependencies
1543
1632
 
1544
1633
  - `@molecule/app-bond`
1634
+ - `@molecule/app-http`
1545
1635
  - `@molecule/app-i18n`
1546
1636
  - `@molecule/app-logger`
1547
1637
 
1638
+ **Synchronous getters for application integrations.** Read the shared client
1639
+ synchronously when an integration needs the raw token, auth state and current user.
1640
+ These reads create no second store: `getAccessToken()`
1641
+ returns the token, `getState().status` includes `unavailable`, and `getUser()` reads
1642
+ the mapped profile. The configured `tokenKey` also applies to these getters.
1643
+ Keep an integration's response shape local; do not persist another token or user.
1644
+
1645
+ ```typescript
1646
+ import { getClient } from '@molecule/app-auth'
1647
+ const readSession = () => {
1648
+ const client = getClient()
1649
+ return {
1650
+ status: client.getState().status,
1651
+ user: client.getUser(),
1652
+ accessToken: client.getAccessToken(),
1653
+ }
1654
+ }
1655
+ ```
1656
+
1548
1657
  - **An API with its own auth envelope keeps this client.** `requestBody` wraps the
1549
1658
  login/register payload (`(kind, p) => ({ user: p })`), `mapAuthResponse` reads the
1550
1659
  token and user out of the answer — keeping the wire bearer OUT of the profile,
@@ -1557,7 +1666,7 @@ Peer dependencies:
1557
1666
  `AuthClientConfig` the client is CONSTRUCTED with
1558
1667
  (`setClient(createJWTAuthClient({ authScheme: 'Token', … }))` in the auth bond), not
1559
1668
  properties of a client that already exists. Do not hand-write an auth client for a spec
1560
- like RealWorld. **Registration fields the base payload lacks (`username`, …) are the
1669
+ like this one. **Registration fields the base payload lacks (`username`, …) are the
1561
1670
  factory's second generic** — `createJWTAuthClient<UserProfile, { username: string }>(…)` —
1562
1671
  so `register({ username, email, password })` type-checks and the body goes out as
1563
1672
  `{ user: { username, email, password } }`. Do not pass them as `name`/`metadata` or
@@ -66,15 +66,16 @@ export interface BrowserStorageAdapterOptions {
66
66
  * - **The trade, stated plainly.** A bearer token in Web Storage is readable by
67
67
  * any script on the origin, so one XSS is one token theft — an account takeover
68
68
  * for the token's whole lifetime, and `localStorage` keeps the copy after the
69
- * tab closes. This is the model the RealWorld suite's own specs write
70
- * (`localStorage.setItem('jwtToken', …)` before a reload) and the reason this
71
- * adapter exists.
69
+ * tab closes. Use this adapter when a host integration requires a stored
70
+ * bearer, and configure its key through `tokenKey` instead of a second store.
72
71
  * - **An httpOnly cookie session is STRONGER, and is the first choice wherever
73
72
  * your API supports it.** Script cannot read an httpOnly cookie, so an XSS
74
73
  * cannot exfiltrate the credential; the token stays in memory and
75
74
  * `initialize()` restores the session through `currentUserEndpoint`
76
75
  * (`@molecule/api-resource-user` issues exactly this cookie — pass
77
- * `storage: 'memory'` when it does). `'memory'` is then the strongest
76
+ * `storage: 'memory'` when it does). The default restore requires its readable
77
+ * `mol_auth=1` presence hint. An external API without that convention uses
78
+ * `cookieRestore: 'always'` with its `currentUserEndpoint`. `'memory'` is then the strongest
78
79
  * configuration. If the API sets no such cookie and you cannot change that,
79
80
  * this adapter is the alternative — keep the token's lifetime short and rotate
80
81
  * it on refresh.
@@ -1 +1 @@
1
- {"version":3,"file":"browser-storage.d.ts","sourceRoot":"","sources":["../src/browser-storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAA;AAEpD,4EAA4E;AAC5E,MAAM,WAAW,4BAA4B;IAC3C;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAA;IACzB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,cAAc,CAAA;CACzB;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,eAAO,MAAM,2BAA2B,GACtC,UAAS,4BAAiC,KACzC,cA6EF,CAAA"}
1
+ {"version":3,"file":"browser-storage.d.ts","sourceRoot":"","sources":["../src/browser-storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAA;AAEpD,4EAA4E;AAC5E,MAAM,WAAW,4BAA4B;IAC3C;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAA;IACzB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,cAAc,CAAA;CACzB;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,eAAO,MAAM,2BAA2B,GACtC,UAAS,4BAAiC,KACzC,cA6EF,CAAA"}
@@ -57,15 +57,16 @@ const warn = (message, error) => {
57
57
  * - **The trade, stated plainly.** A bearer token in Web Storage is readable by
58
58
  * any script on the origin, so one XSS is one token theft — an account takeover
59
59
  * for the token's whole lifetime, and `localStorage` keeps the copy after the
60
- * tab closes. This is the model the RealWorld suite's own specs write
61
- * (`localStorage.setItem('jwtToken', …)` before a reload) and the reason this
62
- * adapter exists.
60
+ * tab closes. Use this adapter when a host integration requires a stored
61
+ * bearer, and configure its key through `tokenKey` instead of a second store.
63
62
  * - **An httpOnly cookie session is STRONGER, and is the first choice wherever
64
63
  * your API supports it.** Script cannot read an httpOnly cookie, so an XSS
65
64
  * cannot exfiltrate the credential; the token stays in memory and
66
65
  * `initialize()` restores the session through `currentUserEndpoint`
67
66
  * (`@molecule/api-resource-user` issues exactly this cookie — pass
68
- * `storage: 'memory'` when it does). `'memory'` is then the strongest
67
+ * `storage: 'memory'` when it does). The default restore requires its readable
68
+ * `mol_auth=1` presence hint. An external API without that convention uses
69
+ * `cookieRestore: 'always'` with its `currentUserEndpoint`. `'memory'` is then the strongest
69
70
  * configuration. If the API sets no such cookie and you cannot change that,
70
71
  * this adapter is the alternative — keep the token's lifetime short and rotate
71
72
  * it on refresh.
@@ -1 +1 @@
1
- {"version":3,"file":"browser-storage.js","sourceRoot":"","sources":["../src/browser-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-storage.js","sourceRoot":"","sources":["../src/browser-storage.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -33,7 +33,7 @@ import type { AuthClient, AuthClientConfigOptions, AuthProfileConstraint, Regist
33
33
  * fields (see {@link AuthProfileConstraint}), including a profile with no `id`.
34
34
  * The default, `UserProfile`, requires `id: string`.
35
35
  * @template TRegister - The app's own registration fields, accepted at the top
36
- * level of `register()` (e.g. `{ username: string }` for a RealWorld-shaped API).
36
+ * level of `register()` (e.g. `{ username: string }` for an account API).
37
37
  * An interface and a type alias are equally valid.
38
38
  * @param config - Auth client configuration including endpoints, storage, and refresh settings.
39
39
  * @returns A fully configured `AuthClient` instance.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EACV,UAAU,EACV,uBAAuB,EAIvB,qBAAqB,EAQrB,kBAAkB,EAClB,WAAW,EACZ,MAAM,YAAY,CAAA;AAmJnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,mBAAmB,GAC9B,CAAC,SAAS,qBAAqB,CAAC,CAAC,CAAC,GAAG,WAAW,EAChD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,SAAQ,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAM,KAC/C,UAAU,CAAC,CAAC,EAAE,SAAS,CAw/BzB,CAAA"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,OAAO,KAAK,EACV,UAAU,EACV,uBAAuB,EAIvB,qBAAqB,EAQrB,kBAAkB,EAClB,WAAW,EACZ,MAAM,YAAY,CAAA;AA+RnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,mBAAmB,GAC9B,CAAC,SAAS,qBAAqB,CAAC,CAAC,CAAC,GAAG,WAAW,EAChD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,SAAQ,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAM,KAC/C,UAAU,CAAC,CAAC,EAAE,SAAS,CAmwCzB,CAAA"}