@prabhask5/stellar-engine 1.1.7 → 1.1.9

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 (191) hide show
  1. package/README.md +12 -18
  2. package/dist/actions/remoteChange.d.ts +143 -18
  3. package/dist/actions/remoteChange.d.ts.map +1 -1
  4. package/dist/actions/remoteChange.js +182 -58
  5. package/dist/actions/remoteChange.js.map +1 -1
  6. package/dist/actions/truncateTooltip.d.ts +26 -12
  7. package/dist/actions/truncateTooltip.d.ts.map +1 -1
  8. package/dist/actions/truncateTooltip.js +89 -34
  9. package/dist/actions/truncateTooltip.js.map +1 -1
  10. package/dist/auth/crypto.d.ts +35 -8
  11. package/dist/auth/crypto.d.ts.map +1 -1
  12. package/dist/auth/crypto.js +38 -10
  13. package/dist/auth/crypto.js.map +1 -1
  14. package/dist/auth/deviceVerification.d.ts +236 -20
  15. package/dist/auth/deviceVerification.d.ts.map +1 -1
  16. package/dist/auth/deviceVerification.js +293 -40
  17. package/dist/auth/deviceVerification.js.map +1 -1
  18. package/dist/auth/displayUtils.d.ts +98 -0
  19. package/dist/auth/displayUtils.d.ts.map +1 -0
  20. package/dist/auth/displayUtils.js +133 -0
  21. package/dist/auth/displayUtils.js.map +1 -0
  22. package/dist/auth/loginGuard.d.ts +103 -16
  23. package/dist/auth/loginGuard.d.ts.map +1 -1
  24. package/dist/auth/loginGuard.js +163 -76
  25. package/dist/auth/loginGuard.js.map +1 -1
  26. package/dist/auth/offlineCredentials.d.ts +88 -24
  27. package/dist/auth/offlineCredentials.d.ts.map +1 -1
  28. package/dist/auth/offlineCredentials.js +114 -73
  29. package/dist/auth/offlineCredentials.js.map +1 -1
  30. package/dist/auth/offlineSession.d.ts +83 -9
  31. package/dist/auth/offlineSession.d.ts.map +1 -1
  32. package/dist/auth/offlineSession.js +104 -13
  33. package/dist/auth/offlineSession.js.map +1 -1
  34. package/dist/auth/resolveAuthState.d.ts +67 -9
  35. package/dist/auth/resolveAuthState.d.ts.map +1 -1
  36. package/dist/auth/resolveAuthState.js +125 -71
  37. package/dist/auth/resolveAuthState.js.map +1 -1
  38. package/dist/auth/singleUser.d.ts +390 -37
  39. package/dist/auth/singleUser.d.ts.map +1 -1
  40. package/dist/auth/singleUser.js +504 -103
  41. package/dist/auth/singleUser.js.map +1 -1
  42. package/dist/bin/install-pwa.d.ts +18 -2
  43. package/dist/bin/install-pwa.d.ts.map +1 -1
  44. package/dist/bin/install-pwa.js +2624 -77
  45. package/dist/bin/install-pwa.js.map +1 -1
  46. package/dist/config.d.ts +131 -15
  47. package/dist/config.d.ts.map +1 -1
  48. package/dist/config.js +87 -9
  49. package/dist/config.js.map +1 -1
  50. package/dist/conflicts.d.ts +246 -23
  51. package/dist/conflicts.d.ts.map +1 -1
  52. package/dist/conflicts.js +495 -46
  53. package/dist/conflicts.js.map +1 -1
  54. package/dist/data.d.ts +338 -18
  55. package/dist/data.d.ts.map +1 -1
  56. package/dist/data.js +385 -34
  57. package/dist/data.js.map +1 -1
  58. package/dist/database.d.ts +72 -14
  59. package/dist/database.d.ts.map +1 -1
  60. package/dist/database.js +120 -29
  61. package/dist/database.js.map +1 -1
  62. package/dist/debug.d.ts +77 -1
  63. package/dist/debug.d.ts.map +1 -1
  64. package/dist/debug.js +88 -1
  65. package/dist/debug.js.map +1 -1
  66. package/dist/deviceId.d.ts +38 -7
  67. package/dist/deviceId.d.ts.map +1 -1
  68. package/dist/deviceId.js +68 -10
  69. package/dist/deviceId.js.map +1 -1
  70. package/dist/engine.d.ts +175 -3
  71. package/dist/engine.d.ts.map +1 -1
  72. package/dist/engine.js +756 -109
  73. package/dist/engine.js.map +1 -1
  74. package/dist/entries/actions.d.ts +13 -0
  75. package/dist/entries/actions.d.ts.map +1 -1
  76. package/dist/entries/actions.js +26 -1
  77. package/dist/entries/actions.js.map +1 -1
  78. package/dist/entries/auth.d.ts +15 -4
  79. package/dist/entries/auth.d.ts.map +1 -1
  80. package/dist/entries/auth.js +47 -4
  81. package/dist/entries/auth.js.map +1 -1
  82. package/dist/entries/config.d.ts +12 -0
  83. package/dist/entries/config.d.ts.map +1 -1
  84. package/dist/entries/config.js +18 -1
  85. package/dist/entries/config.js.map +1 -1
  86. package/dist/entries/kit.d.ts +11 -0
  87. package/dist/entries/kit.d.ts.map +1 -1
  88. package/dist/entries/kit.js +52 -2
  89. package/dist/entries/kit.js.map +1 -1
  90. package/dist/entries/stores.d.ts +11 -0
  91. package/dist/entries/stores.d.ts.map +1 -1
  92. package/dist/entries/stores.js +43 -2
  93. package/dist/entries/stores.js.map +1 -1
  94. package/dist/entries/types.d.ts +10 -1
  95. package/dist/entries/types.d.ts.map +1 -1
  96. package/dist/entries/types.js +10 -0
  97. package/dist/entries/types.js.map +1 -1
  98. package/dist/entries/utils.d.ts +6 -0
  99. package/dist/entries/utils.d.ts.map +1 -1
  100. package/dist/entries/utils.js +22 -1
  101. package/dist/entries/utils.js.map +1 -1
  102. package/dist/entries/vite.d.ts +17 -0
  103. package/dist/entries/vite.d.ts.map +1 -1
  104. package/dist/entries/vite.js +24 -1
  105. package/dist/entries/vite.js.map +1 -1
  106. package/dist/index.d.ts +32 -4
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +166 -23
  109. package/dist/index.js.map +1 -1
  110. package/dist/kit/auth.d.ts +60 -5
  111. package/dist/kit/auth.d.ts.map +1 -1
  112. package/dist/kit/auth.js +45 -4
  113. package/dist/kit/auth.js.map +1 -1
  114. package/dist/kit/confirm.d.ts +93 -12
  115. package/dist/kit/confirm.d.ts.map +1 -1
  116. package/dist/kit/confirm.js +103 -16
  117. package/dist/kit/confirm.js.map +1 -1
  118. package/dist/kit/loads.d.ts +148 -23
  119. package/dist/kit/loads.d.ts.map +1 -1
  120. package/dist/kit/loads.js +136 -28
  121. package/dist/kit/loads.js.map +1 -1
  122. package/dist/kit/server.d.ts +142 -10
  123. package/dist/kit/server.d.ts.map +1 -1
  124. package/dist/kit/server.js +158 -15
  125. package/dist/kit/server.js.map +1 -1
  126. package/dist/kit/sw.d.ts +152 -23
  127. package/dist/kit/sw.d.ts.map +1 -1
  128. package/dist/kit/sw.js +182 -26
  129. package/dist/kit/sw.js.map +1 -1
  130. package/dist/queue.d.ts +274 -0
  131. package/dist/queue.d.ts.map +1 -1
  132. package/dist/queue.js +556 -38
  133. package/dist/queue.js.map +1 -1
  134. package/dist/realtime.d.ts +241 -27
  135. package/dist/realtime.d.ts.map +1 -1
  136. package/dist/realtime.js +633 -109
  137. package/dist/realtime.js.map +1 -1
  138. package/dist/runtime/runtimeConfig.d.ts +91 -8
  139. package/dist/runtime/runtimeConfig.d.ts.map +1 -1
  140. package/dist/runtime/runtimeConfig.js +146 -19
  141. package/dist/runtime/runtimeConfig.js.map +1 -1
  142. package/dist/stores/authState.d.ts +150 -11
  143. package/dist/stores/authState.d.ts.map +1 -1
  144. package/dist/stores/authState.js +169 -17
  145. package/dist/stores/authState.js.map +1 -1
  146. package/dist/stores/network.d.ts +39 -0
  147. package/dist/stores/network.d.ts.map +1 -1
  148. package/dist/stores/network.js +169 -16
  149. package/dist/stores/network.js.map +1 -1
  150. package/dist/stores/remoteChanges.d.ts +327 -52
  151. package/dist/stores/remoteChanges.d.ts.map +1 -1
  152. package/dist/stores/remoteChanges.js +337 -75
  153. package/dist/stores/remoteChanges.js.map +1 -1
  154. package/dist/stores/sync.d.ts +130 -0
  155. package/dist/stores/sync.d.ts.map +1 -1
  156. package/dist/stores/sync.js +167 -7
  157. package/dist/stores/sync.js.map +1 -1
  158. package/dist/supabase/auth.d.ts +186 -46
  159. package/dist/supabase/auth.d.ts.map +1 -1
  160. package/dist/supabase/auth.js +238 -190
  161. package/dist/supabase/auth.js.map +1 -1
  162. package/dist/supabase/client.d.ts +79 -6
  163. package/dist/supabase/client.d.ts.map +1 -1
  164. package/dist/supabase/client.js +158 -15
  165. package/dist/supabase/client.js.map +1 -1
  166. package/dist/supabase/validate.d.ts +101 -7
  167. package/dist/supabase/validate.d.ts.map +1 -1
  168. package/dist/supabase/validate.js +117 -8
  169. package/dist/supabase/validate.js.map +1 -1
  170. package/dist/sw/build/vite-plugin.d.ts +55 -10
  171. package/dist/sw/build/vite-plugin.d.ts.map +1 -1
  172. package/dist/sw/build/vite-plugin.js +77 -18
  173. package/dist/sw/build/vite-plugin.js.map +1 -1
  174. package/dist/sw/sw.js +99 -44
  175. package/dist/types.d.ts +150 -26
  176. package/dist/types.d.ts.map +1 -1
  177. package/dist/types.js +12 -10
  178. package/dist/types.js.map +1 -1
  179. package/dist/utils.d.ts +55 -13
  180. package/dist/utils.d.ts.map +1 -1
  181. package/dist/utils.js +83 -22
  182. package/dist/utils.js.map +1 -1
  183. package/package.json +1 -1
  184. package/dist/auth/admin.d.ts +0 -12
  185. package/dist/auth/admin.d.ts.map +0 -1
  186. package/dist/auth/admin.js +0 -26
  187. package/dist/auth/admin.js.map +0 -1
  188. package/dist/auth/offlineLogin.d.ts +0 -34
  189. package/dist/auth/offlineLogin.d.ts.map +0 -1
  190. package/dist/auth/offlineLogin.js +0 -75
  191. package/dist/auth/offlineLogin.js.map +0 -1
@@ -1,42 +1,161 @@
1
1
  /**
2
- * Single-User Auth Module
2
+ * @fileoverview Single-User Authentication Module
3
3
  *
4
- * Uses Supabase email/password auth where the PIN *is* the password (padded).
5
- * Replaces the previous anonymous auth + client-side SHA-256 hash approach.
4
+ * Provides the complete authentication lifecycle for single-user mode, where a
5
+ * single user account is tied to the application instance. This module handles
6
+ * setup, unlock (login), locking, gate (PIN/password) changes, email changes,
7
+ * profile updates, multi-device linking, and full account reset.
6
8
  *
7
- * - Setup: signUp() with email + padded PIN
8
- * - Unlock: signInWithPassword() with email + padded PIN
9
- * - Device verification: signInWithOtp() for untrusted devices
10
- * - Offline fallback: cached credentials in IndexedDB
9
+ * ## Architecture
10
+ *
11
+ * Authentication is backed by Supabase email/password auth, where the user's
12
+ * PIN or password is padded (via {@link padPin}) to meet Supabase's minimum
13
+ * password length requirement. A local IndexedDB config store
14
+ * (`singleUserConfig` table) mirrors essential auth metadata for offline
15
+ * fallback and fast reads.
16
+ *
17
+ * ## Auth Flow Summary
18
+ *
19
+ * 1. **Setup** ({@link setupSingleUser}): Creates a Supabase user with
20
+ * `signUp()`. Optionally requires email confirmation.
21
+ * 2. **Unlock** ({@link unlockSingleUser}): Authenticates via
22
+ * `signInWithPassword()`. If device verification is enabled, untrusted
23
+ * devices are challenged with an OTP email before being granted a session.
24
+ * 3. **Offline fallback**: When offline, credentials are verified against a
25
+ * locally-cached SHA-256 hash of the gate. A cached Supabase session is
26
+ * restored if available; otherwise, a synthetic offline session is created.
27
+ * 4. **Lock** ({@link lockSingleUser}): Stops the sync engine and clears
28
+ * in-memory auth state, but preserves the Supabase session and local data.
29
+ *
30
+ * ## Security Considerations
31
+ *
32
+ * - **PIN padding**: PINs are short by design. The {@link padPin} function
33
+ * appends an app-specific suffix to meet Supabase's 6-character minimum,
34
+ * but the effective entropy remains that of the original PIN.
35
+ * - **Offline hash**: The gate hash stored in IndexedDB uses SHA-256 via the
36
+ * Web Crypto API. This is a convenience fallback, NOT a substitute for
37
+ * server-side verification. An attacker with IndexedDB access could
38
+ * brute-force a short PIN.
39
+ * - **Rate limiting**: The {@link preCheckLogin} guard provides client-side
40
+ * rate limiting to slow down brute-force attempts. Server-side rate limiting
41
+ * is handled by Supabase.
42
+ * - **Device verification**: When enabled, untrusted devices must verify via
43
+ * an email OTP before a session is granted. See {@link deviceVerification}.
44
+ *
45
+ * @module singleUser
46
+ * @see {@link deviceVerification} for the device trust and OTP verification layer
47
+ * @see {@link offlineCredentials} for cached credential management
48
+ * @see {@link offlineSession} for synthetic offline session creation
49
+ * @see {@link loginGuard} for pre-check rate limiting
11
50
  */
12
51
  import type { SingleUserConfig } from '../types';
13
52
  /**
14
53
  * Pad a PIN to meet Supabase's minimum password length.
15
- * e.g. "1234" → "1234_stellar" (12 chars, well above the 6-char minimum)
54
+ *
55
+ * Supabase requires passwords of at least 6 characters. Since PINs can be as
56
+ * short as 4 digits, this function appends an app-specific prefix as a suffix
57
+ * to reach a safe length.
58
+ *
59
+ * @param pin - The raw PIN/password entered by the user.
60
+ * @returns The padded string suitable for use as a Supabase password.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * // With default prefix 'app':
65
+ * padPin('1234'); // => '1234_app'
66
+ *
67
+ * // With custom prefix 'stellar':
68
+ * padPin('1234'); // => '1234_stellar'
69
+ * ```
70
+ *
71
+ * @security The padding increases character length but does NOT increase
72
+ * entropy. The suffix is deterministic and app-wide.
16
73
  */
17
74
  export declare function padPin(pin: string): string;
18
75
  /**
19
76
  * Check if single-user mode has been set up (config exists in IndexedDB).
77
+ *
78
+ * This is a lightweight read used by the UI to decide whether to show the
79
+ * setup screen or the unlock screen.
80
+ *
81
+ * @returns `true` if a single-user config record exists, `false` otherwise.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * if (await isSingleUserSetUp()) {
86
+ * showUnlockScreen();
87
+ * } else {
88
+ * showSetupScreen();
89
+ * }
90
+ * ```
20
91
  */
21
92
  export declare function isSingleUserSetUp(): Promise<boolean>;
22
93
  /**
23
94
  * Get non-sensitive display info about the single user.
24
- * Returns null if not set up.
95
+ *
96
+ * Returns profile data, gate type, code length, and a masked email suitable
97
+ * for display in the UI. Does NOT return the gate hash or any secrets.
98
+ *
99
+ * @returns An object with display-safe user info, or `null` if not set up.
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * const info = await getSingleUserInfo();
104
+ * if (info) {
105
+ * console.log(info.maskedEmail); // "pr••••@gmail.com"
106
+ * console.log(info.gateType); // "code"
107
+ * }
108
+ * ```
25
109
  */
26
110
  export declare function getSingleUserInfo(): Promise<{
111
+ /** Arbitrary user profile data (name, avatar, etc.). */
27
112
  profile: Record<string, unknown>;
113
+ /** The type of gate: 'code' for numeric PIN, 'password' for freeform. */
28
114
  gateType: SingleUserConfig['gateType'];
115
+ /** Length of the numeric code (4 or 6), if gateType is 'code'. */
29
116
  codeLength?: 4 | 6;
117
+ /** The raw email address (included for internal use). */
30
118
  email?: string;
119
+ /** The masked email for safe display (e.g. "pr••••@gmail.com"). */
31
120
  maskedEmail?: string;
32
121
  } | null>;
33
122
  /**
34
- * First-time setup: create Supabase user with email/password auth.
123
+ * First-time setup: create a Supabase user with email/password auth.
124
+ *
125
+ * This is the entry point for new users. It creates a Supabase account using
126
+ * `signUp()`, stores a local config in IndexedDB, and optionally requires
127
+ * email confirmation before granting a session.
128
+ *
129
+ * ## Online vs Offline
130
+ *
131
+ * - **Online**: Creates a real Supabase user, caches offline credentials,
132
+ * trusts the current device, and sets up the auth state.
133
+ * - **Offline**: Creates a temporary local-only setup with a random UUID as
134
+ * the user ID. The real Supabase account will be created when the user
135
+ * comes back online (handled by the sync engine).
136
+ *
137
+ * @param gate - The PIN or password chosen by the user.
138
+ * @param profile - Arbitrary profile data (e.g., `{ name: 'Alice' }`).
139
+ * @param email - The user's email address for Supabase auth.
140
+ * @returns An object with `error` (string or null) and `confirmationRequired`
141
+ * (true if the caller should show a "check your email" modal).
35
142
  *
36
- * Uses signUp() which sends a confirmation email if emailConfirmation is enabled.
37
- * The PIN is padded to meet Supabase's minimum password length.
143
+ * @throws Never throws directly; all errors are caught and returned in the
144
+ * `error` field.
38
145
  *
39
- * @returns confirmationRequired — true if the caller should show a "check your email" modal
146
+ * @example
147
+ * ```ts
148
+ * const result = await setupSingleUser('1234', { name: 'Alice' }, 'alice@example.com');
149
+ * if (result.error) {
150
+ * showError(result.error);
151
+ * } else if (result.confirmationRequired) {
152
+ * showEmailConfirmationModal();
153
+ * } else {
154
+ * navigateToHome();
155
+ * }
156
+ * ```
157
+ *
158
+ * @see {@link completeSingleUserSetup} for finalizing after email confirmation
40
159
  */
41
160
  export declare function setupSingleUser(gate: string, profile: Record<string, unknown>, email: string): Promise<{
42
161
  error: string | null;
@@ -44,15 +163,62 @@ export declare function setupSingleUser(gate: string, profile: Record<string, un
44
163
  }>;
45
164
  /**
46
165
  * Complete setup after email confirmation succeeds.
47
- * Called when the original tab receives AUTH_CONFIRMED via BroadcastChannel.
166
+ *
167
+ * Called when the original tab receives an `AUTH_CONFIRMED` message via
168
+ * BroadcastChannel. At this point, Supabase has confirmed the email and a
169
+ * session should be available. This function caches offline credentials,
170
+ * creates an offline session, and trusts the current device.
171
+ *
172
+ * @returns An object with `error` (string or null).
173
+ *
174
+ * @throws Never throws directly; all errors are caught and returned.
175
+ *
176
+ * @see {@link setupSingleUser} for the initial setup that triggers confirmation
48
177
  */
49
178
  export declare function completeSingleUserSetup(): Promise<{
50
179
  error: string | null;
51
180
  }>;
52
181
  /**
53
- * Unlock: verify PIN via signInWithPassword, handle device verification.
182
+ * Unlock (login) the single-user account by verifying the PIN/password.
183
+ *
184
+ * ## Online Flow
185
+ *
186
+ * 1. Pre-check via {@link preCheckLogin} (client-side rate limiting).
187
+ * 2. Authenticate with Supabase `signInWithPassword()`.
188
+ * 3. If device verification is enabled and this device is untrusted, trigger
189
+ * an OTP email and return `deviceVerificationRequired: true`.
190
+ * 4. Otherwise, cache credentials, update offline session, refresh the local
191
+ * gate hash, and set auth state.
192
+ *
193
+ * ## Offline Flow
194
+ *
195
+ * 1. Verify the gate against the locally-stored SHA-256 hash.
196
+ * 2. Attempt to restore a cached Supabase session.
197
+ * 3. If no cached session, create a synthetic offline session.
198
+ *
199
+ * @param gate - The PIN or password entered by the user.
200
+ * @returns An object containing:
201
+ * - `error`: Error message or null on success.
202
+ * - `deviceVerificationRequired`: True if the UI should show OTP verification.
203
+ * - `maskedEmail`: Masked email for display during device verification.
204
+ * - `retryAfterMs`: Milliseconds to wait before retrying (rate-limited).
54
205
  *
55
- * Returns deviceVerificationRequired if the device is untrusted.
206
+ * @throws Never throws directly; all errors are caught and returned.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * const result = await unlockSingleUser('1234');
211
+ * if (result.error) {
212
+ * showError(result.error);
213
+ * } else if (result.deviceVerificationRequired) {
214
+ * showDeviceVerificationModal(result.maskedEmail);
215
+ * } else {
216
+ * navigateToHome();
217
+ * }
218
+ * ```
219
+ *
220
+ * @see {@link completeDeviceVerification} for finishing the OTP flow
221
+ * @see {@link lockSingleUser} for the reverse operation
56
222
  */
57
223
  export declare function unlockSingleUser(gate: string): Promise<{
58
224
  error: string | null;
@@ -61,73 +227,244 @@ export declare function unlockSingleUser(gate: string): Promise<{
61
227
  retryAfterMs?: number;
62
228
  }>;
63
229
  /**
64
- * Complete device verification after OTP email link is clicked.
65
- * Called when the original tab receives AUTH_CONFIRMED via BroadcastChannel.
230
+ * Complete device verification after the OTP email link is clicked.
231
+ *
232
+ * This can be called in two scenarios:
233
+ * 1. **From the confirm page** (with `tokenHash`): Verifies the OTP token,
234
+ * then establishes the session.
235
+ * 2. **From the original tab** (without `tokenHash`): The confirm page has
236
+ * already verified the OTP and sent `AUTH_CONFIRMED` via BroadcastChannel.
237
+ * This function just picks up the now-available session.
238
+ *
239
+ * After verification, the current device is trusted, offline credentials are
240
+ * cached, and auth state is set.
241
+ *
242
+ * @param tokenHash - Optional OTP token hash from the email link URL. If
243
+ * provided, the token is verified against Supabase before proceeding.
244
+ * @returns An object with `error` (string or null).
245
+ *
246
+ * @throws Never throws directly; all errors are caught and returned.
247
+ *
248
+ * @see {@link unlockSingleUser} which triggers device verification
249
+ * @see {@link pollDeviceVerification} for polling-based completion
66
250
  */
67
251
  export declare function completeDeviceVerification(tokenHash?: string): Promise<{
68
252
  error: string | null;
69
253
  }>;
70
254
  /**
71
- * Poll whether this device has been trusted (e.g. after OTP verified on another device).
255
+ * Poll whether this device has been trusted after OTP verification.
256
+ *
257
+ * Used by the UI to detect when device verification has been completed on
258
+ * another device (e.g., the user opened the OTP link on their phone). The
259
+ * confirm page calls {@link trustPendingDevice}, which trusts the originating
260
+ * device. Once that happens, this poll returns `true`.
261
+ *
262
+ * Requires an active session — {@link sendDeviceVerification} keeps the
263
+ * session alive specifically for this purpose.
264
+ *
265
+ * @returns `true` if the current device is now trusted, `false` otherwise.
72
266
  *
73
- * Requires an active session (sendDeviceVerification keeps the session alive).
74
- * The confirm page calls trustPendingDevice() which trusts the originating device,
75
- * so this check will pass once verification is complete on any device.
267
+ * @example
268
+ * ```ts
269
+ * const interval = setInterval(async () => {
270
+ * if (await pollDeviceVerification()) {
271
+ * clearInterval(interval);
272
+ * await completeDeviceVerification();
273
+ * }
274
+ * }, 3000);
275
+ * ```
76
276
  */
77
277
  export declare function pollDeviceVerification(): Promise<boolean>;
78
278
  /**
79
- * Lock: stop sync engine, reset auth state to 'none'.
80
- * Does NOT destroy session, data, or sign out of Supabase.
279
+ * Lock the application: stop the sync engine and reset auth state to 'none'.
280
+ *
281
+ * This is a "soft lock" — it does NOT destroy the Supabase session, clear
282
+ * local data, or sign out. The user can unlock again with their PIN without
283
+ * needing network access (if offline credentials are cached).
284
+ *
285
+ * @example
286
+ * ```ts
287
+ * await lockSingleUser();
288
+ * navigateToLockScreen();
289
+ * ```
290
+ *
291
+ * @see {@link unlockSingleUser} for the reverse operation
292
+ * @see {@link resetSingleUser} for a full destructive reset
81
293
  */
82
294
  export declare function lockSingleUser(): Promise<void>;
83
295
  /**
84
- * Change the gate (code/password). Verifies old gate via signInWithPassword.
296
+ * Change the gate (PIN/password) for the single-user account.
297
+ *
298
+ * Verifies the old gate before accepting the new one. When online, the
299
+ * password is also updated in Supabase. When offline, only the local hash
300
+ * is updated (Supabase will be out of sync until the next online login).
301
+ *
302
+ * @param oldGate - The current PIN/password for verification.
303
+ * @param newGate - The new PIN/password to set.
304
+ * @returns An object with `error` (string or null).
305
+ *
306
+ * @throws Never throws directly; all errors are caught and returned.
307
+ *
308
+ * @security The old gate is verified either via local hash comparison or
309
+ * Supabase `signInWithPassword()` before the change is applied. This
310
+ * prevents unauthorized changes if the device is left unlocked.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * const result = await changeSingleUserGate('1234', '5678');
315
+ * if (result.error) {
316
+ * showError(result.error);
317
+ * } else {
318
+ * showSuccess('Code changed successfully');
319
+ * }
320
+ * ```
85
321
  */
86
322
  export declare function changeSingleUserGate(oldGate: string, newGate: string): Promise<{
87
323
  error: string | null;
88
324
  }>;
89
325
  /**
90
- * Update profile in IndexedDB and Supabase user_metadata.
326
+ * Update the user's profile in both IndexedDB and Supabase `user_metadata`.
327
+ *
328
+ * When online, the profile is pushed to Supabase so it's available on all
329
+ * devices. When offline, only the local config is updated (Supabase will be
330
+ * synced on the next online login via {@link unlockSingleUser}).
331
+ *
332
+ * @param profile - The new profile data to store (replaces the existing profile entirely).
333
+ * @returns An object with `error` (string or null).
334
+ *
335
+ * @throws Never throws directly; all errors are caught and returned.
336
+ *
337
+ * @example
338
+ * ```ts
339
+ * const result = await updateSingleUserProfile({ name: 'Bob', avatar: 'cat' });
340
+ * if (result.error) {
341
+ * showError(result.error);
342
+ * }
343
+ * ```
91
344
  */
92
345
  export declare function updateSingleUserProfile(profile: Record<string, unknown>): Promise<{
93
346
  error: string | null;
94
347
  }>;
95
348
  /**
96
- * Initiate an email change. Requires online state.
97
- * Supabase sends a confirmation email to the new address.
349
+ * Initiate an email change for the single-user account.
350
+ *
351
+ * Requires an active internet connection. Supabase sends a confirmation email
352
+ * to the new address. The change is not applied until the user clicks the
353
+ * confirmation link and {@link completeSingleUserEmailChange} is called.
354
+ *
355
+ * @param newEmail - The new email address to change to.
356
+ * @returns An object with `error` (string or null) and `confirmationRequired`
357
+ * (true if the caller should show a "check your email" prompt).
358
+ *
359
+ * @throws Never throws directly; all errors are caught and returned.
360
+ *
361
+ * @see {@link completeSingleUserEmailChange} for finalizing the change
98
362
  */
99
363
  export declare function changeSingleUserEmail(newEmail: string): Promise<{
100
364
  error: string | null;
101
365
  confirmationRequired: boolean;
102
366
  }>;
103
367
  /**
104
- * Complete email change after the user confirms via the email link.
105
- * Called when the original tab receives AUTH_CONFIRMED with type 'email_change'.
368
+ * Complete an email change after the user confirms via the email link.
369
+ *
370
+ * Called when the original tab receives `AUTH_CONFIRMED` with type
371
+ * `email_change`. Refreshes the Supabase session to pick up the new email,
372
+ * then updates IndexedDB config and offline credentials.
373
+ *
374
+ * @returns An object with `error` (string or null) and `newEmail` (the
375
+ * confirmed new email, or null on error).
376
+ *
377
+ * @throws Never throws directly; all errors are caught and returned.
378
+ *
379
+ * @see {@link changeSingleUserEmail} for initiating the change
106
380
  */
107
381
  export declare function completeSingleUserEmailChange(): Promise<{
108
382
  error: string | null;
109
383
  newEmail: string | null;
110
384
  }>;
111
385
  /**
112
- * Full reset: clear config, sign out of Supabase, clear all data.
386
+ * Full reset: clear config, sign out of Supabase, and clear all local data.
387
+ *
388
+ * This is a destructive operation that removes the single-user config from
389
+ * IndexedDB and signs out of Supabase (which clears the session and all
390
+ * local auth state). After this, the app returns to the initial setup state.
391
+ *
392
+ * @returns An object with `error` (string or null).
393
+ *
394
+ * @throws Never throws directly; all errors are caught and returned.
395
+ *
396
+ * @security This clears auth state but does NOT delete the Supabase user
397
+ * account or any server-side data. Use {@link resetSingleUserRemote} for
398
+ * a full server-side reset.
399
+ *
400
+ * @see {@link resetSingleUserRemote} for server-side account deletion
113
401
  */
114
402
  export declare function resetSingleUser(): Promise<{
115
403
  error: string | null;
116
404
  }>;
117
405
  /**
118
- * Fetch remote gate config via the get_extension_config() RPC.
119
- * Returns user info if a user exists in Supabase, null otherwise.
120
- * Works without authentication (uses anon key).
406
+ * Fetch remote gate configuration via the `get_extension_config()` Supabase RPC.
407
+ *
408
+ * Returns user info if a user exists in the Supabase project, `null` otherwise.
409
+ * This is used by browser extensions and new devices to discover the existing
410
+ * account before linking. Works without authentication (uses the anon key).
411
+ *
412
+ * @returns An object with `email`, `gateType`, `codeLength`, and `profile`,
413
+ * or `null` if no user exists or the RPC fails.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * const remote = await fetchRemoteGateConfig();
418
+ * if (remote) {
419
+ * // Account exists — show link-device screen
420
+ * showLinkDeviceScreen(remote.email, remote.gateType);
421
+ * } else {
422
+ * // No account — show setup screen
423
+ * showSetupScreen();
424
+ * }
425
+ * ```
426
+ *
427
+ * @see {@link linkSingleUserDevice} for linking after discovery
121
428
  */
122
429
  export declare function fetchRemoteGateConfig(): Promise<{
430
+ /** The user's email address. */
123
431
  email: string;
432
+ /** The gate type ('code' or 'password'). */
124
433
  gateType: string;
434
+ /** The numeric code length (4 or 6). */
125
435
  codeLength: number;
436
+ /** The user's profile metadata. */
126
437
  profile: Record<string, unknown>;
127
438
  } | null>;
128
439
  /**
129
440
  * Link a new device to an existing single-user account.
130
- * Signs in with email + padded PIN, builds local config from user_metadata.
441
+ *
442
+ * Signs in with the provided email and PIN via Supabase `signInWithPassword()`,
443
+ * then builds and stores a local config from the user's `user_metadata`. If
444
+ * device verification is enabled, untrusted devices are challenged with an OTP.
445
+ *
446
+ * This is the multi-device counterpart to {@link setupSingleUser}: setup
447
+ * creates the account, while link joins an existing one from a new device.
448
+ *
449
+ * @param email - The email address of the existing account.
450
+ * @param pin - The PIN/password to authenticate with.
451
+ * @returns An object containing:
452
+ * - `error`: Error message or null on success.
453
+ * - `deviceVerificationRequired`: True if OTP verification is needed.
454
+ * - `maskedEmail`: Masked email for display during device verification.
455
+ * - `retryAfterMs`: Milliseconds to wait before retrying (rate-limited).
456
+ *
457
+ * @throws Never throws directly; all errors are caught and returned.
458
+ *
459
+ * @example
460
+ * ```ts
461
+ * const result = await linkSingleUserDevice('alice@example.com', '1234');
462
+ * if (result.deviceVerificationRequired) {
463
+ * showOtpModal(result.maskedEmail);
464
+ * }
465
+ * ```
466
+ *
467
+ * @see {@link fetchRemoteGateConfig} for discovering the account to link to
131
468
  */
132
469
  export declare function linkSingleUserDevice(email: string, pin: string): Promise<{
133
470
  error: string | null;
@@ -136,8 +473,24 @@ export declare function linkSingleUserDevice(email: string, pin: string): Promis
136
473
  retryAfterMs?: number;
137
474
  }>;
138
475
  /**
139
- * Reset the remote single user via the reset_single_user() RPC.
140
- * Also clears all local auth state (IndexedDB + localStorage).
476
+ * Reset the remote single-user account via the `reset_single_user()` Supabase RPC.
477
+ *
478
+ * This is a full destructive reset that:
479
+ * 1. Calls the server-side `reset_single_user()` RPC to delete the user account.
480
+ * 2. Signs out of Supabase to clear the in-memory session.
481
+ * 3. Clears all local IndexedDB state (config, offline credentials, offline session).
482
+ * 4. Removes Supabase session tokens from localStorage.
483
+ *
484
+ * After this, the app returns to its initial un-configured state on all devices.
485
+ *
486
+ * @returns An object with `error` (string or null).
487
+ *
488
+ * @throws Never throws directly; all errors are caught and returned.
489
+ *
490
+ * @security This permanently deletes the Supabase user account. The operation
491
+ * cannot be undone. The RPC should be secured with appropriate RLS policies.
492
+ *
493
+ * @see {@link resetSingleUser} for a local-only reset that preserves the server account
141
494
  */
142
495
  export declare function resetSingleUserRemote(): Promise<{
143
496
  error: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"singleUser.d.ts","sourceRoot":"","sources":["../../src/auth/singleUser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAgCjD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG1C;AAyBD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO1D;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAAC,CAUR;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,oBAAoB,EAAE,OAAO,CAAA;CAAE,CAAC,CA2HlE;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAuDjF;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC,CA0ID;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAgDnC;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAW/D;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAWpD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAuEnC;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA6CnC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,oBAAoB,EAAE,OAAO,CAAA;CAAE,CAAC,CA4BlE;AAED;;;GAGG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC;IAC7D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC,CAmDD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAkBzE;AAMD;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,GAAG,IAAI,CAAC,CAoBR;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IACT,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC,CA+FD;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAyC/E"}
1
+ {"version":3,"file":"singleUser.d.ts","sourceRoot":"","sources":["../../src/auth/singleUser.ts"],"names":[],"mappings":"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"}