@genesislcap/foundation-auth 15.14.0 → 15.14.2-FUI-2603.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 (46) hide show
  1. package/dist/dts/machine/actions.d.ts +13 -0
  2. package/dist/dts/machine/actions.d.ts.map +1 -1
  3. package/dist/dts/machine/actions.test.d.ts +2 -0
  4. package/dist/dts/machine/actions.test.d.ts.map +1 -0
  5. package/dist/dts/machine/errors.d.ts +5 -0
  6. package/dist/dts/machine/errors.d.ts.map +1 -1
  7. package/dist/dts/machine/guards.d.ts +2 -1
  8. package/dist/dts/machine/guards.d.ts.map +1 -1
  9. package/dist/dts/machine/guards.test.d.ts +2 -0
  10. package/dist/dts/machine/guards.test.d.ts.map +1 -0
  11. package/dist/dts/machine/machine.d.ts +4 -0
  12. package/dist/dts/machine/machine.d.ts.map +1 -1
  13. package/dist/dts/machine/types.d.ts +2 -0
  14. package/dist/dts/machine/types.d.ts.map +1 -1
  15. package/dist/dts/mapper/utils.d.ts +11 -0
  16. package/dist/dts/mapper/utils.d.ts.map +1 -1
  17. package/dist/dts/mapper/utils.test.d.ts +2 -0
  18. package/dist/dts/mapper/utils.test.d.ts.map +1 -0
  19. package/dist/dts/routes/base.d.ts +1 -0
  20. package/dist/dts/routes/base.d.ts.map +1 -1
  21. package/dist/dts/routes/forgot-password/forgot-password.d.ts.map +1 -1
  22. package/dist/dts/routes/reset-password/reset-identity.d.ts +38 -0
  23. package/dist/dts/routes/reset-password/reset-identity.d.ts.map +1 -0
  24. package/dist/dts/routes/reset-password/reset-identity.test.d.ts +2 -0
  25. package/dist/dts/routes/reset-password/reset-identity.test.d.ts.map +1 -0
  26. package/dist/dts/routes/reset-password/reset-password.d.ts +2 -0
  27. package/dist/dts/routes/reset-password/reset-password.d.ts.map +1 -1
  28. package/dist/dts/routes/reset-password/reset-password.template.d.ts.map +1 -1
  29. package/dist/esm/machine/actions.js +16 -6
  30. package/dist/esm/machine/actions.test.js +21 -0
  31. package/dist/esm/machine/errors.js +39 -8
  32. package/dist/esm/machine/guards.js +13 -5
  33. package/dist/esm/machine/guards.test.js +53 -0
  34. package/dist/esm/machine/machine.js +46 -19
  35. package/dist/esm/mapper/utils.js +16 -0
  36. package/dist/esm/mapper/utils.test.js +56 -0
  37. package/dist/esm/routes/base.js +7 -1
  38. package/dist/esm/routes/forgot-password/forgot-password.js +5 -0
  39. package/dist/esm/routes/reset-password/reset-identity.js +99 -0
  40. package/dist/esm/routes/reset-password/reset-identity.test.js +55 -0
  41. package/dist/esm/routes/reset-password/reset-password.js +22 -0
  42. package/dist/esm/routes/reset-password/reset-password.template.js +6 -2
  43. package/dist/esm/translation.json +1 -0
  44. package/dist/foundation-auth.api.json +175 -2
  45. package/dist/foundation-auth.d.ts +35 -1
  46. package/package.json +19 -19
@@ -0,0 +1,56 @@
1
+ import { APIError } from '@genesislcap/foundation-state-machine';
2
+ import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
3
+ import { StatusCodes } from 'http-status-codes';
4
+ import { nackErrorFromUnknown } from '../machine/errors';
5
+ import { hasDTOErrors, isFailedAuthDTO, isNackDTO } from './utils';
6
+ const Suite = createLogicSuite('password-reset response handling');
7
+ const passwordValidationNack = {
8
+ WARNING: [],
9
+ ERROR: [
10
+ {
11
+ '@type': 'StandardError',
12
+ CODE: 'INTERNAL_ERROR',
13
+ TEXT: 'Password validation failed Password must be 8 or more characters in length.\nPassword must contain 1 or more special characters.',
14
+ STATUS_CODE: '500 Internal Server Error',
15
+ },
16
+ ],
17
+ MESSAGE_TYPE: 'EVENT_NACK',
18
+ SOURCE_REF: '17605761-55cb-4b5a-a1ec-7235d3cae393',
19
+ };
20
+ const eventAck = {
21
+ MESSAGE_TYPE: 'EVENT_ACK',
22
+ SOURCE_REF: 'ack-ref',
23
+ };
24
+ Suite('detects EVENT_NACK as failure', () => {
25
+ assert.ok(isNackDTO(passwordValidationNack));
26
+ assert.ok(isFailedAuthDTO(passwordValidationNack));
27
+ assert.ok(hasDTOErrors(passwordValidationNack));
28
+ });
29
+ Suite('detects ERROR payload as failure even without NACK suffix', () => {
30
+ const ackWithErrors = Object.assign(Object.assign({}, eventAck), { ERROR: passwordValidationNack.ERROR });
31
+ assert.not.ok(isNackDTO(ackWithErrors));
32
+ assert.ok(hasDTOErrors(ackWithErrors));
33
+ assert.ok(isFailedAuthDTO(ackWithErrors));
34
+ });
35
+ Suite('treats EVENT_ACK without ERROR as success', () => {
36
+ assert.not.ok(isNackDTO(eventAck));
37
+ assert.not.ok(hasDTOErrors(eventAck));
38
+ assert.not.ok(isFailedAuthDTO(eventAck));
39
+ });
40
+ Suite('extracts strong-password error text from EVENT_NACK', () => {
41
+ const error = nackErrorFromUnknown(passwordValidationNack);
42
+ assert.ok(error);
43
+ assert.ok(error.message.includes('Password validation failed'));
44
+ assert.is(error.status, StatusCodes.INTERNAL_SERVER_ERROR);
45
+ });
46
+ Suite('extracts NACK from FetchMachineOutput and APIError wrappers', () => {
47
+ const fromFetch = nackErrorFromUnknown({ data: passwordValidationNack, response: { ok: true } });
48
+ assert.ok(fromFetch === null || fromFetch === void 0 ? void 0 : fromFetch.message.includes('Password validation failed'));
49
+ const fromApiError = nackErrorFromUnknown(new APIError(StatusCodes.INTERNAL_SERVER_ERROR, passwordValidationNack));
50
+ assert.ok(fromApiError === null || fromApiError === void 0 ? void 0 : fromApiError.message.includes('Password validation failed'));
51
+ });
52
+ Suite('does not treat EVENT_ACK as an error', () => {
53
+ assert.is(nackErrorFromUnknown(eventAck), null);
54
+ assert.is(nackErrorFromUnknown({ data: eventAck }), null);
55
+ });
56
+ Suite.run();
@@ -53,6 +53,12 @@ export class BaseRoute extends ConfigHostElement {
53
53
  super(...arguments);
54
54
  this.onBack = () => this.routing.navigateTo('/');
55
55
  }
56
+ connectedCallback() {
57
+ var _a, _b, _c, _d, _e;
58
+ super.connectedCallback();
59
+ (_c = (_b = (_a = this.store) === null || _a === void 0 ? void 0 : _a.formEntry) === null || _b === void 0 ? void 0 : _b.errors) === null || _c === void 0 ? void 0 : _c.clear();
60
+ (_e = (_d = this.store) === null || _d === void 0 ? void 0 : _d.authMachine) === null || _e === void 0 ? void 0 : _e.send({ type: 'dismiss' });
61
+ }
56
62
  toLocalisedText(text) {
57
63
  return this.i18next.t(`${defaultAuthConfig.name}:${text}`, { lng: this.i18next.language });
58
64
  }
@@ -372,7 +378,7 @@ let MessageElement = class MessageElement extends FASTElement {
372
378
  const translateHelper = (metaMessage) => this.i18next.t(`${defaultAuthConfig.name}:${metaMessage}`, { lng: this.i18next.language });
373
379
  const meta = this.store.metaMessages.map(translateHelper).join('\n');
374
380
  const error = this.store.errorMessages.map(translateHelper).join('\n');
375
- return !error ? meta : `${meta} ${error}.`;
381
+ return error || meta;
376
382
  }
377
383
  get hasError() {
378
384
  return this.store.errorMessages.length > 0;
@@ -3,6 +3,7 @@ import { customElement } from '@microsoft/fast-element';
3
3
  import { commonStyles } from '../../styles';
4
4
  import { logger } from '../../utils';
5
5
  import { BaseRoute } from '../base';
6
+ import { persistResetIdentity } from '../reset-password/reset-identity';
6
7
  import { ForgotPasswordTemplate as template } from './forgot-password.template';
7
8
  /**
8
9
  * ForgotPassword
@@ -20,6 +21,10 @@ let ForgotPassword = class ForgotPassword extends BaseRoute {
20
21
  /**
21
22
  * Example url from email: https://public-foundation.genesislab.global/reset-password?password=nc_cbGrlgCkZeJHAF043oqEidnk
22
23
  */
24
+ persistResetIdentity({
25
+ username: this.store.formEntry.username,
26
+ organisation: this.store.formEntry.organisation,
27
+ });
23
28
  this.$emit('auth-forgot-password', {
24
29
  username: this.store.formEntry.orgUsername,
25
30
  returnUrl: this.routing.getForgotPasswordReturnUrl(),
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Identity captured during forgot-password so the token reset screen can
3
+ * submit USER_NAME without asking the user to type it again.
4
+ */
5
+ export const RESET_IDENTITY_STORAGE_KEY = 'foundation-auth:password-reset-identity';
6
+ const getStorage = (storage) => {
7
+ if (storage) {
8
+ return storage;
9
+ }
10
+ try {
11
+ return globalThis.localStorage;
12
+ }
13
+ catch (_a) {
14
+ return undefined;
15
+ }
16
+ };
17
+ /**
18
+ * @public
19
+ */
20
+ export function persistResetIdentity(identity, storage) {
21
+ var _a, _b;
22
+ if (!((_a = identity === null || identity === void 0 ? void 0 : identity.username) === null || _a === void 0 ? void 0 : _a.trim())) {
23
+ return;
24
+ }
25
+ const target = getStorage(storage);
26
+ if (!target) {
27
+ return;
28
+ }
29
+ try {
30
+ target.setItem(RESET_IDENTITY_STORAGE_KEY, JSON.stringify({
31
+ username: identity.username.trim(),
32
+ organisation: ((_b = identity.organisation) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
33
+ }));
34
+ }
35
+ catch (_c) {
36
+ // Storage may be unavailable (private mode, SSR).
37
+ }
38
+ }
39
+ /**
40
+ * @public
41
+ */
42
+ export function readResetIdentity(storage) {
43
+ var _a, _b;
44
+ const target = getStorage(storage);
45
+ if (!target) {
46
+ return undefined;
47
+ }
48
+ try {
49
+ const raw = target.getItem(RESET_IDENTITY_STORAGE_KEY);
50
+ if (!raw) {
51
+ return undefined;
52
+ }
53
+ const parsed = JSON.parse(raw);
54
+ if ((_a = parsed === null || parsed === void 0 ? void 0 : parsed.username) === null || _a === void 0 ? void 0 : _a.trim()) {
55
+ return {
56
+ username: parsed.username.trim(),
57
+ organisation: ((_b = parsed.organisation) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
58
+ };
59
+ }
60
+ }
61
+ catch (_c) {
62
+ // Ignore malformed payloads.
63
+ }
64
+ return undefined;
65
+ }
66
+ /**
67
+ * @public
68
+ */
69
+ export function clearResetIdentity(storage) {
70
+ const target = getStorage(storage);
71
+ if (!target) {
72
+ return;
73
+ }
74
+ try {
75
+ target.removeItem(RESET_IDENTITY_STORAGE_KEY);
76
+ }
77
+ catch (_a) {
78
+ // Storage may be unavailable.
79
+ }
80
+ }
81
+ /**
82
+ * @public
83
+ */
84
+ export function resolveResetUsername(queryParams = {}, stored) {
85
+ return (queryParams.username ||
86
+ queryParams.user ||
87
+ queryParams.USER_NAME ||
88
+ (stored === null || stored === void 0 ? void 0 : stored.username) ||
89
+ '').trim();
90
+ }
91
+ /**
92
+ * Username is required by EVENT_PASSWORD_RESET_ACTION. Hide it only when a
93
+ * reset token is present and the username is already known.
94
+ *
95
+ * @public
96
+ */
97
+ export function shouldShowIdentityFields(passwordResetToken, username) {
98
+ return !passwordResetToken || !username.trim();
99
+ }
@@ -0,0 +1,55 @@
1
+ import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
2
+ import { clearResetIdentity, persistResetIdentity, readResetIdentity, resolveResetUsername, RESET_IDENTITY_STORAGE_KEY, shouldShowIdentityFields, } from './reset-identity';
3
+ const Suite = createLogicSuite('reset-identity');
4
+ const createMemoryStorage = () => {
5
+ const map = new Map();
6
+ return {
7
+ get length() {
8
+ return map.size;
9
+ },
10
+ clear: () => map.clear(),
11
+ getItem: (key) => { var _a; return (_a = map.get(key)) !== null && _a !== void 0 ? _a : null; },
12
+ key: (index) => { var _a; return (_a = [...map.keys()][index]) !== null && _a !== void 0 ? _a : null; },
13
+ removeItem: (key) => {
14
+ map.delete(key);
15
+ },
16
+ setItem: (key, value) => {
17
+ map.set(key, value);
18
+ },
19
+ };
20
+ };
21
+ Suite('hides username when token is present and username is known', () => {
22
+ assert.not.ok(shouldShowIdentityFields('reset-token', 'JaneDee'));
23
+ });
24
+ Suite('shows username when token is present but username is missing', () => {
25
+ assert.ok(shouldShowIdentityFields('reset-token', ''));
26
+ assert.ok(shouldShowIdentityFields('reset-token', ' '));
27
+ });
28
+ Suite('shows username when token is absent', () => {
29
+ assert.ok(shouldShowIdentityFields('', 'JaneDee'));
30
+ assert.ok(shouldShowIdentityFields(undefined, ''));
31
+ });
32
+ Suite('resolves username from query params before stored identity', () => {
33
+ const stored = { username: 'stored-user' };
34
+ assert.is(resolveResetUsername({ username: 'query-user' }, stored), 'query-user');
35
+ assert.is(resolveResetUsername({ user: 'alias-user' }, stored), 'alias-user');
36
+ assert.is(resolveResetUsername({ USER_NAME: 'legacy-user' }, stored), 'legacy-user');
37
+ });
38
+ Suite('resolves username from stored identity when query has no username', () => {
39
+ assert.is(resolveResetUsername({ password: 'token' }, { username: 'stored-user' }), 'stored-user');
40
+ assert.is(resolveResetUsername({ password: 'token' }), '');
41
+ });
42
+ Suite('persists, reads and clears reset identity', () => {
43
+ const storage = createMemoryStorage();
44
+ persistResetIdentity({ username: ' JaneDee ', organisation: ' FBN ' }, storage);
45
+ assert.equal(readResetIdentity(storage), { username: 'JaneDee', organisation: 'FBN' });
46
+ assert.ok(storage.getItem(RESET_IDENTITY_STORAGE_KEY));
47
+ clearResetIdentity(storage);
48
+ assert.is(readResetIdentity(storage), undefined);
49
+ });
50
+ Suite('does not persist empty username', () => {
51
+ const storage = createMemoryStorage();
52
+ persistResetIdentity({ username: ' ' }, storage);
53
+ assert.is(readResetIdentity(storage), undefined);
54
+ });
55
+ Suite.run();
@@ -2,6 +2,7 @@ import { __awaiter, __decorate } from "tslib";
2
2
  import { customElement, observable, volatile } from '@microsoft/fast-element';
3
3
  import { commonStyles } from '../../styles';
4
4
  import { BaseRoute } from '../base';
5
+ import { readResetIdentity, resolveResetUsername, shouldShowIdentityFields, } from './reset-identity';
5
6
  import { ResetPasswordTemplate as template } from './reset-password.template';
6
7
  /**
7
8
  * ResetPassword
@@ -26,6 +27,21 @@ let ResetPassword = class ResetPassword extends BaseRoute {
26
27
  enter(phase) {
27
28
  this.hasPasswordExpired = !!phase.route.queryParams.expired;
28
29
  this.passwordResetToken = phase.route.queryParams.password;
30
+ this.applyResetIdentity(phase.route.queryParams);
31
+ }
32
+ applyResetIdentity(queryParams) {
33
+ if (!this.passwordResetToken) {
34
+ return;
35
+ }
36
+ const stored = readResetIdentity();
37
+ const username = resolveResetUsername(queryParams, stored);
38
+ if (username) {
39
+ this.store.formEntry.onUsernameChanged(new CustomEvent('auth-username-changed', { detail: username }));
40
+ }
41
+ const organisation = queryParams.organisation || (stored === null || stored === void 0 ? void 0 : stored.organisation);
42
+ if (organisation) {
43
+ this.store.formEntry.onOrganisationChanged(new CustomEvent('auth-organisation-changed', { detail: organisation }));
44
+ }
29
45
  }
30
46
  onSubmit() {
31
47
  return __awaiter(this, void 0, void 0, function* () {
@@ -53,6 +69,9 @@ let ResetPassword = class ResetPassword extends BaseRoute {
53
69
  get headingText() {
54
70
  return this.hasPasswordExpired ? 'You are required to change your password' : 'Change Password';
55
71
  }
72
+ get showIdentityFields() {
73
+ return shouldShowIdentityFields(this.passwordResetToken, this.store.formEntry.username);
74
+ }
56
75
  };
57
76
  __decorate([
58
77
  observable
@@ -63,6 +82,9 @@ __decorate([
63
82
  __decorate([
64
83
  volatile
65
84
  ], ResetPassword.prototype, "headingText", null);
85
+ __decorate([
86
+ volatile
87
+ ], ResetPassword.prototype, "showIdentityFields", null);
66
88
  ResetPassword = __decorate([
67
89
  customElement({
68
90
  name: 'foundation-auth-reset-password',
@@ -12,10 +12,14 @@ export const ResetPasswordTemplate = html `
12
12
  <auth-logo></auth-logo>
13
13
  ${showEnvironmentIndicator()}
14
14
  <div class="heading2" data-test-id="heading">${(x) => x.headingText}</div>
15
- <div class="heading3">${(x) => x.toLocalisedText('RESET_PASSWORD_SUBTITLE')}</div>
15
+ <div class="heading3">
16
+ ${(x) => x.toLocalisedText(x.showIdentityFields ? 'RESET_PASSWORD_SUBTITLE' : 'RESET_PASSWORD_TOKEN_SUBTITLE')}
17
+ </div>
16
18
  </div>
17
19
  <form @submit=${(x) => x.onSubmit()} autocomplete="on" data-test-id="form">
18
- ${organisationField()} ${usernameField()}
20
+ ${when((x) => x.showIdentityFields, html `
21
+ ${organisationField()} ${usernameField()}
22
+ `)}
19
23
  ${when((x) => !x.passwordResetToken, html `
20
24
  ${(x) => passwordField(x.toLocalisedText(x.hasPasswordExpired
21
25
  ? 'RESET_PASSWORD_CURRENT_PASSWORD_FIELD'
@@ -26,6 +26,7 @@
26
26
  "REQUEST_ACCOUNT_SUBMIT_BUTTON": "Request Account",
27
27
  "REQUEST_ACCOUNT_BUTTON_BACK": "Back",
28
28
  "RESET_PASSWORD_SUBTITLE": "Enter the username registered to your account",
29
+ "RESET_PASSWORD_TOKEN_SUBTITLE": "Enter a new password for your account",
29
30
  "RESET_PASSWORD_OLD_PASSWORD_FIELD": "Old Password",
30
31
  "RESET_PASSWORD_CURRENT_PASSWORD_FIELD": "Current Password",
31
32
  "RESET_PASSWORD_SUBMIT_BUTTON": "Change Password",
@@ -2179,7 +2179,7 @@
2179
2179
  },
2180
2180
  {
2181
2181
  "kind": "Content",
2182
- "text": ";\n} | {\n type: 'logout';\n} | {\n type: 'cancel-mfa';\n} | {\n type: 'change-password';\n params: "
2182
+ "text": ";\n} | {\n type: 'logout';\n} | {\n type: 'cancel-mfa';\n} | {\n type: 'dismiss';\n} | {\n type: 'change-password';\n params: "
2183
2183
  },
2184
2184
  {
2185
2185
  "kind": "Reference",
@@ -3283,6 +3283,89 @@
3283
3283
  "endIndex": 2
3284
3284
  }
3285
3285
  },
3286
+ {
3287
+ "kind": "Function",
3288
+ "canonicalReference": "@genesislcap/foundation-auth!clearAuthErrorState:function(1)",
3289
+ "docComment": "/**\n * Drop accumulated machine errors. `ErrorMap` is shared with `startingContext`, so reset must clear it in place rather than replacing the context object.\n *\n * @public\n */\n",
3290
+ "excerptTokens": [
3291
+ {
3292
+ "kind": "Content",
3293
+ "text": "export declare function clearAuthErrorState<T extends "
3294
+ },
3295
+ {
3296
+ "kind": "Reference",
3297
+ "text": "ErrorState",
3298
+ "canonicalReference": "@genesislcap/foundation-auth!~ErrorState:type"
3299
+ },
3300
+ {
3301
+ "kind": "Content",
3302
+ "text": ">(context: "
3303
+ },
3304
+ {
3305
+ "kind": "Content",
3306
+ "text": "T"
3307
+ },
3308
+ {
3309
+ "kind": "Content",
3310
+ "text": ", starting?: "
3311
+ },
3312
+ {
3313
+ "kind": "Content",
3314
+ "text": "T"
3315
+ },
3316
+ {
3317
+ "kind": "Content",
3318
+ "text": "): "
3319
+ },
3320
+ {
3321
+ "kind": "Content",
3322
+ "text": "T"
3323
+ },
3324
+ {
3325
+ "kind": "Content",
3326
+ "text": ";"
3327
+ }
3328
+ ],
3329
+ "fileUrlPath": "src/machine/actions.ts",
3330
+ "returnTypeTokenRange": {
3331
+ "startIndex": 7,
3332
+ "endIndex": 8
3333
+ },
3334
+ "releaseTag": "Public",
3335
+ "overloadIndex": 1,
3336
+ "parameters": [
3337
+ {
3338
+ "parameterName": "context",
3339
+ "parameterTypeTokenRange": {
3340
+ "startIndex": 3,
3341
+ "endIndex": 4
3342
+ },
3343
+ "isOptional": false
3344
+ },
3345
+ {
3346
+ "parameterName": "starting",
3347
+ "parameterTypeTokenRange": {
3348
+ "startIndex": 5,
3349
+ "endIndex": 6
3350
+ },
3351
+ "isOptional": true
3352
+ }
3353
+ ],
3354
+ "typeParameters": [
3355
+ {
3356
+ "typeParameterName": "T",
3357
+ "constraintTokenRange": {
3358
+ "startIndex": 1,
3359
+ "endIndex": 2
3360
+ },
3361
+ "defaultTypeTokenRange": {
3362
+ "startIndex": 0,
3363
+ "endIndex": 0
3364
+ }
3365
+ }
3366
+ ],
3367
+ "name": "clearAuthErrorState"
3368
+ },
3286
3369
  {
3287
3370
  "kind": "Function",
3288
3371
  "canonicalReference": "@genesislcap/foundation-auth!configure:function(1)",
@@ -6068,7 +6151,7 @@
6068
6151
  },
6069
6152
  {
6070
6153
  "kind": "Content",
6071
- "text": "() => {\n login: {\n actions: string[];\n target: string;\n };\n \"terms-and-conditions\": {\n actions: string[];\n target: string;\n };\n \"forgot-password\": {\n actions: string[];\n target: string;\n };\n \"change-password\": {\n actions: string[];\n target: string;\n };\n \"reset-password\": {\n actions: string[];\n target: string;\n };\n }"
6154
+ "text": "() => {\n login: {\n actions: string[];\n target: string;\n };\n \"terms-and-conditions\": {\n actions: string[];\n target: string;\n };\n \"forgot-password\": {\n actions: string[];\n target: string;\n };\n \"change-password\": {\n actions: string[];\n target: string;\n };\n \"reset-password\": {\n actions: string[];\n target: string;\n };\n dismiss: {\n actions: string[];\n target: string;\n };\n }"
6072
6155
  },
6073
6156
  {
6074
6157
  "kind": "Content",
@@ -10006,6 +10089,51 @@
10006
10089
  ],
10007
10090
  "name": "getRoutePath"
10008
10091
  },
10092
+ {
10093
+ "kind": "Function",
10094
+ "canonicalReference": "@genesislcap/foundation-auth!hasDTOErrors:function(1)",
10095
+ "docComment": "/**\n * True when a Genesis payload contains at least one ERROR item.\n *\n * @public\n */\n",
10096
+ "excerptTokens": [
10097
+ {
10098
+ "kind": "Content",
10099
+ "text": "export declare function hasDTOErrors(dto: "
10100
+ },
10101
+ {
10102
+ "kind": "Content",
10103
+ "text": "unknown"
10104
+ },
10105
+ {
10106
+ "kind": "Content",
10107
+ "text": "): "
10108
+ },
10109
+ {
10110
+ "kind": "Content",
10111
+ "text": "boolean"
10112
+ },
10113
+ {
10114
+ "kind": "Content",
10115
+ "text": ";"
10116
+ }
10117
+ ],
10118
+ "fileUrlPath": "src/mapper/utils.ts",
10119
+ "returnTypeTokenRange": {
10120
+ "startIndex": 3,
10121
+ "endIndex": 4
10122
+ },
10123
+ "releaseTag": "Public",
10124
+ "overloadIndex": 1,
10125
+ "parameters": [
10126
+ {
10127
+ "parameterName": "dto",
10128
+ "parameterTypeTokenRange": {
10129
+ "startIndex": 1,
10130
+ "endIndex": 2
10131
+ },
10132
+ "isOptional": false
10133
+ }
10134
+ ],
10135
+ "name": "hasDTOErrors"
10136
+ },
10009
10137
  {
10010
10138
  "kind": "Function",
10011
10139
  "canonicalReference": "@genesislcap/foundation-auth!hasDTOErrorWarningCode:function(1)",
@@ -10408,6 +10536,51 @@
10408
10536
  ],
10409
10537
  "name": "isChangePasswordParams"
10410
10538
  },
10539
+ {
10540
+ "kind": "Function",
10541
+ "canonicalReference": "@genesislcap/foundation-auth!isFailedAuthDTO:function(1)",
10542
+ "docComment": "/**\n * True when a Genesis payload must be treated as failure. HTTP status is intentionally ignored; MESSAGE_TYPE and ERROR are the contract.\n *\n * @public\n */\n",
10543
+ "excerptTokens": [
10544
+ {
10545
+ "kind": "Content",
10546
+ "text": "export declare function isFailedAuthDTO(dto: "
10547
+ },
10548
+ {
10549
+ "kind": "Content",
10550
+ "text": "unknown"
10551
+ },
10552
+ {
10553
+ "kind": "Content",
10554
+ "text": "): "
10555
+ },
10556
+ {
10557
+ "kind": "Content",
10558
+ "text": "boolean"
10559
+ },
10560
+ {
10561
+ "kind": "Content",
10562
+ "text": ";"
10563
+ }
10564
+ ],
10565
+ "fileUrlPath": "src/mapper/utils.ts",
10566
+ "returnTypeTokenRange": {
10567
+ "startIndex": 3,
10568
+ "endIndex": 4
10569
+ },
10570
+ "releaseTag": "Public",
10571
+ "overloadIndex": 1,
10572
+ "parameters": [
10573
+ {
10574
+ "parameterName": "dto",
10575
+ "parameterTypeTokenRange": {
10576
+ "startIndex": 1,
10577
+ "endIndex": 2
10578
+ },
10579
+ "isOptional": false
10580
+ }
10581
+ ],
10582
+ "name": "isFailedAuthDTO"
10583
+ },
10411
10584
  {
10412
10585
  "kind": "Function",
10413
10586
  "canonicalReference": "@genesislcap/foundation-auth!isForgotPasswordParams:function(1)",
@@ -438,6 +438,8 @@ export declare type AuthMachineEvent = {
438
438
  type: 'logout';
439
439
  } | {
440
440
  type: 'cancel-mfa';
441
+ } | {
442
+ type: 'dismiss';
441
443
  } | {
442
444
  type: 'change-password';
443
445
  params: ChangePasswordParams;
@@ -639,6 +641,13 @@ export declare type ChangePasswordParams = {
639
641
  requester?: string;
640
642
  };
641
643
 
644
+ /**
645
+ * Drop accumulated machine errors. `ErrorMap` is shared with `startingContext`, so
646
+ * reset must clear it in place rather than replacing the context object.
647
+ * @public
648
+ */
649
+ export declare function clearAuthErrorState<T extends ErrorState>(context: T, starting?: T): T;
650
+
642
651
  /**
643
652
  * configure.
644
653
  *
@@ -1031,6 +1040,10 @@ export declare class DefaultAuthMachine extends AbstractMachine<AuthMachineConte
1031
1040
  actions: string[];
1032
1041
  target: string;
1033
1042
  };
1043
+ dismiss: {
1044
+ actions: string[];
1045
+ target: string;
1046
+ };
1034
1047
  };
1035
1048
  protected dtoTransition: () => {
1036
1049
  actions: string[];
@@ -1237,6 +1250,13 @@ declare interface Details_2 {
1237
1250
  readonly PRODUCT: Product_2[];
1238
1251
  }
1239
1252
 
1253
+ declare type ErrorState = {
1254
+ error?: unknown;
1255
+ errors?: {
1256
+ clear(): void;
1257
+ };
1258
+ };
1259
+
1240
1260
  /**
1241
1261
  * @public
1242
1262
  */
@@ -1951,6 +1971,12 @@ export declare function getRoutePath(route: AuthRoutes | string, hostPath?: stri
1951
1971
 
1952
1972
  export { getUser }
1953
1973
 
1974
+ /**
1975
+ * True when a Genesis payload contains at least one ERROR item.
1976
+ * @public
1977
+ */
1978
+ export declare function hasDTOErrors(dto: unknown): boolean;
1979
+
1954
1980
  /**
1955
1981
  * hasDTOErrorWarningCode
1956
1982
  * @remarks
@@ -2012,7 +2038,8 @@ declare type InternalEventMap = {
2012
2038
  /**
2013
2039
  * is200Nack.
2014
2040
  * @privateRemarks
2015
- * Required until http status codes are aligned on backend.
2041
+ * Required until http status codes are aligned on backend. HTTP status is ignored;
2042
+ * Genesis MESSAGE_TYPE / ERROR determine failure.
2016
2043
  * @public
2017
2044
  */
2018
2045
  export declare const is200Nack: <TOutput = any>(event: EventObject | DoneInvokeEvent<TOutput>) => event is DoneInvokeEvent<TOutput>;
@@ -2026,6 +2053,13 @@ export declare const is200Nack: <TOutput = any>(event: EventObject | DoneInvokeE
2026
2053
  */
2027
2054
  export declare function isChangePasswordParams(params: AuthMachineEventParams): params is ChangePasswordParams;
2028
2055
 
2056
+ /**
2057
+ * True when a Genesis payload must be treated as failure.
2058
+ * HTTP status is intentionally ignored; MESSAGE_TYPE and ERROR are the contract.
2059
+ * @public
2060
+ */
2061
+ export declare function isFailedAuthDTO(dto: unknown): boolean;
2062
+
2029
2063
  /**
2030
2064
  * isForgotPasswordParams.
2031
2065
  * @remarks