@madauth/server 0.3.0-beta.2 → 0.5.0-beta.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 (37) hide show
  1. package/README.md +3 -2
  2. package/dist/bin.js +202 -50
  3. package/dist/chunk-7DHKDRGY.js +1706 -0
  4. package/dist/{chunk-DCDTO5LG.js → chunk-A7UYZRBL.js} +1 -0
  5. package/dist/chunk-NP75Y3IV.js +107 -0
  6. package/dist/chunk-NYIEFI4B.js +1040 -0
  7. package/dist/{chunk-56MOVFO4.js → chunk-O2URPWA6.js} +37 -4
  8. package/dist/{chunk-3QRKWLR7.js → chunk-SISM7YUZ.js} +15 -10
  9. package/dist/{config-Dg2fZuWR.d.ts → config-CcGlHVAN.d.ts} +19 -8
  10. package/dist/dynamodb.js +1 -1
  11. package/dist/entry/azure.d.ts +3 -3
  12. package/dist/entry/azure.js +4 -4
  13. package/dist/entry/lambda.d.ts +3 -3
  14. package/dist/entry/lambda.js +4 -4
  15. package/dist/entry/node.d.ts +3 -3
  16. package/dist/entry/node.js +4 -4
  17. package/dist/index.d.ts +37 -15
  18. package/dist/index.js +12 -6
  19. package/dist/{schema-3yhCc2jH.d.ts → schema-BTgDj1Xn.d.ts} +79 -3
  20. package/dist/sqlite.js +2 -2
  21. package/dist/standalone/azure.mjs +5511 -922
  22. package/dist/standalone/lambda.mjs +5461 -872
  23. package/dist/standalone/main.mjs +5487 -898
  24. package/dist/store/dynamodb.d.ts +1 -1
  25. package/dist/store/sqlite.d.ts +1 -1
  26. package/dist/testing.d.ts +1 -1
  27. package/dist/testing.js +21 -0
  28. package/dist/{user-BMWEWREH.d.ts → user-yoGjrw4k.d.ts} +5 -0
  29. package/dist/verify.d.ts +1 -1
  30. package/dist/verify.js +1 -1
  31. package/dist/{webhook-j5u9Kv9l.d.ts → webhook-DlmfG_kS.d.ts} +5 -2
  32. package/dist/webhook.d.ts +1 -1
  33. package/dist/webhook.js +1 -1
  34. package/package.json +4 -2
  35. package/dist/chunk-CD7Y4T66.js +0 -62
  36. package/dist/chunk-DVVBIFIV.js +0 -718
  37. package/dist/chunk-TI35AZ2U.js +0 -660
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  madauthSchema
3
- } from "./chunk-CD7Y4T66.js";
3
+ } from "./chunk-NP75Y3IV.js";
4
4
 
5
5
  // src/store/sql.ts
6
6
  function tableName(model) {
7
- return `madauth_${model}`;
7
+ return `madauth_${columnName(model)}`;
8
8
  }
9
9
  function columnName(field) {
10
10
  return field.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
@@ -15,6 +15,10 @@ var columnTypes = {
15
15
  postgres: { string: "TEXT", number: "DOUBLE PRECISION", boolean: "BOOLEAN" },
16
16
  mysql: { string: "TEXT", number: "DOUBLE", boolean: "BOOLEAN" }
17
17
  };
18
+ function columnType(dialect, def) {
19
+ const keyed = def.primaryKey || def.unique || def.index;
20
+ return dialect === "mysql" && def.type === "string" && keyed ? "VARCHAR(255)" : columnTypes[dialect][def.type];
21
+ }
18
22
  var upgrades = [
19
23
  {
20
24
  version: 2,
@@ -45,6 +49,36 @@ var upgrades = [
45
49
  `DROP TABLE ${tableName("role")};`,
46
50
  createTablesSql(dialect, { version: 4, models: { setting: madauthSchema.models.setting } })
47
51
  ].join("\n")
52
+ },
53
+ {
54
+ // The authenticator app: which code was used last, and the recovery codes.
55
+ version: 5,
56
+ sql: (dialect) => [
57
+ `ALTER TABLE ${tableName("account")} ADD COLUMN ${columnName("lastUsedStep")} ${columnTypes[dialect].number} NOT NULL DEFAULT 0;`,
58
+ `ALTER TABLE ${tableName("account")} ADD COLUMN ${columnName("setupId")} ${columnTypes[dialect].string};`,
59
+ createTablesSql(dialect, { version: 5, models: { recoveryCode: madauthSchema.models.recoveryCode } })
60
+ ].join("\n")
61
+ },
62
+ {
63
+ // SMS codes as a second factor: the phone number of an sms account, and when the last SMS went to a user.
64
+ version: 6,
65
+ sql: (dialect) => [
66
+ `ALTER TABLE ${tableName("account")} ADD COLUMN ${columnName("phone")} ${columnTypes[dialect].string};`,
67
+ `ALTER TABLE ${tableName("user")} ADD COLUMN ${columnName("lastSmsAt")} ${columnTypes[dialect].number};`
68
+ ].join("\n")
69
+ },
70
+ {
71
+ // One primary sign-in method per user, which accounts are second factors, and when a user's sign-up was
72
+ // complete. Older records stay empty: madAuth tells them apart by the account's key, and counts their
73
+ // sign-up as complete.
74
+ version: 7,
75
+ sql: (dialect) => [
76
+ `ALTER TABLE ${tableName("user")} ADD COLUMN ${columnName("signedUpAt")} ${columnTypes[dialect].number};`,
77
+ // SQLite can't add a UNIQUE column, so the constraint is an index.
78
+ `ALTER TABLE ${tableName("account")} ADD COLUMN ${columnName("primaryUserId")} ${columnType(dialect, madauthSchema.models.account.fields.primaryUserId)};`,
79
+ `CREATE UNIQUE INDEX ${tableName("account")}_${columnName("primaryUserId")} ON ${tableName("account")} (${columnName("primaryUserId")});`,
80
+ `ALTER TABLE ${tableName("account")} ADD COLUMN ${columnName("secondFactor")} ${columnType(dialect, madauthSchema.models.account.fields.secondFactor)};`
81
+ ].join("\n")
48
82
  }
49
83
  ];
50
84
  function upgradeTablesSql(dialect, fromVersion) {
@@ -55,8 +89,7 @@ function createTablesSql(dialect, schema = madauthSchema) {
55
89
  for (const [model, { fields }] of Object.entries(schema.models)) {
56
90
  const table = tableName(model);
57
91
  const columns = Object.entries(fields).map(([field, def]) => {
58
- const keyed = def.primaryKey || def.unique || def.index;
59
- const type = dialect === "mysql" && def.type === "string" && keyed ? "VARCHAR(255)" : columnTypes[dialect][def.type];
92
+ const type = columnType(dialect, def);
60
93
  const constraints = def.primaryKey ? " PRIMARY KEY" : `${def.nullable ? "" : " NOT NULL"}${def.unique ? " UNIQUE" : ""}`;
61
94
  return ` ${columnName(field)} ${type}${constraints}`;
62
95
  });
@@ -1,24 +1,29 @@
1
1
  // src/webhooks.ts
2
2
  import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "crypto";
3
3
  var WEBHOOK_TYPES = [
4
- "email.verify",
5
- "email.reset",
6
- "email.already_registered",
7
- "email.no_password",
8
- "signup.before",
9
- "user.created",
10
- "email.verified",
11
- "email.password_reset",
4
+ "email.send_verification",
5
+ "email.send_password_reset",
6
+ "email.send_signin_link",
7
+ "email.send_already_registered",
8
+ "email.send_password_reset_no_password",
9
+ "sms.send_code",
10
+ "user.signing_up",
11
+ "user.signed_up",
12
+ "user.email_verified",
13
+ "user.password_reset",
12
14
  "user.signed_in",
13
15
  "user.deleted",
14
- "user.claims_changed"
16
+ "user.claims_changed",
17
+ "user.second_factor_enabled",
18
+ "user.second_factor_disabled",
19
+ "user.recovery_code_used"
15
20
  ];
16
21
  var WEBHOOK_TIMEOUT_MS = 1e4;
17
22
  var MAX_LOCALE_LENGTH = 35;
18
23
  function localeOf(value) {
19
24
  return typeof value === "string" && value.length <= MAX_LOCALE_LENGTH ? value : void 0;
20
25
  }
21
- var REQUIRED_EMAIL_TYPES = ["email.verify", "email.reset"];
26
+ var REQUIRED_EMAIL_TYPES = ["email.send_verification", "email.send_password_reset"];
22
27
  var SECRET_PREFIX = "whsec_";
23
28
  var DEV_WEBHOOK_RECEIVER_URL = "https://github.com/inouiw/madAuth-webhooks/tree/main/dev-receiver";
24
29
  var WEBHOOK_TOLERANCE_SECONDS = 5 * 60;
@@ -1,6 +1,6 @@
1
1
  import { JWK, JWTVerifyGetKey } from 'jose';
2
- import { S as StoreAdapter } from './schema-3yhCc2jH.js';
3
- import { W as WebhookSettings } from './webhook-j5u9Kv9l.js';
2
+ import { S as StoreAdapter } from './schema-BTgDj1Xn.js';
3
+ import { W as WebhookSettings } from './webhook-DlmfG_kS.js';
4
4
 
5
5
  interface MadauthConfig {
6
6
  /** Public base URL of the server (MADAUTH_ISSUER). */
@@ -15,6 +15,8 @@ interface MadauthConfig {
15
15
  renewalTtlSeconds: number;
16
16
  /** Cookie domain, e.g. `.example.com` (COOKIE_DOMAIN). */
17
17
  cookieDomain?: string;
18
+ /** The name authenticator apps show next to the account (TOTP_ISSUER). Default: the host of the app that asked for the setup. */
19
+ totpIssuer?: string;
18
20
  /** Google sign-in; off when GOOGLE_CLIENT_ID is not set. */
19
21
  google?: {
20
22
  /** OAuth web client ID (GOOGLE_CLIENT_ID). */
@@ -22,13 +24,20 @@ interface MadauthConfig {
22
24
  /** Enables the server-side code flow (GOOGLE_CLIENT_SECRET). */
23
25
  clientSecret?: string;
24
26
  };
27
+ /** GitHub sign-in; off when GITHUB_CLIENT_ID is not set. GitHub only has the redirect flow, so the secret is needed too. */
28
+ github?: {
29
+ /** The client ID of the OAuth App (GITHUB_CLIENT_ID). */
30
+ clientId: string;
31
+ /** Its client secret (GITHUB_CLIENT_SECRET). */
32
+ clientSecret: string;
33
+ };
25
34
  /** Where the users, their accounts, claims and the settings are kept (DATABASE_URL or the `store` option). */
26
35
  store: StoreAdapter;
27
- /** E-mail & password sign-in; off unless the webhook sends the e-mails (`email.verify` and `email.reset`). */
28
- password?: {
29
- /** PASSWORD_MIN_LENGTH. */
30
- minLength: number;
31
- };
36
+ /**
37
+ * E-mail & password sign-in; off unless the webhook sends the e-mails (`email.send_verification` and `email.send_password_reset`).
38
+ * Its rules for new passwords are a setting, see `Settings.passwordRules`.
39
+ */
40
+ password?: Record<string, never>;
32
41
  /** Where madAuth sends e-mails, sign-up checks and events (WEBHOOK_URL). */
33
42
  webhook?: WebhookSettings;
34
43
  /** Test hook: resolves Google's signing keys. Defaults to Google's published JWKS. */
@@ -43,8 +52,10 @@ declare const envVars: {
43
52
  readonly ALLOWED_ORIGINS: true;
44
53
  readonly GOOGLE_CLIENT_ID: false;
45
54
  readonly GOOGLE_CLIENT_SECRET: false;
55
+ readonly GITHUB_CLIENT_ID: false;
56
+ readonly GITHUB_CLIENT_SECRET: false;
46
57
  readonly DATABASE_URL: true;
47
- readonly PASSWORD_MIN_LENGTH: false;
58
+ readonly TOTP_ISSUER: false;
48
59
  readonly WEBHOOK_URL: false;
49
60
  readonly WEBHOOK_SECRET: false;
50
61
  readonly WEBHOOK_EVENTS: false;
package/dist/dynamodb.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  madauthSchema
3
- } from "./chunk-CD7Y4T66.js";
3
+ } from "./chunk-NP75Y3IV.js";
4
4
 
5
5
  // src/store/dynamodb.ts
6
6
  var SORT_KEY = "#";
@@ -1,7 +1,7 @@
1
- import { E as EntryOptions } from '../config-Dg2fZuWR.js';
1
+ import { E as EntryOptions } from '../config-CcGlHVAN.js';
2
2
  import 'jose';
3
- import '../schema-3yhCc2jH.js';
4
- import '../webhook-j5u9Kv9l.js';
3
+ import '../schema-BTgDj1Xn.js';
4
+ import '../webhook-DlmfG_kS.js';
5
5
 
6
6
  /**
7
7
  * Registers madAuth as an Azure Functions v4 HTTP function that handles every route. Pass `store` to use your
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-DVVBIFIV.js";
4
- import "../chunk-DCDTO5LG.js";
3
+ } from "../chunk-7DHKDRGY.js";
4
+ import "../chunk-A7UYZRBL.js";
5
5
  import {
6
6
  loadConfig,
7
7
  resolveEnv
8
- } from "../chunk-TI35AZ2U.js";
8
+ } from "../chunk-NYIEFI4B.js";
9
9
  import "../chunk-JDQLSL36.js";
10
- import "../chunk-3QRKWLR7.js";
10
+ import "../chunk-SISM7YUZ.js";
11
11
 
12
12
  // src/entry/azure.ts
13
13
  import { app } from "@azure/functions";
@@ -1,8 +1,8 @@
1
1
  import { LambdaEvent, LambdaContext, handle } from 'hono/aws-lambda';
2
- import { E as EntryOptions } from '../config-Dg2fZuWR.js';
2
+ import { E as EntryOptions } from '../config-CcGlHVAN.js';
3
3
  import 'jose';
4
- import '../schema-3yhCc2jH.js';
5
- import '../webhook-j5u9Kv9l.js';
4
+ import '../schema-BTgDj1Xn.js';
5
+ import '../webhook-DlmfG_kS.js';
6
6
 
7
7
  type LambdaHandler = (event: LambdaEvent, context: LambdaContext) => ReturnType<ReturnType<typeof handle>>;
8
8
  /**
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-DVVBIFIV.js";
4
- import "../chunk-DCDTO5LG.js";
3
+ } from "../chunk-7DHKDRGY.js";
4
+ import "../chunk-A7UYZRBL.js";
5
5
  import {
6
6
  loadConfig,
7
7
  resolveEnv
8
- } from "../chunk-TI35AZ2U.js";
8
+ } from "../chunk-NYIEFI4B.js";
9
9
  import "../chunk-JDQLSL36.js";
10
- import "../chunk-3QRKWLR7.js";
10
+ import "../chunk-SISM7YUZ.js";
11
11
 
12
12
  // src/entry/lambda.ts
13
13
  import { handle } from "hono/aws-lambda";
@@ -1,7 +1,7 @@
1
- import { E as EntryOptions } from '../config-Dg2fZuWR.js';
1
+ import { E as EntryOptions } from '../config-CcGlHVAN.js';
2
2
  import 'jose';
3
- import '../schema-3yhCc2jH.js';
4
- import '../webhook-j5u9Kv9l.js';
3
+ import '../schema-BTgDj1Xn.js';
4
+ import '../webhook-DlmfG_kS.js';
5
5
 
6
6
  type StartOptions = EntryOptions;
7
7
  /**
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-DVVBIFIV.js";
4
- import "../chunk-DCDTO5LG.js";
3
+ } from "../chunk-7DHKDRGY.js";
4
+ import "../chunk-A7UYZRBL.js";
5
5
  import {
6
6
  loadConfig,
7
7
  resolveEnv
8
- } from "../chunk-TI35AZ2U.js";
8
+ } from "../chunk-NYIEFI4B.js";
9
9
  import "../chunk-JDQLSL36.js";
10
- import "../chunk-3QRKWLR7.js";
10
+ import "../chunk-SISM7YUZ.js";
11
11
 
12
12
  // src/entry/node.ts
13
13
  import { serve } from "@hono/node-server";
package/dist/index.d.ts CHANGED
@@ -1,22 +1,44 @@
1
1
  import { Hono } from 'hono';
2
- import { M as MadauthConfig } from './config-Dg2fZuWR.js';
3
- export { C as ConfigError, a as ConfigOverrides, E as EntryOptions, e as envVars, l as loadConfig } from './config-Dg2fZuWR.js';
2
+ import { M as MadauthConfig } from './config-CcGlHVAN.js';
3
+ export { C as ConfigError, a as ConfigOverrides, E as EntryOptions, e as envVars, l as loadConfig } from './config-CcGlHVAN.js';
4
4
  import { JWK } from 'jose';
5
- import { a as Schema } from './schema-3yhCc2jH.js';
6
- export { F as FieldDef, b as FieldType, R as Row, S as StoreAdapter, V as Value, W as Where, m as madauthSchema } from './schema-3yhCc2jH.js';
7
- export { M as MadauthUser } from './user-BMWEWREH.js';
8
- import './webhook-j5u9Kv9l.js';
5
+ import { a as Schema } from './schema-BTgDj1Xn.js';
6
+ export { F as FieldDef, b as FieldType, R as Row, S as StoreAdapter, V as Value, W as Where, m as madauthSchema } from './schema-BTgDj1Xn.js';
7
+ export { M as MadauthUser } from './user-yoGjrw4k.js';
8
+ import './webhook-DlmfG_kS.js';
9
+
10
+ /**
11
+ * The primary sign-in methods madAuth has: Google, GitHub, e-mail & password, the authenticator app on its
12
+ * own (`totp`: the e-mail address and a code from the app), and the passwordless e-mail link (`email-link`:
13
+ * the address, then the link or the code from an e-mail).
14
+ */
15
+ declare const SIGN_IN_METHODS: readonly ["google", "github", "password", "totp", "email-link"];
16
+ type SignInMethod = (typeof SIGN_IN_METHODS)[number];
17
+ /**
18
+ * Every key of the methods setting: the primary methods, and `sms`, which signs nobody in by itself: SMS
19
+ * codes as a second factor of the methods whose policy asks for one, next to the authenticator app.
20
+ */
21
+ declare const METHODS: readonly ["google", "github", "password", "totp", "email-link", "sms"];
22
+ type MethodId = (typeof METHODS)[number];
23
+ /** The methods that can ask for a second factor (a code from the authenticator app) after they succeeded. */
24
+ declare const METHODS_WITH_SECOND_FACTOR: readonly ["google", "github", "password", "email-link"];
25
+ /**
26
+ * Whether a method asks for the authenticator app as a second factor: never, when the user has set one up
27
+ * (`optional`), or always, so that a user without one sets it up at the next sign-in (`required`).
28
+ */
29
+ declare const SECOND_FACTOR_POLICIES: readonly ["none", "optional", "required"];
30
+ type SecondFactorPolicy = (typeof SECOND_FACTOR_POLICIES)[number];
31
+ /** The settings of a method that is on. `secondFactor` is for the METHODS_WITH_SECOND_FACTOR; it defaults to `none`. */
32
+ interface MethodSetting {
33
+ secondFactor?: SecondFactorPolicy;
34
+ }
35
+ /** The sign-in methods that are on, each with its settings. A method that is not listed is off. */
36
+ type MethodSettings = Partial<Record<MethodId, MethodSetting>>;
9
37
 
10
38
  /** Creates a new private ES256 JWK for MADAUTH_SIGNING_KEY. */
11
39
  declare function generateSigningKey(): Promise<JWK>;
12
40
 
13
- /** The sign-in methods madAuth has. */
14
- declare const SIGN_IN_METHODS: readonly ["google", "password"];
15
- type SignInMethod = (typeof SIGN_IN_METHODS)[number];
16
- /** Which sign-in methods are on. A method that is not mentioned is on. */
17
- type MethodSettings = Partial<Record<SignInMethod, boolean>>;
18
-
19
- /** Hash parameter that carries a sign-in error back to the app after the code flow. */
41
+ /** Hash parameter that carries a sign-in error back to the app after the redirect flow. */
20
42
  declare const REDIRECT_ERROR_PARAM = "madauth_error";
21
43
 
22
44
  /**
@@ -25,7 +47,7 @@ declare const REDIRECT_ERROR_PARAM = "madauth_error";
25
47
  */
26
48
  declare function createApp(config: MadauthConfig): Hono;
27
49
 
28
- /** The SQL table that holds a model, e.g. `madauth_user`. */
50
+ /** The SQL table that holds a model, e.g. `madauth_user`, or `madauth_recovery_code` for `recoveryCode`. */
29
51
  declare function tableName(model: string): string;
30
52
  /** The SQL column that holds a field, e.g. `email_normalized` for `emailNormalized`. */
31
53
  declare function columnName(field: string): string;
@@ -55,4 +77,4 @@ declare function parseRoles(input: unknown): string[] | null;
55
77
  */
56
78
  declare function parseClaims(input: unknown): Claims | null;
57
79
 
58
- export { ADMIN_ROLE, type Claims, MadauthConfig, type MethodSettings, REDIRECT_ERROR_PARAM, SIGN_IN_METHODS, Schema, type SignInMethod, type SqlDialect, columnName, createApp, createTablesSql, generateSigningKey, parseClaims, parseRoles, tableName, upgradeTablesSql };
80
+ export { ADMIN_ROLE, type Claims, METHODS, METHODS_WITH_SECOND_FACTOR, MadauthConfig, type MethodId, type MethodSetting, type MethodSettings, REDIRECT_ERROR_PARAM, SECOND_FACTOR_POLICIES, SIGN_IN_METHODS, Schema, type SecondFactorPolicy, type SignInMethod, type SqlDialect, columnName, createApp, createTablesSql, generateSigningKey, parseClaims, parseRoles, tableName, upgradeTablesSql };
package/dist/index.js CHANGED
@@ -3,32 +3,38 @@ import {
3
3
  createTablesSql,
4
4
  tableName,
5
5
  upgradeTablesSql
6
- } from "./chunk-56MOVFO4.js";
6
+ } from "./chunk-O2URPWA6.js";
7
7
  import {
8
8
  madauthSchema
9
- } from "./chunk-CD7Y4T66.js";
9
+ } from "./chunk-NP75Y3IV.js";
10
10
  import {
11
11
  REDIRECT_ERROR_PARAM,
12
12
  createApp
13
- } from "./chunk-DVVBIFIV.js";
14
- import "./chunk-DCDTO5LG.js";
13
+ } from "./chunk-7DHKDRGY.js";
14
+ import "./chunk-A7UYZRBL.js";
15
15
  import {
16
16
  ADMIN_ROLE,
17
17
  ConfigError,
18
+ METHODS,
19
+ METHODS_WITH_SECOND_FACTOR,
20
+ SECOND_FACTOR_POLICIES,
18
21
  SIGN_IN_METHODS,
19
22
  envVars,
20
23
  loadConfig,
21
24
  parseClaims,
22
25
  parseRoles
23
- } from "./chunk-TI35AZ2U.js";
26
+ } from "./chunk-NYIEFI4B.js";
24
27
  import {
25
28
  generateSigningKey
26
29
  } from "./chunk-JDQLSL36.js";
27
- import "./chunk-3QRKWLR7.js";
30
+ import "./chunk-SISM7YUZ.js";
28
31
  export {
29
32
  ADMIN_ROLE,
30
33
  ConfigError,
34
+ METHODS,
35
+ METHODS_WITH_SECOND_FACTOR,
31
36
  REDIRECT_ERROR_PARAM,
37
+ SECOND_FACTOR_POLICIES,
32
38
  SIGN_IN_METHODS,
33
39
  columnName,
34
40
  createApp,
@@ -43,7 +43,7 @@ interface Schema {
43
43
  }
44
44
  /** The records madAuth stores. Timestamps are milliseconds since 1970. */
45
45
  declare const madauthSchema: {
46
- readonly version: 4;
46
+ readonly version: 7;
47
47
  readonly models: {
48
48
  /** Someone who signed in, whichever way: the e-mail address is the identity shared by the sign-in methods. */
49
49
  readonly user: {
@@ -69,9 +69,15 @@ declare const madauthSchema: {
69
69
  readonly sessionVersion: {
70
70
  readonly type: "number";
71
71
  };
72
+ /** When the last e-mail was sent to the user: at most one per minute. */
72
73
  readonly lastMailAt: {
73
74
  readonly type: "number";
74
75
  };
76
+ /** When the last SMS was sent to the user: at most one per minute, counted apart from the e-mails (since version 6). */
77
+ readonly lastSmsAt: {
78
+ readonly type: "number";
79
+ readonly nullable: true;
80
+ };
75
81
  /** Wrong e-mail codes in a row, counted across e-mails (since version 2). */
76
82
  readonly wrongCodes: {
77
83
  readonly type: "number";
@@ -81,12 +87,25 @@ declare const madauthSchema: {
81
87
  readonly type: "string";
82
88
  readonly nullable: true;
83
89
  };
90
+ /**
91
+ * When the user's first session started: the sign-up was complete, with every second factor the
92
+ * policy asked for. 0 until then. Empty in records from before version 7, whose sign-up counts as
93
+ * complete (since version 7).
94
+ */
95
+ readonly signedUpAt: {
96
+ readonly type: "number";
97
+ readonly nullable: true;
98
+ };
84
99
  readonly createdAt: {
85
100
  readonly type: "number";
86
101
  };
87
102
  };
88
103
  };
89
- /** How a user signs in. `key` is `password:<userId>` or `google:<sub>`; later e.g. `totp:<userId>`. */
104
+ /**
105
+ * How a user signs in. `key` is `password:<userId>`, `google:<sub>`, `totp:<userId>` (the authenticator
106
+ * app, whose `secret` is encrypted), `email-link:<userId>` or `sms:<userId>` (the phone that gets the
107
+ * codes of the second factor).
108
+ */
90
109
  readonly account: {
91
110
  readonly fields: {
92
111
  readonly id: {
@@ -116,12 +135,69 @@ declare const madauthSchema: {
116
135
  readonly type: "string";
117
136
  readonly nullable: true;
118
137
  };
138
+ /** The time step of the last authenticator code that was accepted, so a code works once; 0 before (since version 5). */
139
+ readonly lastUsedStep: {
140
+ readonly type: "number";
141
+ };
142
+ /**
143
+ * The setup an authenticator secret came from; its recovery codes carry the same id, so the app and
144
+ * its codes always belong together. Empty for other accounts (since version 5).
145
+ */
146
+ readonly setupId: {
147
+ readonly type: "string";
148
+ readonly nullable: true;
149
+ };
150
+ /** The phone number of an `sms:` account, in E.164 form (`+41791234567`). Empty for other accounts (since version 6). */
151
+ readonly phone: {
152
+ readonly type: "string";
153
+ readonly nullable: true;
154
+ };
155
+ /**
156
+ * The user's id when the account is how they sign in (their one primary method), empty for a second
157
+ * factor. Unique, so a user has one primary method at most (since version 7; empty in older records).
158
+ */
159
+ readonly primaryUserId: {
160
+ readonly type: "string";
161
+ readonly nullable: true;
162
+ readonly unique: true;
163
+ };
164
+ /**
165
+ * Whether the account is a second factor (an authenticator app that is a step of the user's sign-in
166
+ * method, or a phone for SMS codes) rather than a sign-in method. Empty in records from before version 7,
167
+ * which madAuth tells apart by their key (since version 7).
168
+ */
169
+ readonly secondFactor: {
170
+ readonly type: "boolean";
171
+ readonly nullable: true;
172
+ };
173
+ readonly createdAt: {
174
+ readonly type: "number";
175
+ };
176
+ };
177
+ };
178
+ /**
179
+ * A recovery code of a user's authenticator app (since version 5). `id` is the code's keyed hash; the
180
+ * record goes when the code is used. It works only while the account's `setupId` is its own.
181
+ */
182
+ readonly recoveryCode: {
183
+ readonly fields: {
184
+ readonly id: {
185
+ readonly type: "string";
186
+ readonly primaryKey: true;
187
+ };
188
+ readonly userId: {
189
+ readonly type: "string";
190
+ readonly index: true;
191
+ };
192
+ readonly setupId: {
193
+ readonly type: "string";
194
+ };
119
195
  readonly createdAt: {
120
196
  readonly type: "number";
121
197
  };
122
198
  };
123
199
  };
124
- /** A pending e-mail verification or password reset. `id` is the SHA-256 of the link token. */
200
+ /** A pending e-mail verification, password reset, sign-in link or SMS code. `id` is the SHA-256 of the link token. */
125
201
  readonly verification: {
126
202
  readonly fields: {
127
203
  readonly id: {
package/dist/sqlite.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  createTablesSql,
4
4
  tableName,
5
5
  upgradeTablesSql
6
- } from "./chunk-56MOVFO4.js";
6
+ } from "./chunk-O2URPWA6.js";
7
7
  import {
8
8
  madauthSchema
9
- } from "./chunk-CD7Y4T66.js";
9
+ } from "./chunk-NP75Y3IV.js";
10
10
 
11
11
  // src/store/sqlite.ts
12
12
  function createSqliteAdapter(path) {