@nxgt/janus 0.13.0 → 0.15.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.
Files changed (92) hide show
  1. package/README.md +132 -25
  2. package/dist/auth/config/index.d.ts +1 -1
  3. package/dist/auth/config/index.d.ts.map +1 -1
  4. package/dist/auth/config/janus-config.d.ts +25 -0
  5. package/dist/auth/config/janus-config.d.ts.map +1 -1
  6. package/dist/auth/config/resolve-config.d.ts.map +1 -1
  7. package/dist/auth/config/resolve-sign-in.d.ts +5 -0
  8. package/dist/auth/config/resolve-sign-in.d.ts.map +1 -0
  9. package/dist/auth/config/resolved-config.d.ts +6 -0
  10. package/dist/auth/config/resolved-config.d.ts.map +1 -1
  11. package/dist/auth/derived-keys.d.ts +9 -0
  12. package/dist/auth/derived-keys.d.ts.map +1 -0
  13. package/dist/auth/email-sign-in.d.ts +40 -0
  14. package/dist/auth/email-sign-in.d.ts.map +1 -0
  15. package/dist/auth/events.d.ts +22 -6
  16. package/dist/auth/events.d.ts.map +1 -1
  17. package/dist/auth/index.d.ts +2 -2
  18. package/dist/auth/index.d.ts.map +1 -1
  19. package/dist/auth/magic-link.d.ts +22 -0
  20. package/dist/auth/magic-link.d.ts.map +1 -0
  21. package/dist/auth/one-time/index.d.ts +3 -1
  22. package/dist/auth/one-time/index.d.ts.map +1 -1
  23. package/dist/auth/one-time/window.d.ts +50 -0
  24. package/dist/auth/one-time/window.d.ts.map +1 -0
  25. package/dist/auth/password-written.d.ts +7 -0
  26. package/dist/auth/password-written.d.ts.map +1 -1
  27. package/dist/auth/port/types/tokens.d.ts +6 -3
  28. package/dist/auth/port/types/tokens.d.ts.map +1 -1
  29. package/dist/auth/second-factor/app-code-attempts.d.ts +5 -8
  30. package/dist/auth/second-factor/app-code-attempts.d.ts.map +1 -1
  31. package/dist/auth/second-factor/challenge.d.ts.map +1 -1
  32. package/dist/auth/second-factor/recovery-codes.d.ts.map +1 -1
  33. package/dist/auth/second-factor/recovery.d.ts.map +1 -1
  34. package/dist/auth/sign-in-attempts.d.ts +43 -0
  35. package/dist/auth/sign-in-attempts.d.ts.map +1 -0
  36. package/dist/auth/sign-in-code.d.ts +1 -3
  37. package/dist/auth/sign-in-code.d.ts.map +1 -1
  38. package/dist/auth/types/email-flows.d.ts +3 -3
  39. package/dist/auth/types/index.d.ts +1 -0
  40. package/dist/auth/types/index.d.ts.map +1 -1
  41. package/dist/auth/types/janus.d.ts +8 -1
  42. package/dist/auth/types/janus.d.ts.map +1 -1
  43. package/dist/auth/types/magic-link.d.ts +46 -0
  44. package/dist/auth/types/magic-link.d.ts.map +1 -0
  45. package/dist/auth/types/password.d.ts +8 -0
  46. package/dist/auth/types/password.d.ts.map +1 -1
  47. package/dist/auth/users/any-type-api.d.ts +2 -2
  48. package/dist/auth/users/any-type-api.d.ts.map +1 -1
  49. package/dist/auth/users/fields-patch.d.ts +8 -2
  50. package/dist/auth/users/fields-patch.d.ts.map +1 -1
  51. package/dist/auth/users/record-flows.d.ts.map +1 -1
  52. package/dist/auth/users/sign-in.d.ts +2 -2
  53. package/dist/auth/users/sign-in.d.ts.map +1 -1
  54. package/dist/auth/users/type-api.d.ts +2 -1
  55. package/dist/auth/users/type-api.d.ts.map +1 -1
  56. package/dist/auth/users/update.d.ts +12 -0
  57. package/dist/auth/users/update.d.ts.map +1 -0
  58. package/dist/chunks/{index-km7ffctx.js → index-6c9fbtv2.js} +2 -2
  59. package/dist/chunks/{index-rd2rddvv.js → index-baazjyvc.js} +2 -2
  60. package/dist/chunks/{index-j2gd8fry.js → index-hnwggyxs.js} +3 -2
  61. package/dist/chunks/{index-j2gd8fry.js.map → index-hnwggyxs.js.map} +3 -3
  62. package/dist/chunks/{index-jp2kka6d.js → index-kj3st57z.js} +2 -2
  63. package/dist/conformance/cases/tokens/kinds.d.ts +4 -1
  64. package/dist/conformance/cases/tokens/kinds.d.ts.map +1 -1
  65. package/dist/conformance/index.js +26 -4
  66. package/dist/conformance/index.js.map +3 -3
  67. package/dist/errors/janus-error/base.d.ts +1 -0
  68. package/dist/errors/janus-error/base.d.ts.map +1 -1
  69. package/dist/errors/janus-error/codes.d.ts +3 -1
  70. package/dist/errors/janus-error/codes.d.ts.map +1 -1
  71. package/dist/errors/janus-error/options.d.ts +9 -2
  72. package/dist/errors/janus-error/options.d.ts.map +1 -1
  73. package/dist/index.js +296 -101
  74. package/dist/index.js.map +24 -17
  75. package/dist/permissions/index.js +3 -3
  76. package/docs/README.md +4 -3
  77. package/docs/guide/adapters.md +11 -7
  78. package/docs/guide/email-flows.md +11 -7
  79. package/docs/guide/errors.md +12 -4
  80. package/docs/guide/events.md +75 -14
  81. package/docs/guide/magic-link.md +411 -0
  82. package/docs/guide/passwords.md +116 -17
  83. package/docs/guide/second-factor.md +6 -3
  84. package/docs/guide/sign-in-code.md +14 -6
  85. package/docs/guide/users.md +13 -7
  86. package/docs/guide/vocabulary.md +6 -5
  87. package/docs/roadmap.md +37 -23
  88. package/docs/troubleshooting.md +203 -9
  89. package/package.json +1 -1
  90. /package/dist/chunks/{index-km7ffctx.js.map → index-6c9fbtv2.js.map} +0 -0
  91. /package/dist/chunks/{index-rd2rddvv.js.map → index-baazjyvc.js.map} +0 -0
  92. /package/dist/chunks/{index-jp2kka6d.js.map → index-kj3st57z.js.map} +0 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Attempts counted by the store in fixed windows of the clock — what bounds
3
+ * the codes tried at an app outside a sign-in (`second-factor/app-code-attempts.ts`)
4
+ * and the passwords tried at one login (`../sign-in-attempts.ts`).
5
+ *
6
+ * **No port of its own.** The count is a one-time token of kind
7
+ * `secondFactor`, counted by `countAttempt` like a challenge's: one
8
+ * conditional write per attempt, never read then written, so twenty guesses
9
+ * at once are twenty distinct counts. Its secret is never given out: each
10
+ * caller names it by a keyed hash of what the count is for, so it cannot be
11
+ * redeemed as a challenge.
12
+ *
13
+ * A token once spent counts nothing more. So the count is a **chain** of
14
+ * links, and what a spent link means is the caller's to say: `carry`, and the
15
+ * next link carries on from the attempts it holds — a password written, which
16
+ * spends every `secondFactor` token of the user, buys no guess; `restart`,
17
+ * and the next link starts from zero — a sign-in that succeeded spends the
18
+ * link it counted on, and the login's count starts again.
19
+ */
20
+ import type { Context } from '../context';
21
+ /**
22
+ * More links than this in one window, for `carry`: more passwords written
23
+ * than guesses, and the count is past any limit.
24
+ */
25
+ export declare const MAX_LINKS = 32;
26
+ /** What {@link countInWindow} counts, and how. */
27
+ export interface AttemptWindow {
28
+ /** How long one window lasts, in milliseconds. */
29
+ readonly windowMs: number;
30
+ /** What a spent link means: its attempts carried on, or a count started again. */
31
+ readonly spent: 'carry' | 'restart';
32
+ /** The `userId` each link is stored under. */
33
+ readonly userId: string;
34
+ /** A link's token hash in one window: never given out, and never a secret. */
35
+ readonly linkHash: (window: number, link: number) => string;
36
+ /** What to throw when a link is gone right after it was stored, or the links never end. */
37
+ readonly vanished: () => Error;
38
+ }
39
+ /** One attempt, counted. */
40
+ export interface CountedAttempt {
41
+ /** The attempts of this window, this one included. */
42
+ readonly attempts: number;
43
+ /** The link it was counted on — what spending restarts — or `null` past the last one. */
44
+ readonly link: string | null;
45
+ /** When the window ends, in milliseconds since the epoch. */
46
+ readonly endsAt: number;
47
+ }
48
+ /** Counts one attempt in the current window, before anything is compared. */
49
+ export declare function countInWindow(context: Context, counting: AttemptWindow): Promise<CountedAttempt>;
50
+ //# sourceMappingURL=window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/auth/one-time/window.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C;;;GAGG;AACH,eAAO,MAAM,SAAS,KAAK,CAAC;AAQ5B,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5D,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,EAAE,MAAM,KAAK,CAAC;CAC/B;AAED,4BAA4B;AAC5B,MAAM,WAAW,cAAc;IAC9B,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAUD,6EAA6E;AAC7E,wBAAsB,aAAa,CAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,aAAa,GACrB,OAAO,CAAC,cAAc,CAAC,CAazB"}
@@ -26,6 +26,13 @@ import type { SignInResult } from './types';
26
26
  * which a reset revokes.
27
27
  */
28
28
  export declare function endWhatThePasswordOpened(context: Context, userId: Id): Promise<void>;
29
+ /**
30
+ * What a change and a set do once the password is written: end what the
31
+ * old one opened, then send `user.passwordChanged` — from a `finally`, so an
32
+ * outage ending them still reports the write, which a retry would not make
33
+ * again. A reset sends `user.passwordReset` instead, from its own flow.
34
+ */
35
+ export declare function passwordChanged(context: Context, written: UserRecord): Promise<void>;
29
36
  /**
30
37
  * Whether the password a sign-in verified is still the user's, once the
31
38
  * sign-in answered. A password written meanwhile ends the sign-in: its
@@ -1 +1 @@
1
- {"version":3,"file":"password-written.d.ts","sourceRoot":"","sources":["../../src/auth/password-written.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAGZ,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,EAAE,GACR,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAkBlB"}
1
+ {"version":3,"file":"password-written.d.ts","sourceRoot":"","sources":["../../src/auth/password-written.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAGZ,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,EAAE,GACR,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAkBlB"}
@@ -16,12 +16,15 @@ import type { Id } from '../../../ids/id';
16
16
  * attempts at `regenerateRecoveryCodes`, a token of this kind whose secret
17
17
  * nobody is given, never redeemed, only counted.
18
18
  * - `signInCode`: a code sent by e-mail to sign in without a password.
19
+ * - `magicLink`: a link sent by e-mail to sign in without a password. A kind
20
+ * of its own, so a sign-in code's challenge — which the visitor holds —
21
+ * never signs anyone in as a link, nor a link's token as a challenge.
19
22
  * - `stepUp`: a signed-in user's confirmation of a sensitive action — a code
20
23
  * sent by e-mail, or, with an active second factor, a code from their app.
21
24
  * A kind of its own, so a sign-in code never confirms an action nor an
22
25
  * action's code signs anyone in.
23
26
  */
24
- export type TokenKind = 'verifyEmail' | 'resetPassword' | 'secondFactor' | 'signInCode' | 'stepUp';
27
+ export type TokenKind = 'verifyEmail' | 'resetPassword' | 'secondFactor' | 'signInCode' | 'magicLink' | 'stepUp';
25
28
  /** A one-time token, as a store holds it: its hash, never its secret. */
26
29
  export interface TokenRecord {
27
30
  /** `sha256` of the token's secret, hex. Unique across the store. */
@@ -104,8 +107,8 @@ export interface TokenStore {
104
107
  * Spends every **unspent** token of one user and one `kind` at `at` —
105
108
  * but the one whose hash is `except`, when given — and answers how many
106
109
  * it spent. What issuing a sign-in code calls, sparing the code it just
107
- * issued, so only the last code sent works — and so for a reset link and
108
- * a step-up; and what writing a password calls, so no reset link and no
110
+ * issued, so only the last code sent works — and so for a sign-in link,
111
+ * a reset link and a step-up; and what writing a password calls, so no reset link and no
109
112
  * second-factor challenge opened with the old one survives.
110
113
  *
111
114
  * - A spent token keeps its `spentAt`: it never changes once set.
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/auth/port/types/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,SAAS,GAClB,aAAa,GACb,eAAe,GACf,cAAc,GACd,YAAY,GACZ,QAAQ,CAAC;AAEZ,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IAC1B;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,GACN,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE9E;;;;;;;;;;;;;;;;;OAiBG;IACH,eAAe,CACd,MAAM,EAAE,EAAE,EACV,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/auth/port/types/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,SAAS,GAClB,aAAa,GACb,eAAe,GACf,cAAc,GACd,YAAY,GACZ,WAAW,GACX,QAAQ,CAAC;AAEZ,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IAC1B;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,GACN,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE9E;;;;;;;;;;;;;;;;;OAiBG;IACH,eAAe,CACd,MAAM,EAAE,EAAE,EACV,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C"}
@@ -8,11 +8,9 @@ import type { Sealer } from '../sealing';
8
8
  * per window, so a stolen session cannot guess the app's code at leisure,
9
9
  * nor buy more guesses by switching from one to the other.
10
10
  *
11
- * **No port of its own.** The count is a one-time token of kind
12
- * `secondFactor`, counted by `countAttempt` like a challenge's: one
13
- * conditional write per attempt, never read then written. Its secret is
14
- * never given out; it is a keyed hash of what the count is for, so nobody
15
- * without the sealing keys can name it — nor redeem it as a challenge.
11
+ * Counted in an attempt window (`../one-time/window.ts`): a `secondFactor`
12
+ * token named by a keyed hash of what the count is for, so nobody without
13
+ * the sealing keys can name it — nor redeem it as a challenge.
16
14
  *
17
15
  * What it is for decides when it starts again: the **window**, a fixed
18
16
  * {@link APP_CODE_WINDOW_MS} slice of the clock, and the factor's
@@ -21,9 +19,8 @@ import type { Sealer } from '../sealing';
21
19
  * app.
22
20
  *
23
21
  * Writing a password spends every `secondFactor` token of the user, this one
24
- * included, and a spent token counts nothing more. So the count is a chain:
25
- * a spent link keeps the attempts it holds, and the next one carries on
26
- * from them — a password written between guesses buys none.
22
+ * included. So a spent link **carries** its attempts on to the next — a
23
+ * password written between guesses buys none.
27
24
  */
28
25
  /** How long the attempts of one window last: fifteen minutes. */
29
26
  export declare const APP_CODE_WINDOW_MS: number;
@@ -1 +1 @@
1
- {"version":3,"file":"app-code-attempts.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/app-code-attempts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGzC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,QAAc,CAAC;AA8C9C;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
1
+ {"version":3,"file":"app-code-attempts.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/app-code-attempts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGzC;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,QAAc,CAAC;AA6B9C;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CA+BjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/challenge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAI/D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE;kBAGhE,UAAU,SACX,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC;uBAqBP,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;EAI3E"}
1
+ {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/challenge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAI/D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE;kBAGhE,UAAU,SACX,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC;uBAqBP,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;EAI3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"recovery-codes.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/recovery-codes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;;;;;;;GAYG;AAEH,sEAAsE;AACtE,eAAO,MAAM,cAAc,KAAK,CAAC;AASjC,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAQ5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO7D;AAwBD,wEAAwE;AACxE,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACV,MAAM,CAIR;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACX,MAAM,CA6BR"}
1
+ {"version":3,"file":"recovery-codes.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/recovery-codes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;;;;;;;GAYG;AAEH,sEAAsE;AACtE,eAAO,MAAM,cAAc,KAAK,CAAC;AASjC,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAQ5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO7D;AASD,wEAAwE;AACxE,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACV,MAAM,CAIR;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACX,MAAM,CA6BR"}
@@ -1 +1 @@
1
- {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAIhD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,EAAE,GACJ,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAmCnC"}
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAIhD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,EAAE,GACJ,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAoCnC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The passwords tried at one login, counted by the store per window —
3
+ * `janus({ signIn: { throttle } })`, ten per fifteen minutes by default.
4
+ * Past the last one, `signIn` answers `CREDENTIALS_INVALID` with
5
+ * `retryAfter`, the right password included, until the window ends. **Nothing
6
+ * locks** past a window — but somebody who keeps trying a login keeps its
7
+ * password sign-in shut, window after window: a per-client limit is the
8
+ * application's, and a sign-in code still opens the account.
9
+ *
10
+ * Counted per login, **known or not**: an unknown login is counted as a
11
+ * registered one is, so the throttle does not tell them apart. Counted
12
+ * before anything is looked up or compared, so of twenty guesses at once,
13
+ * exactly as many as the limit are compared.
14
+ *
15
+ * Counted in an attempt window (`one-time/window.ts`), in `secondFactor`
16
+ * tokens stored under no user: the `userId` of each is a keyed hash of the
17
+ * login, never the login. The key is derived from the sealing keys when
18
+ * `secondFactor` is configured; without them it is a fixed one, and the hash
19
+ * only keeps the login out of plain sight — safe because a `secondFactor`
20
+ * token is redeemed only by the second factor's flows, which do not exist
21
+ * without the keys. A sign-in that opens a session spends the link it
22
+ * counts on, and the login's count **restarts** from zero.
23
+ *
24
+ * A store that cannot count throws `STORE_FAILED`: never a refusal, and
25
+ * never a sign-in let through uncounted.
26
+ */
27
+ import type { ResolvedType } from './config';
28
+ import type { Context } from './context';
29
+ import type { UserRecord } from './port/types';
30
+ /**
31
+ * Counts one password tried at `login` — already normalised — before it is
32
+ * looked up, and refuses past the last one: the right password included.
33
+ */
34
+ export declare function countSignInAttempt(context: Context, type: ResolvedType, login: string, where: string): Promise<void>;
35
+ /**
36
+ * Starts the user's count again, once a sign-in opens a session: after the
37
+ * password alone, or after the second factor's code — never after the
38
+ * password of a user whose second factor is still to come, so knowing the
39
+ * password buys no more challenges. It counts one attempt on the current
40
+ * link, and spends it: the next one counts from zero.
41
+ */
42
+ export declare function restartSignInCount(context: Context, type: ResolvedType, record: UserRecord, where: string): Promise<void>;
43
+ //# sourceMappingURL=sign-in-attempts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-in-attempts.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-attempts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA8C/C;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAWf"}
@@ -1,7 +1,7 @@
1
1
  import type { At } from './at';
2
2
  import type { ResolvedType } from './config';
3
3
  import { type AnyUser, type Context } from './context';
4
- import type { UserRecord } from './port/types';
4
+ import { type Finish } from './email-sign-in';
5
5
  import type { SignInCodeApi, SignInResult } from './types';
6
6
  /**
7
7
  * Signing in with a code sent to the user's e-mail: no password, and the
@@ -18,6 +18,4 @@ import type { SignInCodeApi, SignInResult } from './types';
18
18
  * tokens alone do not reveal it.
19
19
  */
20
20
  export declare function signInCodeFlows(context: Context, type: ResolvedType, at: At, finish: Finish): SignInCodeApi<AnyUser, SignInResult<AnyUser>>['signInCode'];
21
- type Finish = (record: UserRecord, where: string) => Promise<SignInResult<AnyUser>>;
22
- export {};
23
21
  //# sourceMappingURL=sign-in-code.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sign-in-code.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,WAAW,CAAC;AAanB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAc,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,GACZ,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAU7D;AAED,KAAK,MAAM,GAAG,CACb,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,KACT,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"sign-in-code.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,WAAW,CAAC;AAC3E,OAAO,EACN,KAAK,MAAM,EAIX,MAAM,iBAAiB,CAAC;AAWzB,OAAO,KAAK,EAAc,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,GACZ,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAU7D"}
@@ -44,9 +44,9 @@ export interface SignInCodeApi<U, Answer = SignedIn<U>> {
44
44
  * time — send the e-mail off the request's path.
45
45
  *
46
46
  * **Rate-limit it, per e-mail and per client.** Every call issues a new
47
- * challenge with five attempts of its own, and the earlier ones stay
48
- * valid until they lapse: the five attempts bound one challenge, not
49
- * one account.
47
+ * challenge with five attempts of its own, and spends the earlier ones:
48
+ * only the last code sent works, and a new `request` is five guesses
49
+ * more — the five attempts bound one challenge, not one account.
50
50
  */
51
51
  request(email: string): Promise<IssuedCode<U> | null>;
52
52
  /**
@@ -11,6 +11,7 @@ export type { Checked } from './checks';
11
11
  export type { IssuedCode, IssuedToken, ResetPasswordApi, SignInCodeApi, VerifyEmailApi, } from './email-flows';
12
12
  export type { EmailOf, LoginOf, RequiredStringKeys, TypesOf, UserOf, } from './inference';
13
13
  export type { Janus, SharedApi, TypeApi } from './janus';
14
+ export type { MagicLinkApi } from './magic-link';
14
15
  export type { PasswordApi } from './password';
15
16
  export type { RecoveredSignIn, RecoveryCodesIssued, SecondFactorApi, SecondFactorEnrolment, } from './second-factor';
16
17
  export type { Authenticated, HeaderRecord, RequestLike, Session, } from './session';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACX,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,OAAO,EACP,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EACX,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,OAAO,GACP,MAAM,WAAW,CAAC;AACnB,YAAY,EACX,oBAAoB,EACpB,QAAQ,EACR,YAAY,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACX,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,OAAO,EACP,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EACX,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,OAAO,GACP,MAAM,WAAW,CAAC;AACnB,YAAY,EACX,oBAAoB,EACpB,QAAQ,EACR,YAAY,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -7,6 +7,7 @@
7
7
  import type { JanusConfig, MultiTypeConfig, SingleTypeConfig } from '../config';
8
8
  import type { ResetPasswordApi, SignInCodeApi, VerifyEmailApi } from './email-flows';
9
9
  import type { EmailOf, FieldsInput, LoginOf, SingleAsType, UserOf, UserOfType } from './inference';
10
+ import type { MagicLinkApi } from './magic-link';
10
11
  import type { PasswordApi } from './password';
11
12
  import type { SecondFactorApi } from './second-factor';
12
13
  import type { Authenticated, RequestLike, Session } from './session';
@@ -14,11 +15,17 @@ import type { SignedIn, SignInResult } from './sign-in';
14
15
  import type { StepUpApi, StepUpByApp, StepUpByEmail } from './step-up';
15
16
  import type { UserRef } from './user';
16
17
  import type { UserTypeApi } from './user-type';
18
+ /**
19
+ * What a sign-in by e-mail — a code or a link — answers: a session, or a
20
+ * challenge when the type has a password in an instance given a
21
+ * `secondFactor`, since the e-mail proves the address and not the factor.
22
+ */
23
+ type EmailSignInAnswer<Name extends string, Def, TwoFactor extends boolean> = TwoFactor extends true ? [LoginOf<Def>] extends [never] ? SignedIn<UserOfType<Name, Def>> : SignInResult<UserOfType<Name, Def>> : SignedIn<UserOfType<Name, Def>>;
17
24
  /**
18
25
  * The whole surface of one user type, with only the flows its configuration
19
26
  * allows. `TwoFactor` is whether `janus()` was given a `secondFactor`.
20
27
  */
21
- export type TypeApi<Name extends string, Def, TwoFactor extends boolean = false> = UserTypeApi<UserOfType<Name, Def>, FieldsInput<Def>> & ([LoginOf<Def>] extends [never] ? unknown : TwoFactor extends true ? PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>, SignInResult<UserOfType<Name, Def>>> & SecondFactorApi<UserOfType<Name, Def>> : PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>>) & ([EmailOf<Def>] extends [never] ? unknown : VerifyEmailApi<UserOfType<Name, Def>> & SignInCodeApi<UserOfType<Name, Def>, TwoFactor extends true ? [LoginOf<Def>] extends [never] ? SignedIn<UserOfType<Name, Def>> : SignInResult<UserOfType<Name, Def>> : SignedIn<UserOfType<Name, Def>>> & StepUpApi<UserOfType<Name, Def>, TwoFactor extends true ? [LoginOf<Def>] extends [never] ? StepUpByEmail<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>> | StepUpByApp<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>>>) & ([LoginOf<Def>] extends [never] ? unknown : [EmailOf<Def>] extends [never] ? unknown : ResetPasswordApi<UserOfType<Name, Def>>);
28
+ export type TypeApi<Name extends string, Def, TwoFactor extends boolean = false> = UserTypeApi<UserOfType<Name, Def>, FieldsInput<Def>> & ([LoginOf<Def>] extends [never] ? unknown : TwoFactor extends true ? PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>, SignInResult<UserOfType<Name, Def>>> & SecondFactorApi<UserOfType<Name, Def>> : PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>>) & ([EmailOf<Def>] extends [never] ? unknown : VerifyEmailApi<UserOfType<Name, Def>> & SignInCodeApi<UserOfType<Name, Def>, EmailSignInAnswer<Name, Def, TwoFactor>> & MagicLinkApi<UserOfType<Name, Def>, EmailSignInAnswer<Name, Def, TwoFactor>> & StepUpApi<UserOfType<Name, Def>, TwoFactor extends true ? [LoginOf<Def>] extends [never] ? StepUpByEmail<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>> | StepUpByApp<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>>>) & ([LoginOf<Def>] extends [never] ? unknown : [EmailOf<Def>] extends [never] ? unknown : ResetPasswordApi<UserOfType<Name, Def>>);
22
29
  /** What every configuration answers, whatever its user types. */
23
30
  export interface SharedApi<U extends {
24
31
  readonly type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"janus.d.ts","sourceRoot":"","sources":["../../../src/auth/types/janus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"janus.d.ts","sourceRoot":"","sources":["../../../src/auth/types/janus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * What a user type with an e-mail answers besides: signing in with a link
3
+ * sent to it.
4
+ *
5
+ * Part of what `janus()` hands back; `./index` gathers it.
6
+ */
7
+ import type { IssuedToken } from './email-flows';
8
+ import type { SignedIn } from './sign-in';
9
+ /**
10
+ * Signing in with a link sent to the user's e-mail, no password needed —
11
+ * a sign-in code with nothing to type.
12
+ *
13
+ * `Answer` is `SignInResult` when the type may have a second factor: the
14
+ * link proves the e-mail, and an active factor is still asked for.
15
+ */
16
+ export interface MagicLinkApi<U, Answer = SignedIn<U>> {
17
+ readonly magicLink: {
18
+ /**
19
+ * Issues a link's token for the user of this type holding this e-mail,
20
+ * or answers `null` when there is none, or they are inactive. **Never
21
+ * tell the visitor which**: answer the same page either way, and in the
22
+ * same time — send the e-mail off the request's path.
23
+ *
24
+ * Put `token` in a link to a page of yours, and **only in the e-mail**.
25
+ * The user's earlier links are spent: only the last one sent works.
26
+ * **Rate-limit it, per e-mail and per client**: every call sends an
27
+ * e-mail.
28
+ */
29
+ request(email: string): Promise<(IssuedToken & {
30
+ readonly user: U;
31
+ }) | null>;
32
+ /**
33
+ * Spends the link's token, marks the e-mail verified — the link reached
34
+ * the inbox — and signs the user in.
35
+ *
36
+ * **Call it from a `POST`**, never from the `GET` of the link: a mail
37
+ * scanner that opens the link would spend it. An unknown, spent or
38
+ * lapsed token is `TOKEN_UNKNOWN`, `TOKEN_SPENT` or `TOKEN_EXPIRED`; an
39
+ * e-mail the user changed since is `TOKEN_STALE`; an inactive user is
40
+ * `USER_INACTIVE`. The first call spends the token, whether it signs
41
+ * in or is refused.
42
+ */
43
+ confirm(token: string): Promise<Answer>;
44
+ };
45
+ }
46
+ //# sourceMappingURL=magic-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magic-link.d.ts","sourceRoot":"","sources":["../../../src/auth/types/magic-link.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE;QACnB;;;;;;;;;;WAUG;QACH,OAAO,CACN,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,WAAW,GAAG;YAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;SAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD;;;;;;;;;;WAUG;QACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACxC,CAAC;CACF"}
@@ -33,6 +33,14 @@ export interface PasswordApi<U, In, Login extends string, Answer = SignedIn<U>>
33
33
  * documented rather than denied. An inactive user who gave the right
34
34
  * password is `USER_INACTIVE`.
35
35
  *
36
+ * **Throttled per login**, on by default: past ten passwords tried at one
37
+ * login in a 15-minute window — known or not — every one is
38
+ * `CREDENTIALS_INVALID` with `reason: 'throttled'` and `retryAfter`, the
39
+ * seconds until the next window, the right password included. Nothing
40
+ * locks; a sign-in that succeeds starts the count again. See
41
+ * `janus({ signIn: { throttle } })`. A tokens store that cannot count is
42
+ * `STORE_FAILED`.
43
+ *
36
44
  * With a `secondFactor` configured, a user whose factor is active gets no
37
45
  * session yet: `{ status: 'secondFactor', challenge }`, for
38
46
  * `secondFactor.confirm`. Switch on `status`.
@@ -1 +1 @@
1
- {"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../../src/auth/types/password.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,WAAW,CAC3B,CAAC,EACD,EAAE,EACF,KAAK,SAAS,MAAM,EACpB,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAEpB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAExE;;;;;;;;;;;;;;OAcG;IACH,MAAM,CACL,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,KAAK,GAAG,MAAM;KAAE,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACtE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB,mFAAmF;IACnF,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE9C,8FAA8F;IAC9F,WAAW,CACV,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAAC;IAEd;;;;OAIG;IACH,cAAc,CACb,IAAI,EAAE,OAAO,EACb,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAC3D,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAAC;CACd"}
1
+ {"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../../src/auth/types/password.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,WAAW,CAC3B,CAAC,EACD,EAAE,EACF,KAAK,SAAS,MAAM,EACpB,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAEpB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAExE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CACL,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,KAAK,GAAG,MAAM;KAAE,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACtE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB,mFAAmF;IACnF,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE9C,8FAA8F;IAC9F,WAAW,CACV,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAAC;IAEd;;;;OAIG;IACH,cAAc,CACb,IAAI,EAAE,OAAO,EACb,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAC3D,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAAC;CACd"}
@@ -1,6 +1,6 @@
1
1
  import type { AnyUser } from '../context';
2
- import type { PasswordApi, ResetPasswordApi, SecondFactorApi, SignInCodeApi, SignInResult, StepUpApi, StepUpByApp, StepUpByEmail, UserTypeApi, VerifyEmailApi } from '../types';
2
+ import type { MagicLinkApi, PasswordApi, ResetPasswordApi, SecondFactorApi, SignInCodeApi, SignInResult, StepUpApi, StepUpByApp, StepUpByEmail, UserTypeApi, VerifyEmailApi } from '../types';
3
3
  import type { Input } from './flow-types';
4
4
  /** Everything one user type answers. Which flows it has is decided by its types; all are built. */
5
- export type AnyTypeApi = UserTypeApi<AnyUser, Input> & PasswordApi<AnyUser, Input, string, SignInResult<AnyUser>> & SecondFactorApi<AnyUser> & SignInCodeApi<AnyUser, SignInResult<AnyUser>> & StepUpApi<AnyUser, StepUpByEmail<AnyUser> | StepUpByApp<AnyUser>> & VerifyEmailApi<AnyUser> & ResetPasswordApi<AnyUser>;
5
+ export type AnyTypeApi = UserTypeApi<AnyUser, Input> & PasswordApi<AnyUser, Input, string, SignInResult<AnyUser>> & SecondFactorApi<AnyUser> & SignInCodeApi<AnyUser, SignInResult<AnyUser>> & MagicLinkApi<AnyUser, SignInResult<AnyUser>> & StepUpApi<AnyUser, StepUpByEmail<AnyUser> | StepUpByApp<AnyUser>> & VerifyEmailApi<AnyUser> & ResetPasswordApi<AnyUser>;
6
6
  //# sourceMappingURL=any-type-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"any-type-api.d.ts","sourceRoot":"","sources":["../../../src/auth/users/any-type-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,EACb,WAAW,EACX,cAAc,EACd,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,GACnD,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,GAC1D,eAAe,CAAC,OAAO,CAAC,GACxB,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,GAC7C,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,GACjE,cAAc,CAAC,OAAO,CAAC,GACvB,gBAAgB,CAAC,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"any-type-api.d.ts","sourceRoot":"","sources":["../../../src/auth/users/any-type-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,EACb,WAAW,EACX,cAAc,EACd,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,GACnD,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,GAC1D,eAAe,CAAC,OAAO,CAAC,GACxB,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,GAC7C,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,GAC5C,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,GACjE,cAAc,CAAC,OAAO,CAAC,GACvB,gBAAgB,CAAC,OAAO,CAAC,CAAC"}
@@ -1,13 +1,19 @@
1
1
  import { type ResolvedType } from '../config';
2
- import type { UserRecord } from '../port/types';
2
+ import type { JsonObject, UserRecord } from '../port/types';
3
3
  import type { Input } from './flow-types';
4
+ /**
5
+ * Whether the e-mail differs between two sets of fields, compared normalised:
6
+ * `Ada@Example.com` for `ada@example.com` is no change. The one test behind
7
+ * both the new e-mail's verification reset and `user.emailChanged`.
8
+ */
9
+ export declare function emailChanged(type: ResolvedType, before: JsonObject, after: JsonObject): boolean;
4
10
  /**
5
11
  * What `update` writes: the patch merged over the stored fields, the whole
6
12
  * result validated, and the logins derived again from it.
7
13
  */
8
14
  export declare function fieldsPatch(type: ResolvedType, record: UserRecord, patch: Input, where: string): Promise<{
9
15
  emailVerifiedAt?: null;
10
- fields: import("..").JsonObject;
16
+ fields: JsonObject;
11
17
  logins: string[];
12
18
  schemaVersion: string;
13
19
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"fields-patch.d.ts","sourceRoot":"","sources":["../../../src/auth/users/fields-patch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C;;;GAGG;AACH,wBAAsB,WAAW,CAChC,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM;;;;;GAoBb"}
1
+ {"version":3,"file":"fields-patch.d.ts","sourceRoot":"","sources":["../../../src/auth/users/fields-patch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAK1C;;;;GAIG;AACH,wBAAgB,YAAY,CAC3B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,UAAU,GACf,OAAO,CAET;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAChC,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM;;;;;GAiBb"}
@@ -1 +1 @@
1
- {"version":3,"file":"record-flows.d.ts","sourceRoot":"","sources":["../../../src/auth/users/record-flows.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAG1C;;;GAGG;AACH,wBAAgB,WAAW,CAC1B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,GACJ,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CA0D7B"}
1
+ {"version":3,"file":"record-flows.d.ts","sourceRoot":"","sources":["../../../src/auth/users/record-flows.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAI1C;;;GAGG;AACH,wBAAgB,WAAW,CAC1B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,GACJ,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CA0D7B"}
@@ -4,8 +4,8 @@ import type { SignInResult } from '../types';
4
4
  import type { Finish, Input } from './flow-types';
5
5
  /**
6
6
  * Checks the password and answers what `finish` answers for the user. One
7
- * refusal for an unknown login, no password and a wrong one; `USER_INACTIVE`
8
- * only once the password matched.
7
+ * refusal for an unknown login, no password, a wrong one and a login past
8
+ * its attempts; `USER_INACTIVE` only once the password matched.
9
9
  */
10
10
  export declare function signIn(context: Context, type: ResolvedType, finish: Finish, input: Input, where: string): Promise<SignInResult<AnyUser>>;
11
11
  //# sourceMappingURL=sign-in.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sign-in.d.ts","sourceRoot":"","sources":["../../../src/auth/users/sign-in.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAElD;;;;GAIG;AACH,wBAAsB,MAAM,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAsDhC"}
1
+ {"version":3,"file":"sign-in.d.ts","sourceRoot":"","sources":["../../../src/auth/users/sign-in.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAElD;;;;GAIG;AACH,wBAAsB,MAAM,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAgEhC"}
@@ -3,7 +3,8 @@ import type { Context } from '../context';
3
3
  import type { AnyTypeApi } from './any-type-api';
4
4
  /**
5
5
  * Everything one user type answers, gathered from its flows: its records,
6
- * its password, its second factor, its sign-in code, its step-up and its e-mails.
6
+ * its password, its second factor, its sign-in code and link, its step-up
7
+ * and its e-mails.
7
8
  */
8
9
  export declare function typeApi(context: Context, type: ResolvedType): AnyTypeApi;
9
10
  //# sourceMappingURL=type-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type-api.d.ts","sourceRoot":"","sources":["../../../src/auth/users/type-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAK1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,UAAU,CAgBxE"}
1
+ {"version":3,"file":"type-api.d.ts","sourceRoot":"","sources":["../../../src/auth/users/type-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,UAAU,CAiBxE"}
@@ -0,0 +1,12 @@
1
+ import type { ResolvedType } from '../config';
2
+ import { type Context } from '../context';
3
+ import type { UserRecord } from '../port/types';
4
+ import type { UserRef, WriteOptions } from '../types';
5
+ import type { Input } from './flow-types';
6
+ /**
7
+ * `update`: the patch written over the stored fields, then — when it changed
8
+ * the e-mail — `user.emailChanged`, carrying the address the write replaced,
9
+ * which nothing keeps once it landed.
10
+ */
11
+ export declare function update(context: Context, type: ResolvedType, user: UserRef, patch: Input, options: WriteOptions | undefined, where: string): Promise<UserRecord>;
12
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/auth/users/update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,YAAY,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C;;;;GAIG;AACH,wBAAsB,MAAM,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,YAAY,GAAG,SAAS,EACjC,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,CAAC,CA0BrB"}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  isSubjectSet2,
3
3
  formatTuple2
4
- } from "./index-j2gd8fry.js";
4
+ } from "./index-hnwggyxs.js";
5
5
 
6
6
  // src/permissions/port/memory.ts
7
7
  function createMemoryRelations2() {
@@ -77,4 +77,4 @@ function copyTuple(tuple) {
77
77
  export { createMemoryRelations2 };
78
78
 
79
79
  //# debugId=0BA3AA406E650E8464756E2164756E21
80
- //# sourceMappingURL=index-km7ffctx.js.map
80
+ //# sourceMappingURL=index-6c9fbtv2.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  StoreConflict2,
3
3
  NotFoundError2
4
- } from "./index-j2gd8fry.js";
4
+ } from "./index-hnwggyxs.js";
5
5
 
6
6
  // src/ids/id.ts
7
7
  var HEX = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
@@ -307,4 +307,4 @@ function createMemoryStores2() {
307
307
  export { mintId2, isId2, mintedAt2, createMemoryStores2 };
308
308
 
309
309
  //# debugId=0777A8A648CFB0FA64756E2164756E21
310
- //# sourceMappingURL=index-rd2rddvv.js.map
310
+ //# sourceMappingURL=index-baazjyvc.js.map
@@ -18,6 +18,7 @@ class JanusError2 extends Error {
18
18
  this.permission = options?.permission;
19
19
  this.maxDepth = options?.maxDepth;
20
20
  this.attemptsLeft = options?.attemptsLeft;
21
+ this.retryAfter = options?.retryAfter;
21
22
  }
22
23
  }
23
24
 
@@ -213,5 +214,5 @@ function parseSubject2(text) {
213
214
 
214
215
  export { JanusError2, UserInvalidError2, CredentialError2, UserInactiveError2, TokenError2, SecondFactorError2, StepUpRequiredError2, InvalidCursorError2, UnsupportedError2, PermissionDepthError2, statusOf2, StoreFailure2, StoreConflict2, NotFoundError2, isSubjectSet2, subjectOf2, setOf2, isSetOf2, formatEntity2, formatSubject2, formatTuple2, parseTuple2, parseSubject2 };
215
216
 
216
- //# debugId=6F0F39FBC3CA3C2C64756E2164756E21
217
- //# sourceMappingURL=index-j2gd8fry.js.map
217
+ //# debugId=241B9AAD2965E64964756E2164756E21
218
+ //# sourceMappingURL=index-hnwggyxs.js.map