@spinajs/authn-orm 0.0.0-stage → 3.0.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 (246) hide show
  1. package/README.md +84 -2
  2. package/lib/cjs/audit/db-audit-sink.d.ts +11 -0
  3. package/lib/cjs/audit/db-audit-sink.d.ts.map +1 -0
  4. package/lib/cjs/audit/db-audit-sink.js +73 -0
  5. package/lib/cjs/audit/db-audit-sink.js.map +1 -0
  6. package/lib/cjs/audit/index.d.ts +2 -0
  7. package/lib/cjs/audit/index.d.ts.map +1 -0
  8. package/lib/cjs/audit/index.js +6 -0
  9. package/lib/cjs/audit/index.js.map +1 -0
  10. package/lib/cjs/identity.d.ts +6 -0
  11. package/lib/cjs/identity.d.ts.map +1 -0
  12. package/lib/cjs/identity.js +27 -0
  13. package/lib/cjs/identity.js.map +1 -0
  14. package/lib/cjs/index.d.ts +10 -0
  15. package/lib/cjs/index.d.ts.map +1 -0
  16. package/lib/cjs/index.js +26 -0
  17. package/lib/cjs/index.js.map +1 -0
  18. package/lib/cjs/links/db-link-store.d.ts +13 -0
  19. package/lib/cjs/links/db-link-store.d.ts.map +1 -0
  20. package/lib/cjs/links/db-link-store.js +88 -0
  21. package/lib/cjs/links/db-link-store.js.map +1 -0
  22. package/lib/cjs/links/index.d.ts +2 -0
  23. package/lib/cjs/links/index.d.ts.map +1 -0
  24. package/lib/cjs/links/index.js +6 -0
  25. package/lib/cjs/links/index.js.map +1 -0
  26. package/lib/cjs/mfa/cipher.d.ts +18 -0
  27. package/lib/cjs/mfa/cipher.d.ts.map +1 -0
  28. package/lib/cjs/mfa/cipher.js +81 -0
  29. package/lib/cjs/mfa/cipher.js.map +1 -0
  30. package/lib/cjs/mfa/db-mfa-enrolments.d.ts +14 -0
  31. package/lib/cjs/mfa/db-mfa-enrolments.d.ts.map +1 -0
  32. package/lib/cjs/mfa/db-mfa-enrolments.js +43 -0
  33. package/lib/cjs/mfa/db-mfa-enrolments.js.map +1 -0
  34. package/lib/cjs/mfa/db-mfa-store.d.ts +51 -0
  35. package/lib/cjs/mfa/db-mfa-store.d.ts.map +1 -0
  36. package/lib/cjs/mfa/db-mfa-store.js +190 -0
  37. package/lib/cjs/mfa/db-mfa-store.js.map +1 -0
  38. package/lib/cjs/mfa/index.d.ts +4 -0
  39. package/lib/cjs/mfa/index.d.ts.map +1 -0
  40. package/lib/cjs/mfa/index.js +20 -0
  41. package/lib/cjs/mfa/index.js.map +1 -0
  42. package/lib/cjs/migrations/AuthnInitial_2026_10_02_00_00_00.d.ts +10 -0
  43. package/lib/cjs/migrations/AuthnInitial_2026_10_02_00_00_00.d.ts.map +1 -0
  44. package/lib/cjs/migrations/AuthnInitial_2026_10_02_00_00_00.js +98 -0
  45. package/lib/cjs/migrations/AuthnInitial_2026_10_02_00_00_00.js.map +1 -0
  46. package/lib/cjs/migrations/index.d.ts +2 -0
  47. package/lib/cjs/migrations/index.d.ts.map +1 -0
  48. package/lib/cjs/migrations/index.js +18 -0
  49. package/lib/cjs/migrations/index.js.map +1 -0
  50. package/lib/cjs/models/AuthnAudit.d.ts +18 -0
  51. package/lib/cjs/models/AuthnAudit.d.ts.map +1 -0
  52. package/lib/cjs/models/AuthnAudit.js +30 -0
  53. package/lib/cjs/models/AuthnAudit.js.map +1 -0
  54. package/lib/cjs/models/AuthnIdentity.d.ts +16 -0
  55. package/lib/cjs/models/AuthnIdentity.d.ts.map +1 -0
  56. package/lib/cjs/models/AuthnIdentity.js +39 -0
  57. package/lib/cjs/models/AuthnIdentity.js.map +1 -0
  58. package/lib/cjs/models/AuthnMfa.d.ts +16 -0
  59. package/lib/cjs/models/AuthnMfa.d.ts.map +1 -0
  60. package/lib/cjs/models/AuthnMfa.js +39 -0
  61. package/lib/cjs/models/AuthnMfa.js.map +1 -0
  62. package/lib/cjs/models/AuthnNonce.d.ts +7 -0
  63. package/lib/cjs/models/AuthnNonce.d.ts.map +1 -0
  64. package/lib/cjs/models/AuthnNonce.js +30 -0
  65. package/lib/cjs/models/AuthnNonce.js.map +1 -0
  66. package/lib/cjs/models/AuthnRecoveryCode.d.ts +10 -0
  67. package/lib/cjs/models/AuthnRecoveryCode.d.ts.map +1 -0
  68. package/lib/cjs/models/AuthnRecoveryCode.js +30 -0
  69. package/lib/cjs/models/AuthnRecoveryCode.js.map +1 -0
  70. package/lib/cjs/models/AuthnSecret.d.ts +13 -0
  71. package/lib/cjs/models/AuthnSecret.d.ts.map +1 -0
  72. package/lib/cjs/models/AuthnSecret.js +38 -0
  73. package/lib/cjs/models/AuthnSecret.js.map +1 -0
  74. package/lib/cjs/models/AuthnThrottle.d.ts +10 -0
  75. package/lib/cjs/models/AuthnThrottle.d.ts.map +1 -0
  76. package/lib/cjs/models/AuthnThrottle.js +38 -0
  77. package/lib/cjs/models/AuthnThrottle.js.map +1 -0
  78. package/lib/cjs/models/index.d.ts +9 -0
  79. package/lib/cjs/models/index.d.ts.map +1 -0
  80. package/lib/cjs/models/index.js +25 -0
  81. package/lib/cjs/models/index.js.map +1 -0
  82. package/lib/cjs/models/time.d.ts +4 -0
  83. package/lib/cjs/models/time.d.ts.map +1 -0
  84. package/lib/cjs/models/time.js +19 -0
  85. package/lib/cjs/models/time.js.map +1 -0
  86. package/lib/cjs/nonces/index.d.ts +2 -0
  87. package/lib/cjs/nonces/index.d.ts.map +1 -0
  88. package/lib/cjs/nonces/index.js +18 -0
  89. package/lib/cjs/nonces/index.js.map +1 -0
  90. package/lib/cjs/nonces/nonce-store.d.ts +11 -0
  91. package/lib/cjs/nonces/nonce-store.d.ts.map +1 -0
  92. package/lib/cjs/nonces/nonce-store.js +77 -0
  93. package/lib/cjs/nonces/nonce-store.js.map +1 -0
  94. package/lib/cjs/package.json +1 -0
  95. package/lib/cjs/secrets/db-secret-store.d.ts +25 -0
  96. package/lib/cjs/secrets/db-secret-store.d.ts.map +1 -0
  97. package/lib/cjs/secrets/db-secret-store.js +99 -0
  98. package/lib/cjs/secrets/db-secret-store.js.map +1 -0
  99. package/lib/cjs/secrets/index.d.ts +2 -0
  100. package/lib/cjs/secrets/index.d.ts.map +1 -0
  101. package/lib/cjs/secrets/index.js +6 -0
  102. package/lib/cjs/secrets/index.js.map +1 -0
  103. package/lib/cjs/support/sql.d.ts +16 -0
  104. package/lib/cjs/support/sql.d.ts.map +1 -0
  105. package/lib/cjs/support/sql.js +50 -0
  106. package/lib/cjs/support/sql.js.map +1 -0
  107. package/lib/cjs/support/values.d.ts +7 -0
  108. package/lib/cjs/support/values.d.ts.map +1 -0
  109. package/lib/cjs/support/values.js +8 -0
  110. package/lib/cjs/support/values.js.map +1 -0
  111. package/lib/cjs/throttle/db-throttle-store.d.ts +79 -0
  112. package/lib/cjs/throttle/db-throttle-store.d.ts.map +1 -0
  113. package/lib/cjs/throttle/db-throttle-store.js +231 -0
  114. package/lib/cjs/throttle/db-throttle-store.js.map +1 -0
  115. package/lib/cjs/throttle/db-throttle.d.ts +77 -0
  116. package/lib/cjs/throttle/db-throttle.d.ts.map +1 -0
  117. package/lib/cjs/throttle/db-throttle.js +192 -0
  118. package/lib/cjs/throttle/db-throttle.js.map +1 -0
  119. package/lib/cjs/throttle/index.d.ts +6 -0
  120. package/lib/cjs/throttle/index.d.ts.map +1 -0
  121. package/lib/cjs/throttle/index.js +8 -0
  122. package/lib/cjs/throttle/index.js.map +1 -0
  123. package/lib/mjs/audit/db-audit-sink.d.ts +11 -0
  124. package/lib/mjs/audit/db-audit-sink.d.ts.map +1 -0
  125. package/lib/mjs/audit/db-audit-sink.js +70 -0
  126. package/lib/mjs/audit/db-audit-sink.js.map +1 -0
  127. package/lib/mjs/audit/index.d.ts +2 -0
  128. package/lib/mjs/audit/index.d.ts.map +1 -0
  129. package/lib/mjs/audit/index.js +2 -0
  130. package/lib/mjs/audit/index.js.map +1 -0
  131. package/lib/mjs/identity.d.ts +6 -0
  132. package/lib/mjs/identity.d.ts.map +1 -0
  133. package/lib/mjs/identity.js +23 -0
  134. package/lib/mjs/identity.js.map +1 -0
  135. package/lib/mjs/index.d.ts +10 -0
  136. package/lib/mjs/index.d.ts.map +1 -0
  137. package/lib/mjs/index.js +10 -0
  138. package/lib/mjs/index.js.map +1 -0
  139. package/lib/mjs/links/db-link-store.d.ts +13 -0
  140. package/lib/mjs/links/db-link-store.d.ts.map +1 -0
  141. package/lib/mjs/links/db-link-store.js +85 -0
  142. package/lib/mjs/links/db-link-store.js.map +1 -0
  143. package/lib/mjs/links/index.d.ts +2 -0
  144. package/lib/mjs/links/index.d.ts.map +1 -0
  145. package/lib/mjs/links/index.js +2 -0
  146. package/lib/mjs/links/index.js.map +1 -0
  147. package/lib/mjs/mfa/cipher.d.ts +18 -0
  148. package/lib/mjs/mfa/cipher.d.ts.map +1 -0
  149. package/lib/mjs/mfa/cipher.js +76 -0
  150. package/lib/mjs/mfa/cipher.js.map +1 -0
  151. package/lib/mjs/mfa/db-mfa-enrolments.d.ts +14 -0
  152. package/lib/mjs/mfa/db-mfa-enrolments.d.ts.map +1 -0
  153. package/lib/mjs/mfa/db-mfa-enrolments.js +40 -0
  154. package/lib/mjs/mfa/db-mfa-enrolments.js.map +1 -0
  155. package/lib/mjs/mfa/db-mfa-store.d.ts +51 -0
  156. package/lib/mjs/mfa/db-mfa-store.d.ts.map +1 -0
  157. package/lib/mjs/mfa/db-mfa-store.js +187 -0
  158. package/lib/mjs/mfa/db-mfa-store.js.map +1 -0
  159. package/lib/mjs/mfa/index.d.ts +4 -0
  160. package/lib/mjs/mfa/index.d.ts.map +1 -0
  161. package/lib/mjs/mfa/index.js +4 -0
  162. package/lib/mjs/mfa/index.js.map +1 -0
  163. package/lib/mjs/migrations/AuthnInitial_2026_10_02_00_00_00.d.ts +10 -0
  164. package/lib/mjs/migrations/AuthnInitial_2026_10_02_00_00_00.d.ts.map +1 -0
  165. package/lib/mjs/migrations/AuthnInitial_2026_10_02_00_00_00.js +95 -0
  166. package/lib/mjs/migrations/AuthnInitial_2026_10_02_00_00_00.js.map +1 -0
  167. package/lib/mjs/migrations/index.d.ts +2 -0
  168. package/lib/mjs/migrations/index.d.ts.map +1 -0
  169. package/lib/mjs/migrations/index.js +2 -0
  170. package/lib/mjs/migrations/index.js.map +1 -0
  171. package/lib/mjs/models/AuthnAudit.d.ts +18 -0
  172. package/lib/mjs/models/AuthnAudit.d.ts.map +1 -0
  173. package/lib/mjs/models/AuthnAudit.js +27 -0
  174. package/lib/mjs/models/AuthnAudit.js.map +1 -0
  175. package/lib/mjs/models/AuthnIdentity.d.ts +16 -0
  176. package/lib/mjs/models/AuthnIdentity.d.ts.map +1 -0
  177. package/lib/mjs/models/AuthnIdentity.js +36 -0
  178. package/lib/mjs/models/AuthnIdentity.js.map +1 -0
  179. package/lib/mjs/models/AuthnMfa.d.ts +16 -0
  180. package/lib/mjs/models/AuthnMfa.d.ts.map +1 -0
  181. package/lib/mjs/models/AuthnMfa.js +36 -0
  182. package/lib/mjs/models/AuthnMfa.js.map +1 -0
  183. package/lib/mjs/models/AuthnNonce.d.ts +7 -0
  184. package/lib/mjs/models/AuthnNonce.d.ts.map +1 -0
  185. package/lib/mjs/models/AuthnNonce.js +27 -0
  186. package/lib/mjs/models/AuthnNonce.js.map +1 -0
  187. package/lib/mjs/models/AuthnRecoveryCode.d.ts +10 -0
  188. package/lib/mjs/models/AuthnRecoveryCode.d.ts.map +1 -0
  189. package/lib/mjs/models/AuthnRecoveryCode.js +27 -0
  190. package/lib/mjs/models/AuthnRecoveryCode.js.map +1 -0
  191. package/lib/mjs/models/AuthnSecret.d.ts +13 -0
  192. package/lib/mjs/models/AuthnSecret.d.ts.map +1 -0
  193. package/lib/mjs/models/AuthnSecret.js +35 -0
  194. package/lib/mjs/models/AuthnSecret.js.map +1 -0
  195. package/lib/mjs/models/AuthnThrottle.d.ts +10 -0
  196. package/lib/mjs/models/AuthnThrottle.d.ts.map +1 -0
  197. package/lib/mjs/models/AuthnThrottle.js +35 -0
  198. package/lib/mjs/models/AuthnThrottle.js.map +1 -0
  199. package/lib/mjs/models/index.d.ts +9 -0
  200. package/lib/mjs/models/index.d.ts.map +1 -0
  201. package/lib/mjs/models/index.js +9 -0
  202. package/lib/mjs/models/index.js.map +1 -0
  203. package/lib/mjs/models/time.d.ts +4 -0
  204. package/lib/mjs/models/time.d.ts.map +1 -0
  205. package/lib/mjs/models/time.js +16 -0
  206. package/lib/mjs/models/time.js.map +1 -0
  207. package/lib/mjs/nonces/index.d.ts +2 -0
  208. package/lib/mjs/nonces/index.d.ts.map +1 -0
  209. package/lib/mjs/nonces/index.js +2 -0
  210. package/lib/mjs/nonces/index.js.map +1 -0
  211. package/lib/mjs/nonces/nonce-store.d.ts +11 -0
  212. package/lib/mjs/nonces/nonce-store.d.ts.map +1 -0
  213. package/lib/mjs/nonces/nonce-store.js +72 -0
  214. package/lib/mjs/nonces/nonce-store.js.map +1 -0
  215. package/lib/mjs/package.json +1 -0
  216. package/lib/mjs/secrets/db-secret-store.d.ts +25 -0
  217. package/lib/mjs/secrets/db-secret-store.d.ts.map +1 -0
  218. package/lib/mjs/secrets/db-secret-store.js +96 -0
  219. package/lib/mjs/secrets/db-secret-store.js.map +1 -0
  220. package/lib/mjs/secrets/index.d.ts +2 -0
  221. package/lib/mjs/secrets/index.d.ts.map +1 -0
  222. package/lib/mjs/secrets/index.js +2 -0
  223. package/lib/mjs/secrets/index.js.map +1 -0
  224. package/lib/mjs/support/sql.d.ts +16 -0
  225. package/lib/mjs/support/sql.d.ts.map +1 -0
  226. package/lib/mjs/support/sql.js +41 -0
  227. package/lib/mjs/support/sql.js.map +1 -0
  228. package/lib/mjs/support/values.d.ts +7 -0
  229. package/lib/mjs/support/values.d.ts.map +1 -0
  230. package/lib/mjs/support/values.js +5 -0
  231. package/lib/mjs/support/values.js.map +1 -0
  232. package/lib/mjs/throttle/db-throttle-store.d.ts +79 -0
  233. package/lib/mjs/throttle/db-throttle-store.d.ts.map +1 -0
  234. package/lib/mjs/throttle/db-throttle-store.js +227 -0
  235. package/lib/mjs/throttle/db-throttle-store.js.map +1 -0
  236. package/lib/mjs/throttle/db-throttle.d.ts +77 -0
  237. package/lib/mjs/throttle/db-throttle.d.ts.map +1 -0
  238. package/lib/mjs/throttle/db-throttle.js +189 -0
  239. package/lib/mjs/throttle/db-throttle.js.map +1 -0
  240. package/lib/mjs/throttle/index.d.ts +6 -0
  241. package/lib/mjs/throttle/index.d.ts.map +1 -0
  242. package/lib/mjs/throttle/index.js +3 -0
  243. package/lib/mjs/throttle/index.js.map +1 -0
  244. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  245. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  246. package/package.json +89 -4
@@ -0,0 +1,51 @@
1
+ import type { IdentityRef } from '@spinajs/authn/contracts';
2
+ /** One MFA step of an identity as stored. */
3
+ export interface MfaRecord {
4
+ /** Cipher text exactly as `putPending` was given it; this store never encrypts or decrypts. */
5
+ readonly secretEnc: string;
6
+ readonly keyId: string;
7
+ readonly confirmedAt: Date | null;
8
+ /** The last accepted time step. */
9
+ readonly lastStep: number | null;
10
+ readonly createdAt: Date;
11
+ }
12
+ /**
13
+ * `authn_mfa` and `authn_recovery_code` for MFA steps (authn-totp, N5). Rows are keyed by `identityKey(id)` and
14
+ * the step name. The store keeps cipher text and its key id only (SR-09); recovery codes are stored as hex SHA-256,
15
+ * never raw, and callers normalise a code before passing it. Replay and single use are decided in SQL (SR-15, D10).
16
+ *
17
+ * Without transactions (the sqlite driver shares one handle) `replaceRecoveryCodes` deletes and then inserts: two
18
+ * parallel calls for one identity may leave both sets.
19
+ */
20
+ export declare class DbMfaStore {
21
+ get(id: IdentityRef, step: string): Promise<MfaRecord | null>;
22
+ /**
23
+ * Stores the step unconfirmed, with no accepted time step and created now, replacing a pending one. A confirmed
24
+ * step is never overwritten: false means a confirmed row exists and nothing changed. The
25
+ * replacing update is conditional on `confirmed_at IS NULL`, so a confirmation that lands first always wins.
26
+ */
27
+ putPending(id: IdentityRef, step: string, secretEnc: string, keyId: string): Promise<boolean>;
28
+ /**
29
+ * Sets `confirmed_at` (default now); true when the step exists. With `expectedSecretEnc`, only an unconfirmed step
30
+ * holding that cipher text is confirmed, so the answer is true for exactly the call that confirmed it.
31
+ */
32
+ confirm(id: IdentityRef, step: string, at?: Date, expectedSecretEnc?: string): Promise<boolean>;
33
+ /** True once per time step, and never for a step at or below the last accepted one (SR-15); false when the step does not exist. */
34
+ acceptStep(id: IdentityRef, step: string, timeStep: number): Promise<boolean>;
35
+ remove(id: IdentityRef, step: string): Promise<void>;
36
+ /** The names of the identity's confirmed steps. */
37
+ confirmedSteps(id: IdentityRef): Promise<string[]>;
38
+ /**
39
+ * Each step name with a confirmed row of any identity, once. Deduplicated here, not with DISTINCT, which folds
40
+ * `totp` and `TOTP` into one under a case-blind collation (MySQL's default); one row per confirmed enrolment.
41
+ */
42
+ confirmedStepNames(): Promise<string[]>;
43
+ /** Deletes the identity's codes, then stores the SHA-256 of each new one. Empty or repeated codes throw. */
44
+ replaceRecoveryCodes(id: IdentityRef, rawCodes: readonly string[]): Promise<void>;
45
+ /** Spends the code in one conditional update; true for exactly one caller. */
46
+ redeemRecoveryCode(id: IdentityRef, raw: string): Promise<boolean>;
47
+ /** Unused codes. */
48
+ countRecoveryCodes(id: IdentityRef): Promise<number>;
49
+ removeRecoveryCodes(id: IdentityRef): Promise<void>;
50
+ }
51
+ //# sourceMappingURL=db-mfa-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-mfa-store.d.ts","sourceRoot":"","sources":["../../../src/mfa/db-mfa-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAmB5D,6CAA6C;AAC7C,MAAM,WAAW,SAAS;IACxB,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IAClC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1B;AAkBD;;;;;;;GAOG;AACH,qBAEa,UAAU;IACR,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAczE;IAED;;;;OAIG;IACU,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqBzG;IAED;;;OAGG;IACU,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAE,IAAiB,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAavH;IAED,mIAAmI;IACtH,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUzF;IAEY,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhE;IAED,mDAAmD;IACtC,cAAc,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAK9D;IAED;;;OAGG;IACU,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAInD;IAED,4GAA4G;IAC/F,oBAAoB,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAU7F;IAED,8EAA8E;IACjE,kBAAkB,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU9E;IAED,oBAAoB;IACP,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAKhE;IAEY,mBAAmB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/D;CACF"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DbMfaStore = void 0;
10
+ const node_crypto_1 = require("node:crypto");
11
+ const di_1 = require("@spinajs/di");
12
+ const exceptions_1 = require("@spinajs/exceptions");
13
+ const orm_1 = require("@spinajs/orm");
14
+ const util_1 = require("@spinajs/util");
15
+ const identity_js_1 = require("../identity.js");
16
+ const AuthnMfa_js_1 = require("../models/AuthnMfa.js");
17
+ const AuthnRecoveryCode_js_1 = require("../models/AuthnRecoveryCode.js");
18
+ const sql_js_1 = require("../support/sql.js");
19
+ const values_js_1 = require("../support/values.js");
20
+ /** Each retry means a parallel `remove` deleted the row between this call's insert and update. */
21
+ const MAX_TRIES = 8;
22
+ /** As DbSecretStore: longer input is refused before hashing. */
23
+ const RAW_MAX = 1024;
24
+ const stepName = (step) => (0, sql_js_1.checkedText)(step, 32, 'DbMfaStore: step');
25
+ function lastStepOf(value) {
26
+ if (value === null || value === undefined)
27
+ return null;
28
+ const n = typeof value === 'number' ? value : Number(String(value));
29
+ if (!Number.isSafeInteger(n))
30
+ throw new exceptions_1.UnexpectedServerError(`DbMfaStore: last_step ${String(value)} is not a safe integer`);
31
+ return n;
32
+ }
33
+ const confirmed = (r) => r.confirmed_at !== null && r.confirmed_at !== undefined;
34
+ /** The columns `putPending` writes: unconfirmed, no accepted time step. */
35
+ function pending(secretEnc, keyId, createdAt) {
36
+ return (0, values_js_1.columnValues)({ secret_enc: secretEnc, secret_hash: (0, sql_js_1.sha256hex)(secretEnc), key_id: keyId, confirmed_at: null, last_step: null, created_at: createdAt });
37
+ }
38
+ /**
39
+ * `authn_mfa` and `authn_recovery_code` for MFA steps (authn-totp, N5). Rows are keyed by `identityKey(id)` and
40
+ * the step name. The store keeps cipher text and its key id only (SR-09); recovery codes are stored as hex SHA-256,
41
+ * never raw, and callers normalise a code before passing it. Replay and single use are decided in SQL (SR-15, D10).
42
+ *
43
+ * Without transactions (the sqlite driver shares one handle) `replaceRecoveryCodes` deletes and then inserts: two
44
+ * parallel calls for one identity may leave both sets.
45
+ */
46
+ let DbMfaStore = class DbMfaStore {
47
+ async get(id, step) {
48
+ const identity = (0, identity_js_1.identityKey)(id);
49
+ const name = stepName(step);
50
+ await (0, orm_1.ormReady)();
51
+ const rows = await AuthnMfa_js_1.AuthnMfa.query().columns(['identity', 'step', 'secret_enc', 'key_id', 'last_step', 'confirmed_at', 'created_at']).where('identity', identity).where('step', name);
52
+ const r = rows.find((x) => x.identity === identity && x.step === name);
53
+ if (!r)
54
+ return null;
55
+ return {
56
+ secretEnc: r.secret_enc,
57
+ keyId: r.key_id,
58
+ confirmedAt: r.confirmed_at ? (0, sql_js_1.dateOf)(r.confirmed_at) : null,
59
+ lastStep: lastStepOf(r.last_step),
60
+ createdAt: (0, sql_js_1.dateOf)(r.created_at),
61
+ };
62
+ }
63
+ /**
64
+ * Stores the step unconfirmed, with no accepted time step and created now, replacing a pending one. A confirmed
65
+ * step is never overwritten: false means a confirmed row exists and nothing changed. The
66
+ * replacing update is conditional on `confirmed_at IS NULL`, so a confirmation that lands first always wins.
67
+ */
68
+ async putPending(id, step, secretEnc, keyId) {
69
+ const identity = (0, identity_js_1.identityKey)(id);
70
+ const name = stepName(step);
71
+ (0, sql_js_1.checkedText)(secretEnc, Number.MAX_SAFE_INTEGER, 'DbMfaStore: secretEnc');
72
+ (0, sql_js_1.checkedText)(keyId, 32, 'DbMfaStore: keyId');
73
+ const ms = (0, sql_js_1.checkedMs)(new Date(), 'DbMfaStore.putPending: the clock');
74
+ await (0, orm_1.ormReady)();
75
+ const fields = pending(secretEnc, keyId, (0, sql_js_1.instant)(ms));
76
+ for (let i = 0; i < MAX_TRIES; i++) {
77
+ try {
78
+ await AuthnMfa_js_1.AuthnMfa.insert({ identity, step: name, ...fields });
79
+ return true;
80
+ }
81
+ catch (err) {
82
+ if (!(err instanceof orm_1.UniqueViolation))
83
+ throw err;
84
+ }
85
+ if ((await AuthnMfa_js_1.AuthnMfa.update(fields).where('identity', identity).where('step', name).whereNull('confirmed_at')).RowsAffected === 1)
86
+ return true;
87
+ // No row updated: either it is confirmed, or a parallel remove deleted it and the insert is worth retrying.
88
+ if ((await this.get(id, name))?.confirmedAt)
89
+ return false;
90
+ }
91
+ throw new exceptions_1.UnexpectedServerError(`DbMfaStore.putPending: the ${name} row kept changing under this call`);
92
+ }
93
+ /**
94
+ * Sets `confirmed_at` (default now); true when the step exists. With `expectedSecretEnc`, only an unconfirmed step
95
+ * holding that cipher text is confirmed, so the answer is true for exactly the call that confirmed it.
96
+ */
97
+ async confirm(id, step, at = new Date(), expectedSecretEnc) {
98
+ const identity = (0, identity_js_1.identityKey)(id);
99
+ const name = stepName(step);
100
+ const ms = (0, sql_js_1.checkedMs)(at, 'DbMfaStore.confirm: at');
101
+ if (expectedSecretEnc !== undefined)
102
+ (0, sql_js_1.checkedText)(expectedSecretEnc, Number.MAX_SAFE_INTEGER, 'DbMfaStore: expectedSecretEnc');
103
+ await (0, orm_1.ormReady)();
104
+ const q = AuthnMfa_js_1.AuthnMfa.update({ confirmed_at: (0, sql_js_1.instant)(ms) })
105
+ .where('identity', identity)
106
+ .where('step', name);
107
+ if (expectedSecretEnc !== undefined) {
108
+ q.whereNull('confirmed_at').where('secret_hash', (0, sql_js_1.sha256hex)(expectedSecretEnc));
109
+ }
110
+ return (await q).RowsAffected === 1;
111
+ }
112
+ /** True once per time step, and never for a step at or below the last accepted one (SR-15); false when the step does not exist. */
113
+ async acceptStep(id, step, timeStep) {
114
+ const identity = (0, identity_js_1.identityKey)(id);
115
+ const name = stepName(step);
116
+ (0, util_1._check_arg)((0, util_1._is_number)((0, util_1._integer)(), (0, util_1._between)(0, Number.MAX_SAFE_INTEGER)))(timeStep, 'timeStep');
117
+ await (0, orm_1.ormReady)();
118
+ const older = function () {
119
+ this.whereNull('last_step');
120
+ this.orWhere('last_step', '<', timeStep);
121
+ };
122
+ return (await AuthnMfa_js_1.AuthnMfa.update({ last_step: timeStep }).where('identity', identity).where('step', name).where(older)).RowsAffected === 1;
123
+ }
124
+ async remove(id, step) {
125
+ const identity = (0, identity_js_1.identityKey)(id);
126
+ const name = stepName(step);
127
+ await (0, orm_1.ormReady)();
128
+ await AuthnMfa_js_1.AuthnMfa.destroy().where('identity', identity).where('step', name);
129
+ }
130
+ /** The names of the identity's confirmed steps. */
131
+ async confirmedSteps(id) {
132
+ const identity = (0, identity_js_1.identityKey)(id);
133
+ await (0, orm_1.ormReady)();
134
+ const rows = await AuthnMfa_js_1.AuthnMfa.query().columns(['identity', 'step', 'confirmed_at']).where('identity', identity).whereNotNull('confirmed_at');
135
+ return rows.filter((r) => r.identity === identity && confirmed(r)).map((r) => r.step);
136
+ }
137
+ /**
138
+ * Each step name with a confirmed row of any identity, once. Deduplicated here, not with DISTINCT, which folds
139
+ * `totp` and `TOTP` into one under a case-blind collation (MySQL's default); one row per confirmed enrolment.
140
+ */
141
+ async confirmedStepNames() {
142
+ await (0, orm_1.ormReady)();
143
+ const rows = await AuthnMfa_js_1.AuthnMfa.query().columns(['step', 'confirmed_at']).whereNotNull('confirmed_at');
144
+ return [...new Set(rows.filter(confirmed).map((r) => r.step))];
145
+ }
146
+ /** Deletes the identity's codes, then stores the SHA-256 of each new one. Empty or repeated codes throw. */
147
+ async replaceRecoveryCodes(id, rawCodes) {
148
+ const identity = (0, identity_js_1.identityKey)(id);
149
+ (0, util_1._check_arg)((0, util_1._is_array)())(rawCodes, 'rawCodes');
150
+ const hashes = rawCodes.map((code) => (0, sql_js_1.sha256hex)((0, sql_js_1.checkedText)(code, Number.MAX_SAFE_INTEGER, 'DbMfaStore: a recovery code')));
151
+ if (new Set(hashes).size !== hashes.length)
152
+ throw new exceptions_1.InvalidArgument('DbMfaStore.replaceRecoveryCodes: the codes repeat');
153
+ await (0, orm_1.ormReady)();
154
+ await AuthnRecoveryCode_js_1.AuthnRecoveryCode.destroy().where('identity', identity);
155
+ if (hashes.length === 0)
156
+ return;
157
+ await AuthnRecoveryCode_js_1.AuthnRecoveryCode.insert(hashes.map((code_hash) => (0, values_js_1.columnValues)({ id: (0, node_crypto_1.randomUUID)(), identity, code_hash, used_at: null })));
158
+ }
159
+ /** Spends the code in one conditional update; true for exactly one caller. */
160
+ async redeemRecoveryCode(id, raw) {
161
+ const identity = (0, identity_js_1.identityKey)(id);
162
+ if (!(0, util_1._try_check_arg)((0, util_1._is_string)((0, util_1._non_empty)(), (0, util_1._max_length)(RAW_MAX)))(raw, 'raw')[0])
163
+ return false;
164
+ const ms = (0, sql_js_1.checkedMs)(new Date(), 'DbMfaStore.redeemRecoveryCode: the clock');
165
+ await (0, orm_1.ormReady)();
166
+ const r = await AuthnRecoveryCode_js_1.AuthnRecoveryCode.update({ used_at: (0, sql_js_1.instant)(ms) })
167
+ .where('identity', identity)
168
+ .where('code_hash', (0, sql_js_1.sha256hex)(raw))
169
+ .whereNull('used_at');
170
+ return r.RowsAffected > 0;
171
+ }
172
+ /** Unused codes. */
173
+ async countRecoveryCodes(id) {
174
+ const identity = (0, identity_js_1.identityKey)(id);
175
+ await (0, orm_1.ormReady)();
176
+ const rows = await AuthnRecoveryCode_js_1.AuthnRecoveryCode.query().columns(['identity']).where('identity', identity).whereNull('used_at');
177
+ return rows.filter((r) => r.identity === identity).length;
178
+ }
179
+ async removeRecoveryCodes(id) {
180
+ const identity = (0, identity_js_1.identityKey)(id);
181
+ await (0, orm_1.ormReady)();
182
+ await AuthnRecoveryCode_js_1.AuthnRecoveryCode.destroy().where('identity', identity);
183
+ }
184
+ };
185
+ exports.DbMfaStore = DbMfaStore;
186
+ exports.DbMfaStore = DbMfaStore = __decorate([
187
+ (0, di_1.PerChildInstance)(),
188
+ (0, di_1.Injectable)()
189
+ ], DbMfaStore);
190
+ //# sourceMappingURL=db-mfa-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-mfa-store.js","sourceRoot":"","sources":["../../../src/mfa/db-mfa-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './db-mfa-store.js';
2
+ export * from './db-mfa-enrolments.js';
3
+ export * from './cipher.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./db-mfa-store.js"), exports);
18
+ __exportStar(require("./db-mfa-enrolments.js"), exports);
19
+ __exportStar(require("./cipher.js"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,yDAAuC;AACvC,8CAA4B"}
@@ -0,0 +1,10 @@
1
+ import { OrmDriver, OrmMigration } from '@spinajs/orm';
2
+ /**
3
+ * The authn-orm tables of design §22.16, plus `authn_recovery_code_owner`. The schema builder has no `char`
4
+ * type, so the `char(64)` hash columns are `varchar(64)`.
5
+ */
6
+ export declare class AuthnInitial_2026_10_02_00_00_00 extends OrmMigration {
7
+ up(connection: OrmDriver): Promise<void>;
8
+ down(connection: OrmDriver): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=AuthnInitial_2026_10_02_00_00_00.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnInitial_2026_10_02_00_00_00.d.ts","sourceRoot":"","sources":["../../../src/migrations/AuthnInitial_2026_10_02_00_00_00.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIlE;;;GAGG;AACH,qBACa,gCAAiC,SAAQ,YAAY;IACnD,EAAE,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EpD;IAEY,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAItD;CACF"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.AuthnInitial_2026_10_02_00_00_00 = void 0;
10
+ const orm_1 = require("@spinajs/orm");
11
+ const TABLES = ['authn_identity', 'authn_throttle', 'authn_audit', 'authn_secret', 'authn_mfa', 'authn_recovery_code', 'authn_nonce'];
12
+ /**
13
+ * The authn-orm tables of design §22.16, plus `authn_recovery_code_owner`. The schema builder has no `char`
14
+ * type, so the `char(64)` hash columns are `varchar(64)`.
15
+ */
16
+ let AuthnInitial_2026_10_02_00_00_00 = class AuthnInitial_2026_10_02_00_00_00 extends orm_1.OrmMigration {
17
+ async up(connection) {
18
+ await connection.schema().createTable('authn_identity', (table) => {
19
+ table.string('id', 36).notNull().primaryKey();
20
+ table.string('identity_type', 16).notNull();
21
+ table.string('identity_id', 64).notNull();
22
+ table.string('provider', 128).notNull();
23
+ table.string('subject', 255).notNull();
24
+ table.string('email', 255);
25
+ table.boolean('email_verified').notNull().default().value(0);
26
+ table.text('attributes');
27
+ table.dateTime('linked_at').notNull();
28
+ table.dateTime('last_used_at');
29
+ });
30
+ await connection.index().unique().table('authn_identity').name('authn_identity_subject').columns(['provider', 'subject']);
31
+ await connection.index().table('authn_identity').name('authn_identity_owner').columns(['identity_type', 'identity_id']);
32
+ await connection.schema().createTable('authn_throttle', (table) => {
33
+ table.string('k', 255).notNull().primaryKey();
34
+ table.int('attempts').notNull();
35
+ table.dateTime('last_attempt_at').notNull();
36
+ table.dateTime('next_allowed_at').notNull();
37
+ table.dateTime('updated_at').notNull();
38
+ });
39
+ await connection.schema().createTable('authn_audit', (table) => {
40
+ table.string('id', 36).notNull().primaryKey();
41
+ table.dateTime('at').notNull();
42
+ table.string('type', 32).notNull();
43
+ table.string('outcome', 8).notNull();
44
+ table.string('identity', 100);
45
+ table.string('actor', 100);
46
+ table.string('strategy', 64);
47
+ table.string('reason', 64);
48
+ table.string('ip', 64);
49
+ table.string('user_agent', 255);
50
+ table.string('session', 64);
51
+ table.text('data');
52
+ });
53
+ await connection.index().table('authn_audit').name('authn_audit_at').columns(['at']);
54
+ await connection.index().table('authn_audit').name('authn_audit_identity').columns(['identity', 'at']);
55
+ await connection.schema().createTable('authn_secret', (table) => {
56
+ table.string('id', 36).notNull().primaryKey();
57
+ table.string('identity', 100).notNull();
58
+ table.string('purpose', 32).notNull();
59
+ table.string('secret_hash', 64).notNull();
60
+ table.dateTime('expires_at').notNull();
61
+ table.dateTime('used_at');
62
+ table.dateTime('created_at').notNull();
63
+ });
64
+ await connection.index().unique().table('authn_secret').name('authn_secret_hash').columns(['secret_hash']);
65
+ await connection.index().table('authn_secret').name('authn_secret_owner').columns(['identity', 'purpose']);
66
+ await connection.schema().createTable('authn_mfa', (table) => {
67
+ table.string('identity', 100).notNull().primaryKey();
68
+ table.string('step', 32).notNull().primaryKey();
69
+ table.text('secret_enc').notNull();
70
+ table.string('secret_hash', 64).notNull();
71
+ table.string('key_id', 32).notNull();
72
+ table.dateTime('confirmed_at');
73
+ table.bigint('last_step');
74
+ table.dateTime('created_at').notNull();
75
+ });
76
+ await connection.schema().createTable('authn_recovery_code', (table) => {
77
+ table.string('id', 36).notNull().primaryKey();
78
+ table.string('identity', 100).notNull();
79
+ table.string('code_hash', 64).notNull();
80
+ table.dateTime('used_at');
81
+ });
82
+ await connection.index().table('authn_recovery_code').name('authn_recovery_code_owner').columns(['identity']);
83
+ await connection.schema().createTable('authn_nonce', (table) => {
84
+ table.string('k', 160).notNull().primaryKey();
85
+ table.dateTime('expires_at').notNull();
86
+ });
87
+ }
88
+ async down(connection) {
89
+ for (const table of [...TABLES].reverse()) {
90
+ await connection.schema().dropTable(table);
91
+ }
92
+ }
93
+ };
94
+ exports.AuthnInitial_2026_10_02_00_00_00 = AuthnInitial_2026_10_02_00_00_00;
95
+ exports.AuthnInitial_2026_10_02_00_00_00 = AuthnInitial_2026_10_02_00_00_00 = __decorate([
96
+ (0, orm_1.Migration)('default')
97
+ ], AuthnInitial_2026_10_02_00_00_00);
98
+ //# sourceMappingURL=AuthnInitial_2026_10_02_00_00_00.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnInitial_2026_10_02_00_00_00.js","sourceRoot":"","sources":["../../../src/migrations/AuthnInitial_2026_10_02_00_00_00.ts"],"names":[],"mappings":";;;;;;;;;AAAA,sCAAkE;AAElE,MAAM,MAAM,GAAG,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,qBAAqB,EAAE,aAAa,CAAC,CAAC;AAEtI;;;GAGG;AAEI,IAAM,gCAAgC,GAAtC,MAAM,gCAAiC,SAAQ,kBAAY;IACzD,KAAK,CAAC,EAAE,CAAC,UAAqB;QACnC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;YAChE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YAC5C,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1C,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACvC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC3B,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;YACtC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1H,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;QAExH,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;YAChE,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;YAChC,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC;YAC5C,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC;YAC5C,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7D,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YAC/B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YACrC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YAC9B,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAC7B,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACvB,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YAChC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACrF,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;QAEvG,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9D,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACtC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1C,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;YACvC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC1B,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;QAC3G,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QAE3G,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3D,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YACrD,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1C,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACrC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;YAC/B,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC1B,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE;YACrE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAE9G,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7D,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,UAAqB;QACrC,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YAC1C,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;CACF,CAAA;;2CApFY,gCAAgC;IAD5C,IAAA,eAAS,EAAC,SAAS,CAAC;GACR,gCAAgC,CAoF5C"}
@@ -0,0 +1,2 @@
1
+ export * from './AuthnInitial_2026_10_02_00_00_00.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,cAAc,uCAAuC,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./AuthnInitial_2026_10_02_00_00_00.js"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/migrations/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wEAAsD"}
@@ -0,0 +1,18 @@
1
+ import { ModelBase } from '@spinajs/orm';
2
+ import { DateTime } from 'luxon';
3
+ export declare class AuthnAudit extends ModelBase<AuthnAudit> {
4
+ id: string;
5
+ at: DateTime;
6
+ type: string;
7
+ outcome: string;
8
+ identity?: string | null;
9
+ actor?: string | null;
10
+ strategy?: string | null;
11
+ reason?: string | null;
12
+ ip?: string | null;
13
+ user_agent?: string | null;
14
+ session?: string | null;
15
+ /** JSON text. */
16
+ data?: string | null;
17
+ }
18
+ //# sourceMappingURL=AuthnAudit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnAudit.d.ts","sourceRoot":"","sources":["../../../src/models/AuthnAudit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,SAAS,EAAW,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,qBAEa,UAAW,SAAQ,SAAS,CAAC,UAAU,CAAC;IAE5C,EAAE,EAAE,MAAM,CAAC;IAGX,EAAE,EAAE,QAAQ,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,OAAO,EAAE,MAAM,CAAC;IAEhB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B,iBAAiB;IACV,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AuthnAudit = void 0;
13
+ const orm_1 = require("@spinajs/orm");
14
+ const luxon_1 = require("luxon");
15
+ let AuthnAudit = class AuthnAudit extends orm_1.ModelBase {
16
+ };
17
+ exports.AuthnAudit = AuthnAudit;
18
+ __decorate([
19
+ (0, orm_1.Primary)({ generated: 'assigned' }),
20
+ __metadata("design:type", String)
21
+ ], AuthnAudit.prototype, "id", void 0);
22
+ __decorate([
23
+ (0, orm_1.DateTime)(),
24
+ __metadata("design:type", luxon_1.DateTime)
25
+ ], AuthnAudit.prototype, "at", void 0);
26
+ exports.AuthnAudit = AuthnAudit = __decorate([
27
+ (0, orm_1.Connection)('default'),
28
+ (0, orm_1.Model)('authn_audit')
29
+ ], AuthnAudit);
30
+ //# sourceMappingURL=AuthnAudit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnAudit.js","sourceRoot":"","sources":["../../../src/models/AuthnAudit.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAAqF;AACrF,iCAAiC;AAI1B,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,eAAqB;CA2BpD,CAAA;;AAzBQ;IADN,IAAA,aAAO,EAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;;sCACjB;AAGX;IADN,IAAA,cAAE,GAAE;8BACM,gBAAQ;sCAAC;qBALT,UAAU;IAFtB,IAAA,gBAAU,EAAC,SAAS,CAAC;IACrB,IAAA,WAAK,EAAC,aAAa,CAAC;GACR,UAAU,CA2BtB"}
@@ -0,0 +1,16 @@
1
+ import { ModelBase } from '@spinajs/orm';
2
+ import { DateTime } from 'luxon';
3
+ /** A link from an external subject to an identity (design §22.16). */
4
+ export declare class AuthnIdentity extends ModelBase<AuthnIdentity> {
5
+ id: string;
6
+ identity_type: string;
7
+ identity_id: string;
8
+ provider: string;
9
+ subject: string;
10
+ email?: string | null;
11
+ email_verified: boolean;
12
+ attributes?: string | null;
13
+ linked_at: DateTime;
14
+ last_used_at?: DateTime;
15
+ }
16
+ //# sourceMappingURL=AuthnIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnIdentity.d.ts","sourceRoot":"","sources":["../../../src/models/AuthnIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,SAAS,EAAW,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,sEAAsE;AACtE,qBAEa,aAAc,SAAQ,SAAS,CAAC,aAAa,CAAC;IAElD,EAAE,EAAE,MAAM,CAAC;IAEX,aAAa,EAAE,MAAM,CAAC;IAEtB,WAAW,EAAE,MAAM,CAAC;IAEpB,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGtB,cAAc,EAAE,OAAO,CAAC;IAExB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,QAAQ,CAAC;IAIpB,YAAY,CAAC,EAAE,QAAQ,CAAC;CAChC"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AuthnIdentity = void 0;
13
+ const orm_1 = require("@spinajs/orm");
14
+ const luxon_1 = require("luxon");
15
+ /** A link from an external subject to an identity (design §22.16). */
16
+ let AuthnIdentity = class AuthnIdentity extends orm_1.ModelBase {
17
+ };
18
+ exports.AuthnIdentity = AuthnIdentity;
19
+ __decorate([
20
+ (0, orm_1.Primary)({ generated: 'assigned' }),
21
+ __metadata("design:type", String)
22
+ ], AuthnIdentity.prototype, "id", void 0);
23
+ __decorate([
24
+ (0, orm_1.Bool)(),
25
+ __metadata("design:type", Boolean)
26
+ ], AuthnIdentity.prototype, "email_verified", void 0);
27
+ __decorate([
28
+ (0, orm_1.DateTime)(),
29
+ __metadata("design:type", luxon_1.DateTime)
30
+ ], AuthnIdentity.prototype, "linked_at", void 0);
31
+ __decorate([
32
+ (0, orm_1.DateTime)(),
33
+ __metadata("design:type", luxon_1.DateTime)
34
+ ], AuthnIdentity.prototype, "last_used_at", void 0);
35
+ exports.AuthnIdentity = AuthnIdentity = __decorate([
36
+ (0, orm_1.Connection)('default'),
37
+ (0, orm_1.Model)('authn_identity')
38
+ ], AuthnIdentity);
39
+ //# sourceMappingURL=AuthnIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnIdentity.js","sourceRoot":"","sources":["../../../src/models/AuthnIdentity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAA2F;AAC3F,iCAAiC;AAEjC,sEAAsE;AAG/D,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,eAAwB;CAyB1D,CAAA;;AAvBQ;IADN,IAAA,aAAO,EAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;;yCACjB;AAaX;IADN,IAAA,UAAI,GAAE;;qDACwB;AAKxB;IADN,IAAA,cAAE,GAAE;8BACa,gBAAQ;gDAAC;AAIpB;IADN,IAAA,cAAE,GAAE;8BACiB,gBAAQ;mDAAC;wBAxBpB,aAAa;IAFzB,IAAA,gBAAU,EAAC,SAAS,CAAC;IACrB,IAAA,WAAK,EAAC,gBAAgB,CAAC;GACX,aAAa,CAyBzB"}
@@ -0,0 +1,16 @@
1
+ import { ModelBase } from '@spinajs/orm';
2
+ import { DateTime } from 'luxon';
3
+ /** One MFA step of an identity; the primary key is (identity, step). */
4
+ export declare class AuthnMfa extends ModelBase<AuthnMfa> {
5
+ identity: string;
6
+ step: string;
7
+ secret_enc: string;
8
+ /** Hex SHA-256 of `secret_enc`: `confirm` compares this, since TEXT is not comparable on MSSQL and case-blind on MySQL. */
9
+ secret_hash: string;
10
+ key_id: string;
11
+ confirmed_at?: DateTime;
12
+ /** Postgres returns bigint as a string. */
13
+ last_step?: number | string | null;
14
+ created_at: DateTime;
15
+ }
16
+ //# sourceMappingURL=AuthnMfa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthnMfa.d.ts","sourceRoot":"","sources":["../../../src/models/AuthnMfa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,SAAS,EAAW,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,wEAAwE;AACxE,qBAEa,QAAS,SAAQ,SAAS,CAAC,QAAQ,CAAC;IAExC,QAAQ,EAAE,MAAM,CAAC;IAGjB,IAAI,EAAE,MAAM,CAAC;IAEb,UAAU,EAAE,MAAM,CAAC;IAE1B,2HAA2H;IACpH,WAAW,EAAE,MAAM,CAAC;IAEpB,MAAM,EAAE,MAAM,CAAC;IAIf,YAAY,CAAC,EAAE,QAAQ,CAAC;IAE/B,2CAA2C;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAGnC,UAAU,EAAE,QAAQ,CAAC;CAC7B"}