@spinajs/authn-orm 0.0.0-stage → 3.0.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 (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,76 @@
1
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
2
+ import { InvalidArgument, InvalidOption } from '@spinajs/exceptions';
3
+ import { _check_arg, _is_string, _non_empty, _reg_match } from '@spinajs/util';
4
+ import { identityKey } from '../identity.js';
5
+ const ALGORITHM = 'aes-256-gcm';
6
+ const VERSION = 'v1';
7
+ const KEY_BYTES = 32;
8
+ const IV_BYTES = 12;
9
+ const TAG_BYTES = 16;
10
+ const HEX = /^[0-9a-fA-F]{64}$/;
11
+ const BASE64 = /^[A-Za-z0-9+/]{43}=?$/;
12
+ const BASE64URL = /^[A-Za-z0-9_-]{43}$/;
13
+ /**
14
+ * Reads a 32-byte key given as 64 hex characters, base64 (44, or 43 unpadded) or base64url (43). Anything else
15
+ * throws `InvalidOption`; the message never contains the value.
16
+ */
17
+ export function mfaKeyFrom(secret) {
18
+ let key;
19
+ if (typeof secret === 'string') {
20
+ if (HEX.test(secret)) {
21
+ key = Buffer.from(secret, 'hex');
22
+ }
23
+ else if (BASE64.test(secret) || BASE64URL.test(secret)) {
24
+ key = Buffer.from(secret, 'base64');
25
+ // Unused low bits in the last character would let several texts name one key.
26
+ if (key.toString('base64url') !== secret.replace(/=$/, '').replace(/\+/g, '-').replace(/\//g, '_'))
27
+ key = undefined;
28
+ }
29
+ }
30
+ if (!key || key.length !== KEY_BYTES) {
31
+ throw new InvalidOption('authn.mfa.encryptionKey.secret must be 32 bytes given as 64 hex characters, base64 or base64url');
32
+ }
33
+ const result = { keyId: createHash('sha256').update(key).digest('base64url').slice(0, 16) };
34
+ Object.defineProperty(result, 'key', { value: key, enumerable: false });
35
+ return Object.freeze(result);
36
+ }
37
+ function aad(identity, step) {
38
+ const id = typeof identity === 'string' ? identity : identityKey(identity);
39
+ _check_arg(_is_string(_non_empty()))(id, 'identity');
40
+ // With no "|" in the step, the last "|" splits the AAD into exactly one (identity, step) pair.
41
+ _check_arg(_is_string(_non_empty(), _reg_match(/^[^|]*$/)))(step, 'step');
42
+ return Buffer.from(`${id}|${step}`, 'utf8');
43
+ }
44
+ /** AES-256-GCM under `key` with AAD `${identity}|${step}`; returns `v1.<iv>.<tag>.<ct>`, each part base64url. */
45
+ export function encryptMfaSecret(key, identity, step, plain) {
46
+ _check_arg(_is_string(_non_empty()))(plain, 'plain');
47
+ const ad = aad(identity, step);
48
+ const iv = randomBytes(IV_BYTES);
49
+ const cipher = createCipheriv(ALGORITHM, key.key, iv, { authTagLength: TAG_BYTES });
50
+ cipher.setAAD(ad);
51
+ const ct = Buffer.concat([cipher.update(plain, 'utf8'), cipher.final()]);
52
+ return [VERSION, iv.toString('base64url'), cipher.getAuthTag().toString('base64url'), ct.toString('base64url')].join('.');
53
+ }
54
+ const PART = /^[A-Za-z0-9_-]+$/;
55
+ /** Throws `InvalidArgument` on a malformed text, another key, a changed text or another row's identity or step. */
56
+ export function decryptMfaSecret(key, identity, step, enc) {
57
+ const ad = aad(identity, step);
58
+ const parts = typeof enc === 'string' ? enc.split('.') : [];
59
+ if (parts.length !== 4 || parts[0] !== VERSION || !parts.slice(1).every((p) => PART.test(p))) {
60
+ throw new InvalidArgument('MFA cipher: the cipher text is not of the form v1.<iv>.<tag>.<ct>');
61
+ }
62
+ const [iv, tag, ct] = parts.slice(1).map((p) => Buffer.from(p, 'base64url'));
63
+ if (iv.length !== IV_BYTES || tag.length !== TAG_BYTES) {
64
+ throw new InvalidArgument('MFA cipher: the cipher text has a wrong IV or tag length');
65
+ }
66
+ try {
67
+ const decipher = createDecipheriv(ALGORITHM, key.key, iv, { authTagLength: TAG_BYTES });
68
+ decipher.setAAD(ad);
69
+ decipher.setAuthTag(tag);
70
+ return Buffer.concat([decipher.update(ct), decipher.final()]).toString('utf8');
71
+ }
72
+ catch (err) {
73
+ throw new InvalidArgument('MFA cipher: the cipher text does not decrypt under this key for this identity and step', undefined, undefined, err);
74
+ }
75
+ }
76
+ //# sourceMappingURL=cipher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../../src/mfa/cipher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { IdentityRef } from '@spinajs/authn/contracts';
2
+ import { MfaEnrolments } from '@spinajs/authn/mfa-enrolments';
3
+ import { DbMfaStore } from './db-mfa-store.js';
4
+ /** The confirmed steps of `authn_mfa` for DefaultMfaPolicy and authn:check-config, whether authn.mfa.steps lists them or not. */
5
+ export declare class DbMfaEnrolments extends MfaEnrolments {
6
+ private readonly db?;
7
+ protected DbMfaStore: DbMfaStore;
8
+ /** DI passes nothing and injects `DbMfaStore`. */
9
+ constructor(db?: DbMfaStore | undefined);
10
+ private store;
11
+ stepsOf(id: IdentityRef): Promise<readonly string[]>;
12
+ stepNames(): Promise<readonly string[]>;
13
+ }
14
+ //# sourceMappingURL=db-mfa-enrolments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-mfa-enrolments.d.ts","sourceRoot":"","sources":["../../../src/mfa/db-mfa-enrolments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,iIAAiI;AACjI,qBAEa,eAAgB,SAAQ,aAAa;IAKpC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IAHhC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC;IAEjC,kDAAkD;IAClD,YAA6B,EAAE,CAAC,EAAE,UAAU,YAAA,EAE3C;IAED,OAAO,CAAC,KAAK;IAIN,OAAO,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAE1D;IAEM,SAAS,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAE7C;CACF"}
@@ -0,0 +1,40 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { MfaEnrolments } from '@spinajs/authn/mfa-enrolments';
11
+ import { Autoinject, Injectable, PerChildInstance } from '@spinajs/di';
12
+ import { DbMfaStore } from './db-mfa-store.js';
13
+ /** The confirmed steps of `authn_mfa` for DefaultMfaPolicy and authn:check-config, whether authn.mfa.steps lists them or not. */
14
+ let DbMfaEnrolments = class DbMfaEnrolments extends MfaEnrolments {
15
+ /** DI passes nothing and injects `DbMfaStore`. */
16
+ constructor(db) {
17
+ super();
18
+ this.db = db;
19
+ }
20
+ store() {
21
+ return this.db ?? this.DbMfaStore;
22
+ }
23
+ stepsOf(id) {
24
+ return this.store().confirmedSteps(id);
25
+ }
26
+ stepNames() {
27
+ return this.store().confirmedStepNames();
28
+ }
29
+ };
30
+ __decorate([
31
+ Autoinject(DbMfaStore),
32
+ __metadata("design:type", DbMfaStore)
33
+ ], DbMfaEnrolments.prototype, "DbMfaStore", void 0);
34
+ DbMfaEnrolments = __decorate([
35
+ PerChildInstance(),
36
+ Injectable(MfaEnrolments),
37
+ __metadata("design:paramtypes", [DbMfaStore])
38
+ ], DbMfaEnrolments);
39
+ export { DbMfaEnrolments };
40
+ //# sourceMappingURL=db-mfa-enrolments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-mfa-enrolments.js","sourceRoot":"","sources":["../../../src/mfa/db-mfa-enrolments.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,iIAAiI;AAG1H,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,aAAa;IAIhD,kDAAkD;IAClD,YAA6B,EAAe;QAC1C,KAAK,EAAE,CAAC;kBADmB,EAAE;IAE/B,CAAC;IAEO,KAAK;QACX,OAAO,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC;IACpC,CAAC;IAEM,OAAO,CAAC,EAAe;QAC5B,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,kBAAkB,EAAE,CAAC;IAC3C,CAAC;CACF,CAAA;AAlBW;IADT,UAAU,CAAC,UAAU,CAAC;8BACD,UAAU;mDAAC;AAFtB,eAAe;IAF3B,gBAAgB,EAAE;IAClB,UAAU,CAAC,aAAa,CAAC;qCAMU,UAAU;GALjC,eAAe,CAoB3B"}
@@ -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,187 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { randomUUID } from 'node:crypto';
8
+ import { Injectable, PerChildInstance } from '@spinajs/di';
9
+ import { InvalidArgument, UnexpectedServerError } from '@spinajs/exceptions';
10
+ import { UniqueViolation, ormReady } from '@spinajs/orm';
11
+ import { _between, _check_arg, _integer, _is_array, _is_number, _is_string, _max_length, _non_empty, _try_check_arg } from '@spinajs/util';
12
+ import { identityKey } from '../identity.js';
13
+ import { AuthnMfa } from '../models/AuthnMfa.js';
14
+ import { AuthnRecoveryCode } from '../models/AuthnRecoveryCode.js';
15
+ import { checkedMs, checkedText, dateOf, instant, sha256hex } from '../support/sql.js';
16
+ import { columnValues } from '../support/values.js';
17
+ /** Each retry means a parallel `remove` deleted the row between this call's insert and update. */
18
+ const MAX_TRIES = 8;
19
+ /** As DbSecretStore: longer input is refused before hashing. */
20
+ const RAW_MAX = 1024;
21
+ const stepName = (step) => checkedText(step, 32, 'DbMfaStore: step');
22
+ function lastStepOf(value) {
23
+ if (value === null || value === undefined)
24
+ return null;
25
+ const n = typeof value === 'number' ? value : Number(String(value));
26
+ if (!Number.isSafeInteger(n))
27
+ throw new UnexpectedServerError(`DbMfaStore: last_step ${String(value)} is not a safe integer`);
28
+ return n;
29
+ }
30
+ const confirmed = (r) => r.confirmed_at !== null && r.confirmed_at !== undefined;
31
+ /** The columns `putPending` writes: unconfirmed, no accepted time step. */
32
+ function pending(secretEnc, keyId, createdAt) {
33
+ return columnValues({ secret_enc: secretEnc, secret_hash: sha256hex(secretEnc), key_id: keyId, confirmed_at: null, last_step: null, created_at: createdAt });
34
+ }
35
+ /**
36
+ * `authn_mfa` and `authn_recovery_code` for MFA steps (authn-totp, N5). Rows are keyed by `identityKey(id)` and
37
+ * the step name. The store keeps cipher text and its key id only (SR-09); recovery codes are stored as hex SHA-256,
38
+ * never raw, and callers normalise a code before passing it. Replay and single use are decided in SQL (SR-15, D10).
39
+ *
40
+ * Without transactions (the sqlite driver shares one handle) `replaceRecoveryCodes` deletes and then inserts: two
41
+ * parallel calls for one identity may leave both sets.
42
+ */
43
+ let DbMfaStore = class DbMfaStore {
44
+ async get(id, step) {
45
+ const identity = identityKey(id);
46
+ const name = stepName(step);
47
+ await ormReady();
48
+ const rows = await AuthnMfa.query().columns(['identity', 'step', 'secret_enc', 'key_id', 'last_step', 'confirmed_at', 'created_at']).where('identity', identity).where('step', name);
49
+ const r = rows.find((x) => x.identity === identity && x.step === name);
50
+ if (!r)
51
+ return null;
52
+ return {
53
+ secretEnc: r.secret_enc,
54
+ keyId: r.key_id,
55
+ confirmedAt: r.confirmed_at ? dateOf(r.confirmed_at) : null,
56
+ lastStep: lastStepOf(r.last_step),
57
+ createdAt: dateOf(r.created_at),
58
+ };
59
+ }
60
+ /**
61
+ * Stores the step unconfirmed, with no accepted time step and created now, replacing a pending one. A confirmed
62
+ * step is never overwritten: false means a confirmed row exists and nothing changed. The
63
+ * replacing update is conditional on `confirmed_at IS NULL`, so a confirmation that lands first always wins.
64
+ */
65
+ async putPending(id, step, secretEnc, keyId) {
66
+ const identity = identityKey(id);
67
+ const name = stepName(step);
68
+ checkedText(secretEnc, Number.MAX_SAFE_INTEGER, 'DbMfaStore: secretEnc');
69
+ checkedText(keyId, 32, 'DbMfaStore: keyId');
70
+ const ms = checkedMs(new Date(), 'DbMfaStore.putPending: the clock');
71
+ await ormReady();
72
+ const fields = pending(secretEnc, keyId, instant(ms));
73
+ for (let i = 0; i < MAX_TRIES; i++) {
74
+ try {
75
+ await AuthnMfa.insert({ identity, step: name, ...fields });
76
+ return true;
77
+ }
78
+ catch (err) {
79
+ if (!(err instanceof UniqueViolation))
80
+ throw err;
81
+ }
82
+ if ((await AuthnMfa.update(fields).where('identity', identity).where('step', name).whereNull('confirmed_at')).RowsAffected === 1)
83
+ return true;
84
+ // No row updated: either it is confirmed, or a parallel remove deleted it and the insert is worth retrying.
85
+ if ((await this.get(id, name))?.confirmedAt)
86
+ return false;
87
+ }
88
+ throw new UnexpectedServerError(`DbMfaStore.putPending: the ${name} row kept changing under this call`);
89
+ }
90
+ /**
91
+ * Sets `confirmed_at` (default now); true when the step exists. With `expectedSecretEnc`, only an unconfirmed step
92
+ * holding that cipher text is confirmed, so the answer is true for exactly the call that confirmed it.
93
+ */
94
+ async confirm(id, step, at = new Date(), expectedSecretEnc) {
95
+ const identity = identityKey(id);
96
+ const name = stepName(step);
97
+ const ms = checkedMs(at, 'DbMfaStore.confirm: at');
98
+ if (expectedSecretEnc !== undefined)
99
+ checkedText(expectedSecretEnc, Number.MAX_SAFE_INTEGER, 'DbMfaStore: expectedSecretEnc');
100
+ await ormReady();
101
+ const q = AuthnMfa.update({ confirmed_at: instant(ms) })
102
+ .where('identity', identity)
103
+ .where('step', name);
104
+ if (expectedSecretEnc !== undefined) {
105
+ q.whereNull('confirmed_at').where('secret_hash', sha256hex(expectedSecretEnc));
106
+ }
107
+ return (await q).RowsAffected === 1;
108
+ }
109
+ /** 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. */
110
+ async acceptStep(id, step, timeStep) {
111
+ const identity = identityKey(id);
112
+ const name = stepName(step);
113
+ _check_arg(_is_number(_integer(), _between(0, Number.MAX_SAFE_INTEGER)))(timeStep, 'timeStep');
114
+ await ormReady();
115
+ const older = function () {
116
+ this.whereNull('last_step');
117
+ this.orWhere('last_step', '<', timeStep);
118
+ };
119
+ return (await AuthnMfa.update({ last_step: timeStep }).where('identity', identity).where('step', name).where(older)).RowsAffected === 1;
120
+ }
121
+ async remove(id, step) {
122
+ const identity = identityKey(id);
123
+ const name = stepName(step);
124
+ await ormReady();
125
+ await AuthnMfa.destroy().where('identity', identity).where('step', name);
126
+ }
127
+ /** The names of the identity's confirmed steps. */
128
+ async confirmedSteps(id) {
129
+ const identity = identityKey(id);
130
+ await ormReady();
131
+ const rows = await AuthnMfa.query().columns(['identity', 'step', 'confirmed_at']).where('identity', identity).whereNotNull('confirmed_at');
132
+ return rows.filter((r) => r.identity === identity && confirmed(r)).map((r) => r.step);
133
+ }
134
+ /**
135
+ * Each step name with a confirmed row of any identity, once. Deduplicated here, not with DISTINCT, which folds
136
+ * `totp` and `TOTP` into one under a case-blind collation (MySQL's default); one row per confirmed enrolment.
137
+ */
138
+ async confirmedStepNames() {
139
+ await ormReady();
140
+ const rows = await AuthnMfa.query().columns(['step', 'confirmed_at']).whereNotNull('confirmed_at');
141
+ return [...new Set(rows.filter(confirmed).map((r) => r.step))];
142
+ }
143
+ /** Deletes the identity's codes, then stores the SHA-256 of each new one. Empty or repeated codes throw. */
144
+ async replaceRecoveryCodes(id, rawCodes) {
145
+ const identity = identityKey(id);
146
+ _check_arg(_is_array())(rawCodes, 'rawCodes');
147
+ const hashes = rawCodes.map((code) => sha256hex(checkedText(code, Number.MAX_SAFE_INTEGER, 'DbMfaStore: a recovery code')));
148
+ if (new Set(hashes).size !== hashes.length)
149
+ throw new InvalidArgument('DbMfaStore.replaceRecoveryCodes: the codes repeat');
150
+ await ormReady();
151
+ await AuthnRecoveryCode.destroy().where('identity', identity);
152
+ if (hashes.length === 0)
153
+ return;
154
+ await AuthnRecoveryCode.insert(hashes.map((code_hash) => columnValues({ id: randomUUID(), identity, code_hash, used_at: null })));
155
+ }
156
+ /** Spends the code in one conditional update; true for exactly one caller. */
157
+ async redeemRecoveryCode(id, raw) {
158
+ const identity = identityKey(id);
159
+ if (!_try_check_arg(_is_string(_non_empty(), _max_length(RAW_MAX)))(raw, 'raw')[0])
160
+ return false;
161
+ const ms = checkedMs(new Date(), 'DbMfaStore.redeemRecoveryCode: the clock');
162
+ await ormReady();
163
+ const r = await AuthnRecoveryCode.update({ used_at: instant(ms) })
164
+ .where('identity', identity)
165
+ .where('code_hash', sha256hex(raw))
166
+ .whereNull('used_at');
167
+ return r.RowsAffected > 0;
168
+ }
169
+ /** Unused codes. */
170
+ async countRecoveryCodes(id) {
171
+ const identity = identityKey(id);
172
+ await ormReady();
173
+ const rows = await AuthnRecoveryCode.query().columns(['identity']).where('identity', identity).whereNull('used_at');
174
+ return rows.filter((r) => r.identity === identity).length;
175
+ }
176
+ async removeRecoveryCodes(id) {
177
+ const identity = identityKey(id);
178
+ await ormReady();
179
+ await AuthnRecoveryCode.destroy().where('identity', identity);
180
+ }
181
+ };
182
+ DbMfaStore = __decorate([
183
+ PerChildInstance(),
184
+ Injectable()
185
+ ], DbMfaStore);
186
+ export { DbMfaStore };
187
+ //# 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,4 @@
1
+ export * from './db-mfa-store.js';
2
+ export * from './db-mfa-enrolments.js';
3
+ export * from './cipher.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC"}
@@ -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,95 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Migration, OrmMigration } from '@spinajs/orm';
8
+ const TABLES = ['authn_identity', 'authn_throttle', 'authn_audit', 'authn_secret', 'authn_mfa', 'authn_recovery_code', 'authn_nonce'];
9
+ /**
10
+ * The authn-orm tables of design §22.16, plus `authn_recovery_code_owner`. The schema builder has no `char`
11
+ * type, so the `char(64)` hash columns are `varchar(64)`.
12
+ */
13
+ let AuthnInitial_2026_10_02_00_00_00 = class AuthnInitial_2026_10_02_00_00_00 extends OrmMigration {
14
+ async up(connection) {
15
+ await connection.schema().createTable('authn_identity', (table) => {
16
+ table.string('id', 36).notNull().primaryKey();
17
+ table.string('identity_type', 16).notNull();
18
+ table.string('identity_id', 64).notNull();
19
+ table.string('provider', 128).notNull();
20
+ table.string('subject', 255).notNull();
21
+ table.string('email', 255);
22
+ table.boolean('email_verified').notNull().default().value(0);
23
+ table.text('attributes');
24
+ table.dateTime('linked_at').notNull();
25
+ table.dateTime('last_used_at');
26
+ });
27
+ await connection.index().unique().table('authn_identity').name('authn_identity_subject').columns(['provider', 'subject']);
28
+ await connection.index().table('authn_identity').name('authn_identity_owner').columns(['identity_type', 'identity_id']);
29
+ await connection.schema().createTable('authn_throttle', (table) => {
30
+ table.string('k', 255).notNull().primaryKey();
31
+ table.int('attempts').notNull();
32
+ table.dateTime('last_attempt_at').notNull();
33
+ table.dateTime('next_allowed_at').notNull();
34
+ table.dateTime('updated_at').notNull();
35
+ });
36
+ await connection.schema().createTable('authn_audit', (table) => {
37
+ table.string('id', 36).notNull().primaryKey();
38
+ table.dateTime('at').notNull();
39
+ table.string('type', 32).notNull();
40
+ table.string('outcome', 8).notNull();
41
+ table.string('identity', 100);
42
+ table.string('actor', 100);
43
+ table.string('strategy', 64);
44
+ table.string('reason', 64);
45
+ table.string('ip', 64);
46
+ table.string('user_agent', 255);
47
+ table.string('session', 64);
48
+ table.text('data');
49
+ });
50
+ await connection.index().table('authn_audit').name('authn_audit_at').columns(['at']);
51
+ await connection.index().table('authn_audit').name('authn_audit_identity').columns(['identity', 'at']);
52
+ await connection.schema().createTable('authn_secret', (table) => {
53
+ table.string('id', 36).notNull().primaryKey();
54
+ table.string('identity', 100).notNull();
55
+ table.string('purpose', 32).notNull();
56
+ table.string('secret_hash', 64).notNull();
57
+ table.dateTime('expires_at').notNull();
58
+ table.dateTime('used_at');
59
+ table.dateTime('created_at').notNull();
60
+ });
61
+ await connection.index().unique().table('authn_secret').name('authn_secret_hash').columns(['secret_hash']);
62
+ await connection.index().table('authn_secret').name('authn_secret_owner').columns(['identity', 'purpose']);
63
+ await connection.schema().createTable('authn_mfa', (table) => {
64
+ table.string('identity', 100).notNull().primaryKey();
65
+ table.string('step', 32).notNull().primaryKey();
66
+ table.text('secret_enc').notNull();
67
+ table.string('secret_hash', 64).notNull();
68
+ table.string('key_id', 32).notNull();
69
+ table.dateTime('confirmed_at');
70
+ table.bigint('last_step');
71
+ table.dateTime('created_at').notNull();
72
+ });
73
+ await connection.schema().createTable('authn_recovery_code', (table) => {
74
+ table.string('id', 36).notNull().primaryKey();
75
+ table.string('identity', 100).notNull();
76
+ table.string('code_hash', 64).notNull();
77
+ table.dateTime('used_at');
78
+ });
79
+ await connection.index().table('authn_recovery_code').name('authn_recovery_code_owner').columns(['identity']);
80
+ await connection.schema().createTable('authn_nonce', (table) => {
81
+ table.string('k', 160).notNull().primaryKey();
82
+ table.dateTime('expires_at').notNull();
83
+ });
84
+ }
85
+ async down(connection) {
86
+ for (const table of [...TABLES].reverse()) {
87
+ await connection.schema().dropTable(table);
88
+ }
89
+ }
90
+ };
91
+ AuthnInitial_2026_10_02_00_00_00 = __decorate([
92
+ Migration('default')
93
+ ], AuthnInitial_2026_10_02_00_00_00);
94
+ export { AuthnInitial_2026_10_02_00_00_00 };
95
+ //# 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":"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"}
@@ -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,2 @@
1
+ export * from './AuthnInitial_2026_10_02_00_00_00.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,cAAc,uCAAuC,CAAC"}
@@ -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,27 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Connection, DateTime as DT, Model, ModelBase, Primary } from '@spinajs/orm';
11
+ import { DateTime } from 'luxon';
12
+ let AuthnAudit = class AuthnAudit extends ModelBase {
13
+ };
14
+ __decorate([
15
+ Primary({ generated: 'assigned' }),
16
+ __metadata("design:type", String)
17
+ ], AuthnAudit.prototype, "id", void 0);
18
+ __decorate([
19
+ DT(),
20
+ __metadata("design:type", DateTime)
21
+ ], AuthnAudit.prototype, "at", void 0);
22
+ AuthnAudit = __decorate([
23
+ Connection('default'),
24
+ Model('authn_audit')
25
+ ], AuthnAudit);
26
+ export { AuthnAudit };
27
+ //# sourceMappingURL=AuthnAudit.js.map