@aooth/auth-moost 0.1.23 → 0.1.25

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/dist/index.d.mts CHANGED
@@ -1785,6 +1785,14 @@ interface AuthWfCtx {
1785
1785
  aborted?: boolean;
1786
1786
  isFirstLogin?: boolean;
1787
1787
  newPasswordRequired?: boolean;
1788
+ /**
1789
+ * Idempotency latch for the single `record-login` funnel step. Set true once
1790
+ * a login has been stamped this run — by the `credentials` step (the password
1791
+ * path stamps eagerly via `users.login()`) or by `record-login` itself — so
1792
+ * the funnel never double-writes `account.lastLogin`. Server-only flow
1793
+ * control; never `@wf.context.pass`-ed to the client.
1794
+ */
1795
+ loginRecorded?: boolean;
1788
1796
  autoLogin?: boolean;
1789
1797
  consents?: AuthWfConsentsState;
1790
1798
  pincode?: AuthWfPincodeUiState;
@@ -2124,6 +2132,47 @@ declare class AuthWorkflow {
2124
2132
  * mirrors `notifyNewDevice`'s posture). Never called by the base class.
2125
2133
  */
2126
2134
  protected sendSecurityAlert(ctx: AuthWfCtx, reason: string, context?: Record<string, unknown>): Promise<void>;
2135
+ /**
2136
+ * A user just authenticated and a session is being established — interactive
2137
+ * login, federated (SSO) login, OR invite/signup/recovery auto-login. Fired
2138
+ * from the single `record-login` funnel, AFTER `account.lastLogin` is stamped
2139
+ * and BEFORE the session/code is delivered, so a throw aborts the login
2140
+ * atomically (no half-issued session). `ctx.subject` is set; read
2141
+ * `ctx.isFirstLogin` to distinguish the very first sign-in, `ctx.oauth` for
2142
+ * federated context. Does NOT fire for the no-session "fresh-login" finalize
2143
+ * (where the user is redirected to sign in separately).
2144
+ */
2145
+ protected afterLogin(_ctx: AuthWfCtx): void | Promise<void>;
2146
+ /**
2147
+ * An invitee finished accepting their invite — account activated — whether or
2148
+ * not the flow auto-logged-them-in. Fires once, before the finalize terminal.
2149
+ * (An auto-login invite ALSO fires {@link afterLogin}.)
2150
+ */
2151
+ protected afterInvitationAccepted(_ctx: AuthWfCtx): void | Promise<void>;
2152
+ /**
2153
+ * A self-signup account was created + activated (post password-set, post
2154
+ * activate). Fires once, before the auto-login finalize. (Signup always
2155
+ * auto-logins, so {@link afterLogin} fires too.)
2156
+ */
2157
+ protected afterSignup(_ctx: AuthWfCtx): void | Promise<void>;
2158
+ /**
2159
+ * A recovery password reset completed. Fires once even when an `admin-only`
2160
+ * lock survived the reset (the password DID change) — so it runs ahead of the
2161
+ * still-locked guard. An auto-login recovery ALSO fires {@link afterLogin}.
2162
+ */
2163
+ protected afterPasswordReset(_ctx: AuthWfCtx): void | Promise<void>;
2164
+ /**
2165
+ * An already-authenticated user changed their own password (change-password
2166
+ * flow). NOT a login — the session is rotated, not established — so
2167
+ * {@link afterLogin} does NOT fire.
2168
+ */
2169
+ protected afterPasswordChanged(_ctx: AuthWfCtx): void | Promise<void>;
2170
+ /**
2171
+ * A user added, changed, or removed an MFA factor (add-mfa flow). NOT fired
2172
+ * on a cancel / nothing-to-do finish. The user KEEPS their session (no
2173
+ * re-issue), so {@link afterLogin} does NOT fire.
2174
+ */
2175
+ protected afterMfaChanged(_ctx: AuthWfCtx): void | Promise<void>;
2127
2176
  /**
2128
2177
  * Return the list of selectable role identifiers for the admin invite form.
2129
2178
  * Mirrors the prior `InviteWorkflow.getAvailableRoles()` consumer hook —
@@ -2994,7 +3043,7 @@ declare class AuthWorkflow {
2994
3043
  * (un-removable operation aborted by `confirm-remove-mfa`) →
2995
3044
  * nothing-available (zero candidates, never had to step-up) → cancelled.
2996
3045
  */
2997
- finishAddMfa(ctx: AuthWfCtx): undefined;
3046
+ finishAddMfa(ctx: AuthWfCtx): undefined | Promise<undefined>;
2998
3047
  /**
2999
3048
  * `finish-add-mfa`'s envelope construction, extracted pure so the outcome
3000
3049
  * priority (removed → changed → added → blocked → nothing-available →
@@ -3349,6 +3398,52 @@ declare class AuthWorkflow {
3349
3398
  * also zeroes `failedLoginAttempts`, so the next login starts clean.
3350
3399
  */
3351
3400
  unlockAccount(ctx: AuthWfCtx): Promise<undefined>;
3401
+ /**
3402
+ * The SINGLE login-completion funnel. Every flow that establishes an
3403
+ * authenticated session routes through here — placed in each login schema
3404
+ * right after the guards and BEFORE the delivery terminal (`issue` /
3405
+ * `mint-authz-code` / `finalize-auto-login`) — so a login can never be
3406
+ * delivered without passing this point. Two uniform jobs:
3407
+ * 1. Stamp `account.lastLogin` exactly once (the sole workflow writer of it).
3408
+ * 2. Fire the `afterLogin` customer hook.
3409
+ *
3410
+ * Idempotent per run via `ctx.loginRecorded`: the password `credentials` path
3411
+ * already stamped eagerly through `users.login()` and latched the flag, so the
3412
+ * stamp NO-OPS there (no double write) — but `afterLogin` still fires, so the
3413
+ * hook runs exactly once for password logins too. Federated (`sso-callback`)
3414
+ * and auto-login (invite/signup/recovery) paths never call `login()`, so this
3415
+ * is their sole stamp. Self-gates on `ctx.subject`. Runs AFTER
3416
+ * `prepare-semantic-flags` derived `isFirstLogin`, so a genuine first
3417
+ * federated login still observes `isFirstLogin === true`.
3418
+ *
3419
+ * A throw (from the stamp or the hook) aborts the flow BEFORE delivery, so the
3420
+ * login fails atomically — no half-issued session.
3421
+ */
3422
+ recordLogin(ctx: AuthWfCtx): undefined | Promise<undefined>;
3423
+ /**
3424
+ * Recovery-only guard, extracted from the finalize terminals so they stay pure
3425
+ * delivery. An `admin-only` lockout never self-unlocks, so a reset that left
3426
+ * the account frozen must NOT be confirmed-as-success OR auto-logged-in
3427
+ * (minting tokens would defeat the very freeze). When still locked it emits the
3428
+ * warn terminal and sets `ctx.aborted`, so the schema's following `{ break }`
3429
+ * skips BOTH the `record-login` funnel and the finalize terminals — a frozen
3430
+ * account is never stamped or logged in. The schema gates this on
3431
+ * `ctx.lockout?.mode === "admin-only"` (the only mode that can reach finalize
3432
+ * still locked: self-service ran `unlock-account`; temporary auto-expires).
3433
+ */
3434
+ recoveryLockCheck(ctx: AuthWfCtx): Promise<undefined>;
3435
+ /**
3436
+ * Thin dispatcher steps for the flow-specific lifecycle hooks. Each is its own
3437
+ * schema step (rather than an in-terminal call) because its flow's finalize
3438
+ * terminals are SHARED across flows (`finalize-auto-login` serves invite +
3439
+ * recovery + signup; `finalize-fresh-login` serves invite + recovery), so a
3440
+ * dedicated step in the flow-specific schema fires the right hook without
3441
+ * ctx-discrimination inside a shared terminal. Named `fire*` so the overridable
3442
+ * `after*` hooks keep the clean public name.
3443
+ */
3444
+ fireInvitationAccepted(ctx: AuthWfCtx): void | Promise<void>;
3445
+ fireSignup(ctx: AuthWfCtx): void | Promise<void>;
3446
+ firePasswordReset(ctx: AuthWfCtx): void | Promise<void>;
3352
3447
  /**
3353
3448
  * Issue access + refresh tokens via `auth.issue`. Stashes the login
3354
3449
  * response envelope on `useWfFinished` so downstream `redirect` can
@@ -3422,7 +3517,7 @@ declare class AuthWorkflow {
3422
3517
  * confirmation first. Discriminated by ctx-slot presence
3423
3518
  * (`ctx.postReset` → recovery; otherwise invite).
3424
3519
  */
3425
- finalizeFreshLogin(ctx: AuthWfCtx): undefined | Promise<undefined>;
3520
+ finalizeFreshLogin(ctx: AuthWfCtx): undefined;
3426
3521
  /**
3427
3522
  * Post-reset store read: did an `admin-only` lockout survive the password
3428
3523
  * reset (account still frozen)? Callers MUST first confirm
@@ -3443,10 +3538,17 @@ declare class AuthWorkflow {
3443
3538
  */
3444
3539
  private finishRecoveryReset;
3445
3540
  /**
3446
- * Auto-login finalize — invite + recovery. Issues access + refresh tokens
3447
- * and stashes the login response envelope on `useWfFinished`. Invite
3448
- * preserves any `message` set by an earlier terminal (`confirmation`) so
3449
- * the SPA paints the confirmation text alongside the tokens (WF-INVITE-020).
3541
+ * Auto-login finalize — invite + recovery + signup. PURE delivery: issues
3542
+ * access + refresh tokens and stashes the login response envelope on
3543
+ * `useWfFinished`. Invite preserves any `message` set by an earlier terminal
3544
+ * (`confirmation`) so the SPA paints the confirmation text alongside the
3545
+ * tokens (WF-INVITE-020).
3546
+ *
3547
+ * It records NOTHING and guards NOTHING: `account.lastLogin` + the
3548
+ * `afterLogin` hook are owned by the upstream `record-login` funnel step, and
3549
+ * the admin-only-survived-lock guard by the upstream `recovery-lock-check`
3550
+ * step — both of which `{ break }`/gate this step out when they apply, so a
3551
+ * still-frozen account never reaches here.
3450
3552
  */
3451
3553
  finalizeAutoLogin(ctx: AuthWfCtx): Promise<undefined>;
3452
3554
  /**
package/dist/index.mjs CHANGED
@@ -1240,6 +1240,47 @@ let AuthWorkflow = class AuthWorkflow {
1240
1240
  });
1241
1241
  }
1242
1242
  /**
1243
+ * A user just authenticated and a session is being established — interactive
1244
+ * login, federated (SSO) login, OR invite/signup/recovery auto-login. Fired
1245
+ * from the single `record-login` funnel, AFTER `account.lastLogin` is stamped
1246
+ * and BEFORE the session/code is delivered, so a throw aborts the login
1247
+ * atomically (no half-issued session). `ctx.subject` is set; read
1248
+ * `ctx.isFirstLogin` to distinguish the very first sign-in, `ctx.oauth` for
1249
+ * federated context. Does NOT fire for the no-session "fresh-login" finalize
1250
+ * (where the user is redirected to sign in separately).
1251
+ */
1252
+ afterLogin(_ctx) {}
1253
+ /**
1254
+ * An invitee finished accepting their invite — account activated — whether or
1255
+ * not the flow auto-logged-them-in. Fires once, before the finalize terminal.
1256
+ * (An auto-login invite ALSO fires {@link afterLogin}.)
1257
+ */
1258
+ afterInvitationAccepted(_ctx) {}
1259
+ /**
1260
+ * A self-signup account was created + activated (post password-set, post
1261
+ * activate). Fires once, before the auto-login finalize. (Signup always
1262
+ * auto-logins, so {@link afterLogin} fires too.)
1263
+ */
1264
+ afterSignup(_ctx) {}
1265
+ /**
1266
+ * A recovery password reset completed. Fires once even when an `admin-only`
1267
+ * lock survived the reset (the password DID change) — so it runs ahead of the
1268
+ * still-locked guard. An auto-login recovery ALSO fires {@link afterLogin}.
1269
+ */
1270
+ afterPasswordReset(_ctx) {}
1271
+ /**
1272
+ * An already-authenticated user changed their own password (change-password
1273
+ * flow). NOT a login — the session is rotated, not established — so
1274
+ * {@link afterLogin} does NOT fire.
1275
+ */
1276
+ afterPasswordChanged(_ctx) {}
1277
+ /**
1278
+ * A user added, changed, or removed an MFA factor (add-mfa flow). NOT fired
1279
+ * on a cancel / nothing-to-do finish. The user KEEPS their session (no
1280
+ * re-issue), so {@link afterLogin} does NOT fire.
1281
+ */
1282
+ afterMfaChanged(_ctx) {}
1283
+ /**
1243
1284
  * Return the list of selectable role identifiers for the admin invite form.
1244
1285
  * Mirrors the prior `InviteWorkflow.getAvailableRoles()` consumer hook —
1245
1286
  * `undefined` (default) means no whitelist is enforced. Read by
@@ -2364,6 +2405,7 @@ let AuthWorkflow = class AuthWorkflow {
2364
2405
  try {
2365
2406
  const result = await this.users.login(input.username, input.password, this.lockoutOverride(ctx));
2366
2407
  ctx.subject = result.user.id;
2408
+ ctx.loginRecorded = true;
2367
2409
  swapStrategy("store");
2368
2410
  if (ctx.guards?.passwordInitial && result.user.password.isInitial) ctx.isPasswordInitial = true;
2369
2411
  if (ctx.guards?.passwordExpiry && this.users.isPasswordExpired(result.user)) ctx.isPasswordExpired = true;
@@ -3003,6 +3045,7 @@ let AuthWorkflow = class AuthWorkflow {
3003
3045
  value: envelope,
3004
3046
  cookies: auth.buildFinishedCookies(issue)
3005
3047
  });
3048
+ await this.afterPasswordChanged(ctx);
3006
3049
  }
3007
3050
  /**
3008
3051
  * Terminal for the manage-MFA flow. The user KEEPS their current session (no
@@ -3016,6 +3059,9 @@ let AuthWorkflow = class AuthWorkflow {
3016
3059
  type: "data",
3017
3060
  value: this.buildAddMfaFinishEnvelope(ctx)
3018
3061
  });
3062
+ if (!ctx.addMfa?.removed && !(ctx.mfaEnroll?.done && ctx.mfaEnroll?.method)) return void 0;
3063
+ const hook = this.afterMfaChanged(ctx);
3064
+ return hook instanceof Promise ? hook.then(() => void 0) : void 0;
3019
3065
  }
3020
3066
  /**
3021
3067
  * `finish-add-mfa`'s envelope construction, extracted pure so the outcome
@@ -4077,6 +4123,71 @@ let AuthWorkflow = class AuthWorkflow {
4077
4123
  await this.users.unlockAccount(ctx.subject);
4078
4124
  }
4079
4125
  /**
4126
+ * The SINGLE login-completion funnel. Every flow that establishes an
4127
+ * authenticated session routes through here — placed in each login schema
4128
+ * right after the guards and BEFORE the delivery terminal (`issue` /
4129
+ * `mint-authz-code` / `finalize-auto-login`) — so a login can never be
4130
+ * delivered without passing this point. Two uniform jobs:
4131
+ * 1. Stamp `account.lastLogin` exactly once (the sole workflow writer of it).
4132
+ * 2. Fire the `afterLogin` customer hook.
4133
+ *
4134
+ * Idempotent per run via `ctx.loginRecorded`: the password `credentials` path
4135
+ * already stamped eagerly through `users.login()` and latched the flag, so the
4136
+ * stamp NO-OPS there (no double write) — but `afterLogin` still fires, so the
4137
+ * hook runs exactly once for password logins too. Federated (`sso-callback`)
4138
+ * and auto-login (invite/signup/recovery) paths never call `login()`, so this
4139
+ * is their sole stamp. Self-gates on `ctx.subject`. Runs AFTER
4140
+ * `prepare-semantic-flags` derived `isFirstLogin`, so a genuine first
4141
+ * federated login still observes `isFirstLogin === true`.
4142
+ *
4143
+ * A throw (from the stamp or the hook) aborts the flow BEFORE delivery, so the
4144
+ * login fails atomically — no half-issued session.
4145
+ */
4146
+ recordLogin(ctx) {
4147
+ if (!ctx.subject) return void 0;
4148
+ if (!ctx.loginRecorded) {
4149
+ ctx.loginRecorded = true;
4150
+ return this.users.recordLogin(ctx.subject).then(() => this.afterLogin(ctx)).then(() => void 0);
4151
+ }
4152
+ const hook = this.afterLogin(ctx);
4153
+ return hook instanceof Promise ? hook.then(() => void 0) : void 0;
4154
+ }
4155
+ /**
4156
+ * Recovery-only guard, extracted from the finalize terminals so they stay pure
4157
+ * delivery. An `admin-only` lockout never self-unlocks, so a reset that left
4158
+ * the account frozen must NOT be confirmed-as-success OR auto-logged-in
4159
+ * (minting tokens would defeat the very freeze). When still locked it emits the
4160
+ * warn terminal and sets `ctx.aborted`, so the schema's following `{ break }`
4161
+ * skips BOTH the `record-login` funnel and the finalize terminals — a frozen
4162
+ * account is never stamped or logged in. The schema gates this on
4163
+ * `ctx.lockout?.mode === "admin-only"` (the only mode that can reach finalize
4164
+ * still locked: self-service ran `unlock-account`; temporary auto-expires).
4165
+ */
4166
+ async recoveryLockCheck(ctx) {
4167
+ if (await this.recoveryLeftAccountLocked(ctx)) {
4168
+ this.finishRecoveryReset(ctx, true);
4169
+ ctx.aborted = true;
4170
+ }
4171
+ }
4172
+ /**
4173
+ * Thin dispatcher steps for the flow-specific lifecycle hooks. Each is its own
4174
+ * schema step (rather than an in-terminal call) because its flow's finalize
4175
+ * terminals are SHARED across flows (`finalize-auto-login` serves invite +
4176
+ * recovery + signup; `finalize-fresh-login` serves invite + recovery), so a
4177
+ * dedicated step in the flow-specific schema fires the right hook without
4178
+ * ctx-discrimination inside a shared terminal. Named `fire*` so the overridable
4179
+ * `after*` hooks keep the clean public name.
4180
+ */
4181
+ fireInvitationAccepted(ctx) {
4182
+ return this.afterInvitationAccepted(ctx);
4183
+ }
4184
+ fireSignup(ctx) {
4185
+ return this.afterSignup(ctx);
4186
+ }
4187
+ firePasswordReset(ctx) {
4188
+ return this.afterPasswordReset(ctx);
4189
+ }
4190
+ /**
4080
4191
  * Issue access + refresh tokens via `auth.issue`. Stashes the login
4081
4192
  * response envelope on `useWfFinished` so downstream `redirect` can
4082
4193
  * override with a redirect envelope while preserving the cookies.
@@ -4096,7 +4207,7 @@ let AuthWorkflow = class AuthWorkflow {
4096
4207
  ...cookies,
4097
4208
  [name]: {
4098
4209
  value,
4099
- options: auth.cookieAttrs({ maxAge: ttlMs / 1e3 })
4210
+ options: auth.cookieAttrs({ maxAge: ttlMs })
4100
4211
  }
4101
4212
  };
4102
4213
  };
@@ -4308,9 +4419,6 @@ let AuthWorkflow = class AuthWorkflow {
4308
4419
  (ctx.completion ??= {}).redirectUrl = target;
4309
4420
  return;
4310
4421
  }
4311
- if (ctx.lockout?.mode === "admin-only") return this.recoveryLeftAccountLocked(ctx).then((locked) => {
4312
- this.finishRecoveryReset(ctx, locked);
4313
- });
4314
4422
  this.finishRecoveryReset(ctx, false);
4315
4423
  }
4316
4424
  /**
@@ -4372,17 +4480,20 @@ let AuthWorkflow = class AuthWorkflow {
4372
4480
  (ctx.completion ??= {}).redirectUrl = target;
4373
4481
  }
4374
4482
  /**
4375
- * Auto-login finalize — invite + recovery. Issues access + refresh tokens
4376
- * and stashes the login response envelope on `useWfFinished`. Invite
4377
- * preserves any `message` set by an earlier terminal (`confirmation`) so
4378
- * the SPA paints the confirmation text alongside the tokens (WF-INVITE-020).
4483
+ * Auto-login finalize — invite + recovery + signup. PURE delivery: issues
4484
+ * access + refresh tokens and stashes the login response envelope on
4485
+ * `useWfFinished`. Invite preserves any `message` set by an earlier terminal
4486
+ * (`confirmation`) so the SPA paints the confirmation text alongside the
4487
+ * tokens (WF-INVITE-020).
4488
+ *
4489
+ * It records NOTHING and guards NOTHING: `account.lastLogin` + the
4490
+ * `afterLogin` hook are owned by the upstream `record-login` funnel step, and
4491
+ * the admin-only-survived-lock guard by the upstream `recovery-lock-check`
4492
+ * step — both of which `{ break }`/gate this step out when they apply, so a
4493
+ * still-frozen account never reaches here.
4379
4494
  */
4380
4495
  async finalizeAutoLogin(ctx) {
4381
4496
  this.requireSubject(ctx);
4382
- if (ctx.lockout?.mode === "admin-only" && await this.recoveryLeftAccountLocked(ctx)) {
4383
- this.finishRecoveryReset(ctx, true);
4384
- return;
4385
- }
4386
4497
  const issue = await this.issueForContext(ctx);
4387
4498
  const auth = useAuth();
4388
4499
  const previousMessage = (useWfFinished().get()?.value)?.message;
@@ -5253,7 +5364,7 @@ __decorate([
5253
5364
  __decorateParam(0, WorkflowParam("context")),
5254
5365
  __decorateMetadata("design:type", Function),
5255
5366
  __decorateMetadata("design:paramtypes", [Object]),
5256
- __decorateMetadata("design:returntype", void 0)
5367
+ __decorateMetadata("design:returntype", Object)
5257
5368
  ], AuthWorkflow.prototype, "finishAddMfa", null);
5258
5369
  __decorate([
5259
5370
  Step("prepare-locked-mfa-transports"),
@@ -5511,6 +5622,46 @@ __decorate([
5511
5622
  __decorateMetadata("design:paramtypes", [Object]),
5512
5623
  __decorateMetadata("design:returntype", Promise)
5513
5624
  ], AuthWorkflow.prototype, "unlockAccount", null);
5625
+ __decorate([
5626
+ Step("record-login"),
5627
+ Public(),
5628
+ __decorateParam(0, WorkflowParam("context")),
5629
+ __decorateMetadata("design:type", Function),
5630
+ __decorateMetadata("design:paramtypes", [Object]),
5631
+ __decorateMetadata("design:returntype", Object)
5632
+ ], AuthWorkflow.prototype, "recordLogin", null);
5633
+ __decorate([
5634
+ Step("recovery-lock-check"),
5635
+ Public(),
5636
+ __decorateParam(0, WorkflowParam("context")),
5637
+ __decorateMetadata("design:type", Function),
5638
+ __decorateMetadata("design:paramtypes", [Object]),
5639
+ __decorateMetadata("design:returntype", Promise)
5640
+ ], AuthWorkflow.prototype, "recoveryLockCheck", null);
5641
+ __decorate([
5642
+ Step("after-invitation-accepted"),
5643
+ Public(),
5644
+ __decorateParam(0, WorkflowParam("context")),
5645
+ __decorateMetadata("design:type", Function),
5646
+ __decorateMetadata("design:paramtypes", [Object]),
5647
+ __decorateMetadata("design:returntype", Object)
5648
+ ], AuthWorkflow.prototype, "fireInvitationAccepted", null);
5649
+ __decorate([
5650
+ Step("after-signup"),
5651
+ Public(),
5652
+ __decorateParam(0, WorkflowParam("context")),
5653
+ __decorateMetadata("design:type", Function),
5654
+ __decorateMetadata("design:paramtypes", [Object]),
5655
+ __decorateMetadata("design:returntype", Object)
5656
+ ], AuthWorkflow.prototype, "fireSignup", null);
5657
+ __decorate([
5658
+ Step("after-password-reset"),
5659
+ Public(),
5660
+ __decorateParam(0, WorkflowParam("context")),
5661
+ __decorateMetadata("design:type", Function),
5662
+ __decorateMetadata("design:paramtypes", [Object]),
5663
+ __decorateMetadata("design:returntype", Object)
5664
+ ], AuthWorkflow.prototype, "firePasswordReset", null);
5514
5665
  __decorate([
5515
5666
  Step("issue"),
5516
5667
  Public(),
@@ -5557,7 +5708,7 @@ __decorate([
5557
5708
  __decorateParam(0, WorkflowParam("context")),
5558
5709
  __decorateMetadata("design:type", Function),
5559
5710
  __decorateMetadata("design:paramtypes", [Object]),
5560
- __decorateMetadata("design:returntype", Object)
5711
+ __decorateMetadata("design:returntype", void 0)
5561
5712
  ], AuthWorkflow.prototype, "finalizeFreshLogin", null);
5562
5713
  __decorate([
5563
5714
  Step("finalize-auto-login"),
@@ -5723,6 +5874,10 @@ __decorate([
5723
5874
  }]
5724
5875
  },
5725
5876
  { break: (ctx) => !!ctx.aborted },
5877
+ {
5878
+ id: "record-login",
5879
+ condition: (ctx) => !!ctx.subject
5880
+ },
5726
5881
  {
5727
5882
  condition: (ctx) => !ctx.authz,
5728
5883
  steps: [
@@ -5796,6 +5951,7 @@ __decorate([
5796
5951
  ...consentsPersistTailSchema,
5797
5952
  { id: "unset-pending-invitation" },
5798
5953
  { id: "activate-user" },
5954
+ { id: "after-invitation-accepted" },
5799
5955
  {
5800
5956
  id: "confirmation",
5801
5957
  condition: (ctx) => !!ctx.accept?.showConfirmation
@@ -5804,6 +5960,10 @@ __decorate([
5804
5960
  id: "finalize-fresh-login",
5805
5961
  condition: (ctx) => !ctx.autoLogin
5806
5962
  },
5963
+ {
5964
+ id: "record-login",
5965
+ condition: (ctx) => !!ctx.autoLogin
5966
+ },
5807
5967
  {
5808
5968
  id: "finalize-auto-login",
5809
5969
  condition: (ctx) => !!ctx.autoLogin
@@ -5846,10 +6006,20 @@ __decorate([
5846
6006
  condition: (ctx) => ctx.lockout?.mode === "self-service"
5847
6007
  },
5848
6008
  ...consentsPersistTailSchema,
6009
+ { id: "after-password-reset" },
6010
+ {
6011
+ id: "recovery-lock-check",
6012
+ condition: (ctx) => ctx.lockout?.mode === "admin-only"
6013
+ },
6014
+ { break: (ctx) => !!ctx.aborted },
5849
6015
  {
5850
6016
  id: "finalize-fresh-login",
5851
6017
  condition: (ctx) => !ctx.autoLogin
5852
6018
  },
6019
+ {
6020
+ id: "record-login",
6021
+ condition: (ctx) => !!ctx.autoLogin
6022
+ },
5853
6023
  {
5854
6024
  id: "finalize-auto-login",
5855
6025
  condition: (ctx) => !!ctx.autoLogin
@@ -5946,6 +6116,8 @@ __decorate([
5946
6116
  { id: "activate-user" },
5947
6117
  ...consentsPersistTailSchema,
5948
6118
  { id: "signup-extra-step" },
6119
+ { id: "after-signup" },
6120
+ { id: "record-login" },
5949
6121
  { id: "finalize-auto-login" }
5950
6122
  ]),
5951
6123
  __decorateMetadata("design:type", Function),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aooth/auth-moost",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "Moost auth integration for aoothjs — AuthGuard interceptor, useAuth composable, REST endpoints, workflows",
5
5
  "keywords": [
6
6
  "aoothjs",
@@ -57,27 +57,27 @@
57
57
  "access": "public"
58
58
  },
59
59
  "dependencies": {
60
- "@atscript/moost-wf": "^0.1.101",
60
+ "@atscript/moost-wf": "^0.1.102",
61
61
  "@wooksjs/http-body": "^0.7.19",
62
- "@aooth/arbac-moost": "^0.1.23",
63
- "@aooth/idp": "0.1.23",
64
- "@aooth/auth": "0.1.23",
65
- "@aooth/user": "0.1.23"
62
+ "@aooth/arbac-moost": "^0.1.25",
63
+ "@aooth/auth": "0.1.25",
64
+ "@aooth/idp": "0.1.25",
65
+ "@aooth/user": "0.1.25"
66
66
  },
67
67
  "devDependencies": {
68
- "@atscript/core": "^0.1.76",
69
- "@atscript/typescript": "^0.1.76",
70
- "@atscript/ui": "^0.1.101",
71
- "@atscript/ui-fns": "^0.1.101",
68
+ "@atscript/core": "^0.1.77",
69
+ "@atscript/typescript": "^0.1.77",
70
+ "@atscript/ui": "^0.1.102",
71
+ "@atscript/ui-fns": "^0.1.102",
72
72
  "@moostjs/event-http": "^0.6.27",
73
73
  "@moostjs/event-wf": "^0.6.27",
74
74
  "moost": "^0.6.27",
75
- "unplugin-atscript": "^0.1.76",
75
+ "unplugin-atscript": "^0.1.77",
76
76
  "wooks": "^0.7.19"
77
77
  },
78
78
  "peerDependencies": {
79
- "@atscript/moost-wf": "^0.1.101",
80
- "@atscript/typescript": "^0.1.76",
79
+ "@atscript/moost-wf": "^0.1.102",
80
+ "@atscript/typescript": "^0.1.77",
81
81
  "@moostjs/event-http": "^0.6.27",
82
82
  "@moostjs/event-wf": "^0.6.27",
83
83
  "@wooksjs/event-core": "^0.7.19",