@carecard/jwt-read 3.9.0 → 3.11.0

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.
@@ -7,6 +7,10 @@ description: 'Follow the shared SO_CareCardCa/CareCard workspace coding, testing
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -83,7 +87,7 @@ config.
83
87
  - Never suppress errors, TypeScript errors, linter warnings, authorization
84
88
  failures, RLS failures, build failures, hydration issues, or failing tests.
85
89
  Do not add `eslint-disable`, `@ts-ignore`, broad catches, empty catches, or
86
- similar suppression unless explicitly requested.
90
+ similar suppression. Fix the root cause.
87
91
  - Do not add dependencies unless clearly necessary. If one might be needed, ask
88
92
  first with the reason, tradeoff, and why existing code cannot solve it.
89
93
  - Before finalizing repository work, run the affected repository's relevant
@@ -212,8 +216,8 @@ build artifacts, logs, or `.DS_Store`.
212
216
 
213
217
  Most JavaScript `ms-*` services use CommonJS, Mocha, Supertest, Docker Compose
214
218
  database tests, `@carecard/*` packages, and `sub-apps`
215
- controller/router/model patterns. TypeScript services such as `ms-contact-us`
216
- and `ms-template-ts` use Jest or TypeScript tooling and should keep their
219
+ controller/router/model patterns. TypeScript services such as `ms-messages`
220
+ use Jest or TypeScript tooling and should keep their
217
221
  existing TypeScript style.
218
222
 
219
223
  - Keep environment-specific files explicit: `.env.development`, `.env.test`,
@@ -311,7 +315,7 @@ existing TypeScript style.
311
315
 
312
316
  `app-dashboard` is a Next.js App Router TypeScript app using MUI, React Query,
313
317
  `next-intl`, and shared CareCard utilities. It consumes `ms-auth`,
314
- `ms-institutions`, `ms-contact-us`, and `ms-user-profiles` through service
318
+ `ms-institutions`, `ms-messages`, and `ms-user-profiles` through service
315
319
  modules.
316
320
 
317
321
  - Keep backend URL definitions centralized in `src/services/api.routes.ts`.
@@ -378,7 +382,7 @@ the authenticated dashboard.
378
382
 
379
383
  ## Auth Service RLS Contract
380
384
 
381
- - `ms-auth` follows the shared PostgreSQL/RLS pattern from `ms-template-js`: auth tables live in the `carecard` schema, RLS is enabled and forced on every auth table, and application runtime queries use the unprivileged database role.
385
+ - `ms-auth` follows the shared PostgreSQL/RLS pattern: auth tables live in the `carecard` schema, RLS is enabled and forced on every auth table, and application runtime queries use the unprivileged database role.
382
386
  - Auth table policies allow normal JWT or server-auth users to access only
383
387
  self-owned rows. Do not add redundant `user_id = <jwt sub>` SQL predicates to
384
388
  duplicate self-row checks when RLS owns the authorization decision.
@@ -7,6 +7,10 @@ description: 'Use only when the user explicitly asks for remote Git or GitHub PR
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -75,14 +79,20 @@ Do not continue automatically when:
75
79
  when `origin/development` is absent:
76
80
 
77
81
  ```sh
78
- if git ls-remote --exit-code --heads origin development >/dev/null 2>&1; then
79
- base="development"
80
- elif git ls-remote --exit-code --heads origin main >/dev/null 2>&1; then
81
- base="main"
82
- else
83
- echo "No origin/development or origin/main branch exists."
84
- exit 1
82
+ remote_base_refs="$(git ls-remote --heads origin development main)"
83
+ remote_query_status=$?
84
+ if [ "$remote_query_status" -ne 0 ]; then
85
+ printf 'Unable to inspect origin base branches (exit %s).\n' "$remote_query_status" >&2
86
+ exit "$remote_query_status"
85
87
  fi
88
+ case "$remote_base_refs" in
89
+ *"refs/heads/development") base="development" ;;
90
+ *"refs/heads/main") base="main" ;;
91
+ *)
92
+ printf '%s\n' "No origin/development or origin/main branch exists." >&2
93
+ exit 1
94
+ ;;
95
+ esac
86
96
  git fetch origin "$base" --prune
87
97
  ```
88
98
 
@@ -7,6 +7,10 @@ description: 'Use only when the user explicitly asks for remote Git or GitHub PR
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -72,14 +76,20 @@ completion.
72
76
 
73
77
  ```sh
74
78
  gh auth status
75
- if git ls-remote --exit-code --heads origin development >/dev/null 2>&1; then
76
- base="development"
77
- elif git ls-remote --exit-code --heads origin main >/dev/null 2>&1; then
78
- base="main"
79
- else
80
- echo "No origin/development or origin/main branch exists."
81
- exit 1
79
+ remote_base_refs="$(git ls-remote --heads origin development main)"
80
+ remote_query_status=$?
81
+ if [ "$remote_query_status" -ne 0 ]; then
82
+ printf 'Unable to inspect origin base branches (exit %s).\n' "$remote_query_status" >&2
83
+ exit "$remote_query_status"
82
84
  fi
85
+ case "$remote_base_refs" in
86
+ *"refs/heads/development") base="development" ;;
87
+ *"refs/heads/main") base="main" ;;
88
+ *)
89
+ printf '%s\n' "No origin/development or origin/main branch exists." >&2
90
+ exit 1
91
+ ;;
92
+ esac
83
93
  target_branch="$(git branch --show-current)"
84
94
  test -n "$target_branch"
85
95
  test "$target_branch" != "$base"
@@ -169,7 +179,19 @@ completion.
169
179
  not protected:
170
180
 
171
181
  ```sh
172
- protected="$(gh api "repos/{owner}/{repo}/branches/$target_branch" --jq '.protected' 2>/dev/null || echo false)"
182
+ protected="$(gh api "repos/{owner}/{repo}/branches/$target_branch" --jq '.protected')"
183
+ protection_query_status=$?
184
+ if [ "$protection_query_status" -ne 0 ]; then
185
+ printf 'Unable to inspect branch protection (exit %s).\n' "$protection_query_status" >&2
186
+ exit "$protection_query_status"
187
+ fi
188
+ case "$protected" in
189
+ true|false) ;;
190
+ *)
191
+ printf 'Unexpected branch protection value: %s\n' "$protected" >&2
192
+ exit 1
193
+ ;;
194
+ esac
173
195
  if [ "$protected" = true ]; then
174
196
  gh pr merge "$pr_number" --squash --admin
175
197
  else
@@ -181,8 +203,16 @@ completion.
181
203
  delete it explicitly:
182
204
 
183
205
  ```sh
184
- if [ "$protected" != true ] && git ls-remote --exit-code --heads origin "$target_branch" >/dev/null 2>&1; then
185
- git push origin --delete "$target_branch"
206
+ if [ "$protected" != true ]; then
207
+ remote_target_ref="$(git ls-remote --heads origin "$target_branch")"
208
+ remote_query_status=$?
209
+ if [ "$remote_query_status" -ne 0 ]; then
210
+ printf 'Unable to inspect the remote target branch (exit %s).\n' "$remote_query_status" >&2
211
+ exit "$remote_query_status"
212
+ fi
213
+ if [ -n "$remote_target_ref" ]; then
214
+ git push origin --delete "$target_branch"
215
+ fi
186
216
  fi
187
217
  ```
188
218
 
@@ -7,6 +7,10 @@ description: 'Use when changing pkg-jwt-read JWT parsing, middleware, visitor to
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -118,6 +122,9 @@ depend on those folders being present.
118
122
  - Server-auth request attachment behavior that normalizes introspected claims
119
123
  into `req.jwt.payload` with `authMode: "server-auth"` and
120
124
  `auth_mode: "server-auth"`.
125
+ - Server-auth email confirmation claims are copied only when present. The
126
+ `emailVerified`, `email_verified`, `emailConfirmed`, and `email_confirmed`
127
+ aliases retain their exact names and values, and omission remains omission.
121
128
  - Integration with `@carecard/common-util` for standardized login and
122
129
  authorization errors.
123
130
 
@@ -7,6 +7,10 @@ description: 'Use when any pkg-* repository has non-Markdown package changes, in
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Trigger
@@ -7,6 +7,10 @@ description: 'Use every time before coding, refactoring, debugging, or reviewing
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
package/lib/jwtLib.js CHANGED
@@ -5,6 +5,7 @@ const { throwLoginRequiredError, throwNotAuthorizedError } = require('@carecard/
5
5
 
6
6
  const DEFAULT_USER_AUTHORIZATION_HEADER_NAME = 'X-Authorization-Context';
7
7
  const DEFAULT_USER_AUTHORIZATION_MAX_TOKEN_LENGTH = 2048;
8
+ const EMAIL_CONFIRMATION_CLAIM_NAMES = ['emailVerified', 'email_verified', 'emailConfirmed', 'email_confirmed'];
8
9
 
9
10
  function jwtClientId(req) {
10
11
  const jwtObj = req?.jwt || this;
@@ -33,7 +34,15 @@ function doesJwtUserHasRole(req, userRole) {
33
34
  }
34
35
 
35
36
  function throwError(customErrorFunction) {
36
- typeof customErrorFunction === 'function' ? customErrorFunction() : throwLoginRequiredError();
37
+ if (typeof customErrorFunction !== 'function') {
38
+ return throwLoginRequiredError();
39
+ }
40
+
41
+ const customError = customErrorFunction();
42
+
43
+ if (customError instanceof Error) throw customError;
44
+
45
+ throw new Error('Custom authentication error function returned without throwing');
37
46
  }
38
47
 
39
48
  function isJwtExpired(req, jwtValiditySeconds) {
@@ -122,15 +131,11 @@ function validateAndExtractServiceJwtObject(req, publicKey, expectedIssuer, expe
122
131
  if (jwtString && isJwtSignatureValid) {
123
132
  _extractJwtObject(req, jwtString, customErrorFunction);
124
133
  } else {
125
- /* istanbul ignore else */
126
- if (req) {
127
- req.jwt = null;
128
- }
134
+ req.jwt = null;
129
135
  }
130
136
 
131
137
  if (!req?.jwt || !_isServiceJwtFor(req.jwt.payload, expectedIssuer, expectedAudience)) {
132
- /* istanbul ignore else */
133
- if (req) req.jwt = null;
138
+ req.jwt = null;
134
139
  throwError(customErrorFunction);
135
140
  }
136
141
 
@@ -336,16 +341,14 @@ function validateAndExtractOptionalUserAuthorizationObject(req, options, customE
336
341
 
337
342
  const header = readUserAuthorizationHeader(req, config);
338
343
  if (!header.present) {
339
- /* istanbul ignore else */
340
- if (req) req.userAuthorization = null;
344
+ req.userAuthorization = null;
341
345
  return req;
342
346
  }
343
347
 
344
348
  if (isUserAuthorizationTokenAllowed(header.token, config)) {
345
349
  _extractUserAuthorizationObjectNoThrow(req, header.token);
346
350
  } else {
347
- /* istanbul ignore else */
348
- if (req) req.userAuthorization = null;
351
+ req.userAuthorization = null;
349
352
  throwError(customErrorFunction);
350
353
  }
351
354
 
@@ -361,10 +364,7 @@ function validateAndExtractOptionalUserAuthorizationObjectNoThrow(req, options)
361
364
  if (header.present && isUserAuthorizationTokenAllowed(header.token, config)) {
362
365
  _extractUserAuthorizationObjectNoThrow(req, header.token);
363
366
  } else {
364
- /* istanbul ignore else */
365
- if (req) {
366
- req.userAuthorization = null;
367
- }
367
+ req.userAuthorization = null;
368
368
  }
369
369
 
370
370
  return req;
@@ -389,8 +389,7 @@ function tryValidateAndExtractJwtObject(req, publicKey) {
389
389
 
390
390
  const isJwtSignatureValid = jwtVerifySignedToken(jwtString, publicKey);
391
391
  if (!isJwtSignatureValid) {
392
- /* istanbul ignore else */
393
- if (req) req.jwt = null;
392
+ req.jwt = null;
394
393
  return false;
395
394
  }
396
395
 
@@ -437,11 +436,22 @@ function attachServerAuthClaims(req, claims, customErrorFunction) {
437
436
  _attachJwtMethods(req.jwt);
438
437
  }
439
438
 
439
+ // Pattern: Projection - copies only authoritative confirmation aliases and preserves their exact values.
440
+ function pickEmailConfirmationClaims(claims) {
441
+ return Object.fromEntries(
442
+ EMAIL_CONFIRMATION_CLAIM_NAMES.filter(claimName => Object.prototype.hasOwnProperty.call(claims, claimName)).map(claimName => [
443
+ claimName,
444
+ claims[claimName],
445
+ ]),
446
+ );
447
+ }
448
+
449
+ // Pattern: Mapper - attaches server-auth metadata while preserving authoritative confirmation claims.
440
450
  function createServerAuthPayload(claims) {
441
451
  return {
442
452
  sub: claims.sub || claims.userId || claims.user_id,
443
453
  email: claims.email || '',
444
- email_verified: claims.emailVerified || claims.email_verified || claims.emailConfirmed || claims.email_confirmed || false,
454
+ ...pickEmailConfirmationClaims(claims),
445
455
  roles: Array.isArray(claims.roles) ? claims.roles : [],
446
456
  authMode: 'server-auth',
447
457
  auth_mode: 'server-auth',
@@ -557,7 +567,7 @@ function getRequestHeader(req, headerName) {
557
567
  function isUserAuthorizationTokenAllowed(token, config) {
558
568
  if (!token || !config.publicKey || !jwtVerifySignedToken(token, config.publicKey)) return false;
559
569
 
560
- const payload = readJwtPayloadNoThrow(token);
570
+ const payload = readVerifiedJwtPayload(token);
561
571
  if (!payload) return false;
562
572
  if (isJwtPayloadIssuedInFuture(payload)) return false;
563
573
  if (isJwtPayloadExpired(payload)) return false;
@@ -570,12 +580,8 @@ function isUserAuthorizationTokenAllowed(token, config) {
570
580
  }
571
581
 
572
582
  // Pattern: Pure Function - decodes payload defensively after signature and shape checks.
573
- function readJwtPayloadNoThrow(token) {
574
- try {
575
- return jwtGetHeaderPayload(token)?.payload || null;
576
- } catch {
577
- return null;
578
- }
583
+ function readVerifiedJwtPayload(token) {
584
+ return jwtGetHeaderPayload(token)?.payload || null;
579
585
  }
580
586
 
581
587
  // Pattern: Pure Function - supports either one expected audience or a small allowed set.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carecard/jwt-read",
3
- "version": "3.9.0",
3
+ "version": "3.11.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/CareCard-ca/pkg-jwt-read.git"
@@ -41,9 +41,9 @@
41
41
  "typescript": "6.0.3"
42
42
  },
43
43
  "dependencies": {
44
- "@carecard/auth-util": "3.9.0",
45
- "@carecard/common-util": "3.9.0",
46
- "@carecard/validate": "3.9.0"
44
+ "@carecard/auth-util": "3.11.0",
45
+ "@carecard/common-util": "3.11.0",
46
+ "@carecard/validate": "3.11.0"
47
47
  },
48
48
  "overrides": {
49
49
  "diff": "8.0.4",
package/readme.md CHANGED
@@ -12,6 +12,10 @@ introspected by `ms-auth`.
12
12
 
13
13
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
14
14
 
15
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
16
+
17
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
18
+
15
19
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
16
20
 
17
21
  ## Features
@@ -142,6 +146,10 @@ those claims onto `req.jwt.payload` with `authMode: "server-auth"` and
142
146
  `auth_mode: "server-auth"` so services can keep their existing JWT-backed
143
147
  database context and role checks.
144
148
 
149
+ Server-auth email confirmation claims are copied only when present. The
150
+ `emailVerified`, `email_verified`, `emailConfirmed`, and `email_confirmed`
151
+ aliases retain their exact names and values, and omission remains omission.
152
+
145
153
  ### Scoped User Authorization Context
146
154
 
147
155
  Use `jwtVerifyUserAuthorization` when a route needs to verify only the compact