@evolu/common 6.0.1-preview.8 → 7.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 (184) hide show
  1. package/README.md +2 -2
  2. package/dist/src/Array.d.ts +256 -12
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +215 -9
  5. package/dist/src/Assert.d.ts +0 -13
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +0 -15
  8. package/dist/src/Brand.d.ts +75 -0
  9. package/dist/src/Brand.d.ts.map +1 -0
  10. package/dist/src/Brand.js +1 -0
  11. package/dist/src/Buffer.d.ts +1 -1
  12. package/dist/src/Buffer.d.ts.map +1 -1
  13. package/dist/src/Buffer.js +8 -7
  14. package/dist/src/Cache.d.ts +44 -0
  15. package/dist/src/Cache.d.ts.map +1 -0
  16. package/dist/src/Cache.js +52 -0
  17. package/dist/src/Callbacks.d.ts +45 -12
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Callbacks.js +14 -7
  20. package/dist/src/Console.d.ts +31 -6
  21. package/dist/src/Console.d.ts.map +1 -1
  22. package/dist/src/Console.js +72 -9
  23. package/dist/src/Crypto.d.ts +56 -42
  24. package/dist/src/Crypto.d.ts.map +1 -1
  25. package/dist/src/Crypto.js +40 -53
  26. package/dist/src/Evolu/Db.d.ts +162 -74
  27. package/dist/src/Evolu/Db.d.ts.map +1 -1
  28. package/dist/src/Evolu/Db.js +284 -702
  29. package/dist/src/Evolu/Diff.d.ts +3 -3
  30. package/dist/src/Evolu/Diff.d.ts.map +1 -1
  31. package/dist/src/Evolu/Diff.js +7 -5
  32. package/dist/src/Evolu/Evolu.d.ts +214 -134
  33. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  34. package/dist/src/Evolu/Evolu.js +189 -180
  35. package/dist/src/Evolu/Internal.d.ts +0 -2
  36. package/dist/src/Evolu/Internal.d.ts.map +1 -1
  37. package/dist/src/Evolu/Internal.js +0 -2
  38. package/dist/src/Evolu/LocalAuth.d.ts +150 -0
  39. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
  40. package/dist/src/Evolu/LocalAuth.js +174 -0
  41. package/dist/src/Evolu/Owner.d.ts +273 -120
  42. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  43. package/dist/src/Evolu/Owner.js +130 -104
  44. package/dist/src/Evolu/Platform.d.ts +9 -7
  45. package/dist/src/Evolu/Platform.d.ts.map +1 -1
  46. package/dist/src/Evolu/Protocol.d.ts +268 -240
  47. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  48. package/dist/src/Evolu/Protocol.js +600 -454
  49. package/dist/src/Evolu/Public.d.ts +6 -8
  50. package/dist/src/Evolu/Public.d.ts.map +1 -1
  51. package/dist/src/Evolu/Public.js +2 -3
  52. package/dist/src/Evolu/PublicKysely.d.ts.map +1 -1
  53. package/dist/src/Evolu/PublicKysely.js +3 -4
  54. package/dist/src/Evolu/Query.d.ts +2 -1
  55. package/dist/src/Evolu/Query.d.ts.map +1 -1
  56. package/dist/src/Evolu/Query.js +1 -1
  57. package/dist/src/Evolu/Relay.d.ts +91 -8
  58. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  59. package/dist/src/Evolu/Relay.js +214 -88
  60. package/dist/src/Evolu/Schema.d.ts +125 -47
  61. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  62. package/dist/src/Evolu/Schema.js +175 -31
  63. package/dist/src/Evolu/Storage.d.ts +249 -27
  64. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  65. package/dist/src/Evolu/Storage.js +198 -92
  66. package/dist/src/Evolu/Sync.d.ts +68 -13
  67. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  68. package/dist/src/Evolu/Sync.js +469 -20
  69. package/dist/src/Evolu/Timestamp.d.ts +83 -30
  70. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  71. package/dist/src/Evolu/Timestamp.js +79 -34
  72. package/dist/src/Identicon.d.ts +35 -0
  73. package/dist/src/Identicon.d.ts.map +1 -0
  74. package/dist/src/Identicon.js +143 -0
  75. package/dist/src/Instances.d.ts +34 -0
  76. package/dist/src/Instances.d.ts.map +1 -0
  77. package/dist/src/Instances.js +44 -0
  78. package/dist/src/Number.d.ts +4 -3
  79. package/dist/src/Number.d.ts.map +1 -1
  80. package/dist/src/Number.js +5 -4
  81. package/dist/src/Object.d.ts +10 -4
  82. package/dist/src/Object.d.ts.map +1 -1
  83. package/dist/src/Object.js +9 -3
  84. package/dist/src/Platform.d.ts +20 -0
  85. package/dist/src/Platform.d.ts.map +1 -0
  86. package/dist/src/Platform.js +22 -0
  87. package/dist/src/Random.d.ts +3 -2
  88. package/dist/src/Random.d.ts.map +1 -1
  89. package/dist/src/Relation.d.ts +79 -0
  90. package/dist/src/Relation.d.ts.map +1 -0
  91. package/dist/src/Relation.js +127 -0
  92. package/dist/src/Resources.d.ts +118 -0
  93. package/dist/src/Resources.d.ts.map +1 -0
  94. package/dist/src/Resources.js +197 -0
  95. package/dist/src/Result.d.ts +184 -52
  96. package/dist/src/Result.d.ts.map +1 -1
  97. package/dist/src/Result.js +30 -241
  98. package/dist/src/Skiplist.js +2 -1
  99. package/dist/src/Sqlite.d.ts +89 -5
  100. package/dist/src/Sqlite.d.ts.map +1 -1
  101. package/dist/src/Sqlite.js +136 -9
  102. package/dist/src/Task.d.ts +586 -0
  103. package/dist/src/Task.d.ts.map +1 -0
  104. package/dist/src/Task.js +469 -0
  105. package/dist/src/Time.d.ts +66 -1
  106. package/dist/src/Time.d.ts.map +1 -1
  107. package/dist/src/Time.js +99 -5
  108. package/dist/src/Type.d.ts +676 -343
  109. package/dist/src/Type.d.ts.map +1 -1
  110. package/dist/src/Type.js +718 -467
  111. package/dist/src/Types.d.ts +1 -75
  112. package/dist/src/Types.d.ts.map +1 -1
  113. package/dist/src/WebSocket.d.ts +5 -2
  114. package/dist/src/WebSocket.d.ts.map +1 -1
  115. package/dist/src/WebSocket.js +12 -18
  116. package/dist/src/Worker.d.ts +39 -11
  117. package/dist/src/Worker.d.ts.map +1 -1
  118. package/dist/src/Worker.js +22 -4
  119. package/dist/src/index.d.ts +8 -3
  120. package/dist/src/index.d.ts.map +1 -1
  121. package/dist/src/index.js +8 -3
  122. package/package.json +15 -14
  123. package/src/Array.ts +301 -19
  124. package/src/Assert.ts +0 -21
  125. package/src/Brand.ts +75 -0
  126. package/src/Buffer.ts +7 -7
  127. package/src/Cache.ts +85 -0
  128. package/src/Callbacks.ts +62 -22
  129. package/src/Console.ts +91 -11
  130. package/src/Crypto.ts +94 -90
  131. package/src/Evolu/Db.ts +519 -1026
  132. package/src/Evolu/Diff.ts +7 -5
  133. package/src/Evolu/Evolu.ts +477 -361
  134. package/src/Evolu/Internal.ts +0 -2
  135. package/src/Evolu/LocalAuth.ts +463 -0
  136. package/src/Evolu/Owner.ts +355 -228
  137. package/src/Evolu/Platform.ts +9 -9
  138. package/src/Evolu/Protocol.ts +842 -742
  139. package/src/Evolu/Public.ts +7 -14
  140. package/src/Evolu/PublicKysely.ts +4 -5
  141. package/src/Evolu/Query.ts +3 -2
  142. package/src/Evolu/Relay.ts +406 -103
  143. package/src/Evolu/Schema.ts +323 -91
  144. package/src/Evolu/Storage.ts +559 -137
  145. package/src/Evolu/Sync.ts +819 -36
  146. package/src/Evolu/Timestamp.ts +90 -58
  147. package/src/Identicon.ts +197 -0
  148. package/src/Instances.ts +90 -0
  149. package/src/Number.ts +6 -10
  150. package/src/Object.ts +13 -5
  151. package/src/Platform.ts +26 -0
  152. package/src/Random.ts +3 -2
  153. package/src/Relation.ts +234 -0
  154. package/src/Resources.ts +367 -0
  155. package/src/Result.ts +191 -54
  156. package/src/Skiplist.ts +1 -1
  157. package/src/Sqlite.ts +152 -17
  158. package/src/Task.ts +901 -0
  159. package/src/Time.ts +180 -5
  160. package/src/Type.ts +1135 -730
  161. package/src/Types.ts +1 -77
  162. package/src/WebSocket.ts +27 -25
  163. package/src/Worker.ts +72 -23
  164. package/src/index.ts +8 -3
  165. package/dist/src/Evolu/Config.d.ts +0 -69
  166. package/dist/src/Evolu/Config.d.ts.map +0 -1
  167. package/dist/src/Evolu/Config.js +0 -9
  168. package/dist/src/Evolu/Kysely.d.ts +0 -6
  169. package/dist/src/Evolu/Kysely.d.ts.map +0 -1
  170. package/dist/src/Evolu/Kysely.js +0 -21
  171. package/dist/src/ManyToManyMap.d.ts +0 -26
  172. package/dist/src/ManyToManyMap.d.ts.map +0 -1
  173. package/dist/src/ManyToManyMap.js +0 -92
  174. package/dist/src/NanoId.d.ts +0 -27
  175. package/dist/src/NanoId.d.ts.map +0 -1
  176. package/dist/src/NanoId.js +0 -6
  177. package/dist/src/Promise.d.ts +0 -180
  178. package/dist/src/Promise.d.ts.map +0 -1
  179. package/dist/src/Promise.js +0 -176
  180. package/src/Evolu/Config.ts +0 -83
  181. package/src/Evolu/Kysely.ts +0 -38
  182. package/src/ManyToManyMap.ts +0 -140
  183. package/src/NanoId.ts +0 -39
  184. package/src/Promise.ts +0 -295
@@ -10,11 +10,9 @@
10
10
  * @module
11
11
  */
12
12
 
13
- export * from "./Config.js";
14
13
  export * from "./Db.js";
15
14
  export * from "./Diff.js";
16
15
  export * from "./Evolu.js";
17
- export * from "./Kysely.js";
18
16
  export * from "./Owner.js";
19
17
  export * from "./Platform.js";
20
18
  export * from "./Protocol.js";
@@ -0,0 +1,463 @@
1
+ import { RandomBytesDep } from "../Crypto.js";
2
+ import { Mnemonic } from "../Type.js";
3
+ import {
4
+ AppOwner,
5
+ createAppOwner,
6
+ createOwnerSecret,
7
+ mnemonicToOwnerSecret,
8
+ OwnerEncryptionKey,
9
+ OwnerId,
10
+ OwnerWriteKey,
11
+ } from "./Owner.js";
12
+
13
+ /**
14
+ * Local authentication and authorization system for Evolu. This is API is
15
+ * subject to change and not recommended for production use.
16
+ *
17
+ * @experimental
18
+ */
19
+ export interface LocalAuth {
20
+ /** Logs in with the given owner ID, or loads the target owner if not provided. */
21
+ login: (
22
+ ownerId: OwnerId,
23
+ options?: LocalAuthOptions,
24
+ ) => Promise<AuthResult | null>;
25
+
26
+ /** Registers a new owner with the given username. */
27
+ register: (
28
+ username: string,
29
+ options?: LocalAuthOptions & { mnemonic?: Mnemonic | null },
30
+ ) => Promise<AuthResult | null>;
31
+
32
+ /** Unregisters an owner with the given owner ID. */
33
+ unregister: (ownerId: OwnerId, options?: LocalAuthOptions) => Promise<void>;
34
+
35
+ /** Gets the current owner (last logged in or last registered owner) */
36
+ getOwner: (options?: LocalAuthOptions) => Promise<AuthResult | null>;
37
+
38
+ /** Lists all registered owner ids with associated usernames. */
39
+ getProfiles: (options?: LocalAuthOptionsValues) => Promise<Array<AuthList>>;
40
+
41
+ /** Clears all owners and metadata from the local auth. */
42
+ clearAll: (options?: LocalAuthOptions) => Promise<void>;
43
+ }
44
+
45
+ export interface LocalAuthDep {
46
+ readonly localAuth: LocalAuth;
47
+ }
48
+
49
+ /**
50
+ * - **⚠️
51
+ *
52
+ * Secure storage interface that must be implemented by each platform.
53
+ */
54
+ export interface SecureStorage {
55
+ setItem: (
56
+ key: string,
57
+ value: string,
58
+ options?: LocalAuthOptions,
59
+ ) => Promise<MutationResult>;
60
+ getItem: (
61
+ key: string,
62
+ options?: LocalAuthOptionsValues,
63
+ ) => Promise<SensitiveInfoItem | null>;
64
+ deleteItem: (key: string, options?: LocalAuthOptions) => Promise<boolean>;
65
+ getAllItems: (
66
+ options?: LocalAuthOptionsValues,
67
+ ) => Promise<Array<SensitiveInfoItem>>;
68
+ clearService: (options?: LocalAuthOptions) => Promise<void>;
69
+ }
70
+
71
+ export interface SecureStorageDep {
72
+ readonly secureStorage: SecureStorage;
73
+ }
74
+
75
+ /**
76
+ * Creates a local auth using the given secure storage implementation. This
77
+ * factory function allows each platform to provide its own storage layer while
78
+ * sharing the common auth logic.
79
+ */
80
+ export const createLocalAuth = (
81
+ deps: SecureStorageDep & RandomBytesDep,
82
+ ): LocalAuth => {
83
+ const setLastOwnerId = async (
84
+ id: OwnerId,
85
+ options?: LocalAuthOptions,
86
+ ): Promise<void> => {
87
+ await deps.secureStorage.setItem(localAuthMetakeyLastOwner, id, {
88
+ ...buildAuthOptions(options),
89
+ accessControl: "none",
90
+ });
91
+ };
92
+
93
+ const getLastOwnerId = async (
94
+ options?: LocalAuthOptions,
95
+ ): Promise<OwnerId | undefined> => {
96
+ const item = await deps.secureStorage.getItem(localAuthMetakeyLastOwner, {
97
+ ...buildAuthOptions(options),
98
+ accessControl: "none",
99
+ });
100
+ return item?.value as OwnerId;
101
+ };
102
+
103
+ const getOwnerNames = async (
104
+ options?: LocalAuthOptions,
105
+ ): Promise<Record<OwnerId, string>> => {
106
+ const item = await deps.secureStorage.getItem(localAuthMetakeyOwnerNames, {
107
+ ...buildAuthOptions(options),
108
+ accessControl: "none",
109
+ });
110
+ let names: Record<OwnerId, string> = {};
111
+ if (item?.value) {
112
+ names = JSON.parse(item.value) as Record<OwnerId, string>;
113
+ }
114
+ return names;
115
+ };
116
+
117
+ const setOwnerName = async (
118
+ id: OwnerId,
119
+ username: string,
120
+ options?: LocalAuthOptions,
121
+ ): Promise<void> => {
122
+ const names = await getOwnerNames(options);
123
+ names[id] = username;
124
+ await deps.secureStorage.setItem(
125
+ localAuthMetakeyOwnerNames,
126
+ JSON.stringify(names),
127
+ {
128
+ ...buildAuthOptions(options),
129
+ accessControl: "none",
130
+ },
131
+ );
132
+ };
133
+
134
+ const deleteOwnerName = async (
135
+ id: OwnerId,
136
+ options?: LocalAuthOptions,
137
+ ): Promise<void> => {
138
+ const { [id]: _, ...names } = await getOwnerNames(options);
139
+ await deps.secureStorage.setItem(
140
+ localAuthMetakeyOwnerNames,
141
+ JSON.stringify(names),
142
+ {
143
+ ...buildAuthOptions(options),
144
+ accessControl: "none",
145
+ },
146
+ );
147
+ };
148
+
149
+ const getOwnerIds = async (
150
+ options?: LocalAuthOptions,
151
+ ): Promise<Array<OwnerId>> => {
152
+ const items = await deps.secureStorage.getAllItems({
153
+ ...buildAuthOptions(options),
154
+ includeValues: false,
155
+ });
156
+ return items
157
+ .filter(Boolean)
158
+ .filter(
159
+ (i) =>
160
+ i.key !== localAuthMetakeyLastOwner &&
161
+ i.key !== localAuthMetakeyOwnerNames,
162
+ )
163
+ .map((i) => i.key as OwnerId);
164
+ };
165
+
166
+ const clearAuthStore = (options?: LocalAuthOptions): Promise<void> =>
167
+ deps.secureStorage.clearService(buildAuthOptions(options));
168
+
169
+ const buildAuthOptions = (
170
+ options?: LocalAuthOptions,
171
+ username?: string,
172
+ ): LocalAuthOptions => {
173
+ const newOptions: LocalAuthOptions = {
174
+ ...localAuthDefaultOptions,
175
+ ...(username && { webAuthnUsername: username }),
176
+ ...options,
177
+ };
178
+ return {
179
+ ...newOptions,
180
+ authenticationPrompt: {
181
+ title: replaceMessageTokens(
182
+ newOptions.authenticationPrompt?.title ?? "",
183
+ username,
184
+ ),
185
+ cancel: replaceMessageTokens(
186
+ newOptions.authenticationPrompt?.cancel ?? "",
187
+ username,
188
+ ),
189
+ subtitle: replaceMessageTokens(
190
+ newOptions.authenticationPrompt?.subtitle ?? "",
191
+ username,
192
+ ),
193
+ description: replaceMessageTokens(
194
+ newOptions.authenticationPrompt?.description ?? "",
195
+ username,
196
+ ),
197
+ },
198
+ };
199
+ };
200
+
201
+ const replaceMessageTokens = (text: string, username?: string): string => {
202
+ if (!username) return text;
203
+ return text.replace("|USERNAME|", username);
204
+ };
205
+
206
+ return {
207
+ login: async (ownerId, options) => {
208
+ // Lookup the associated username
209
+ const names = await getOwnerNames(options);
210
+ const username = names[ownerId] ?? "";
211
+ // Currently a reload is needed. This avoids authentication
212
+ // it needs to be handled on next page load.
213
+ // We set the last owner so we know what the target is.
214
+ // It is the applications's responsibility to reload and trigger login.
215
+ await setLastOwnerId(ownerId, options);
216
+ return { owner: undefined, username };
217
+ },
218
+
219
+ register: async (username, options) => {
220
+ // Create an owner with a new secret or use specified mnemonic
221
+ const owner = createAppOwner(
222
+ options?.mnemonic
223
+ ? mnemonicToOwnerSecret(options.mnemonic)
224
+ : createOwnerSecret(deps),
225
+ );
226
+
227
+ // Store owner, associated username, and update last owner
228
+ await Promise.all([
229
+ // setOwnerItem
230
+ deps.secureStorage.setItem(
231
+ owner.id,
232
+ JSON.stringify({ owner }),
233
+ buildAuthOptions(options, username),
234
+ ),
235
+ setOwnerName(owner.id, username, options),
236
+ setLastOwnerId(owner.id, options),
237
+ ]);
238
+
239
+ // Return the owner and associated username
240
+ return { owner, username };
241
+ },
242
+
243
+ unregister: async (ownerId, options) => {
244
+ // Delete the owner and associated username
245
+ await Promise.all([
246
+ // deleteOwnerItem
247
+ deps.secureStorage.deleteItem(ownerId, buildAuthOptions(options)),
248
+ deleteOwnerName(ownerId, options),
249
+ ]);
250
+
251
+ // If the owner was the last owner then set to
252
+ // the next owner based on metadata timestamp
253
+ const lastOwnerId = await getLastOwnerId(options);
254
+ if (lastOwnerId === ownerId) {
255
+ const ids = await getOwnerIds(options);
256
+ if (ids.length > 0) {
257
+ await setLastOwnerId(ids[0], options);
258
+ }
259
+ }
260
+ },
261
+
262
+ getOwner: async (options) => {
263
+ const ownerId = await getLastOwnerId(options);
264
+ if (!ownerId) return null;
265
+
266
+ const names = await getOwnerNames(options);
267
+ const username = names[ownerId] ?? "";
268
+
269
+ // Retrieve and decrypt the owner (this will trigger device authentication)
270
+ const account = await deps.secureStorage.getItem(
271
+ ownerId,
272
+ buildAuthOptions(options, username),
273
+ );
274
+ if (!account?.value) return null;
275
+
276
+ // Unserialize the values (TODO: save these as base64 instead of json serializing)
277
+ const result = JSON.parse(account.value) as { owner: AppOwner };
278
+ const writeKey = OwnerWriteKey.orThrow(
279
+ new Uint8Array(Object.values(result.owner.writeKey)),
280
+ );
281
+ const encryptionKey = OwnerEncryptionKey.orThrow(
282
+ new Uint8Array(Object.values(result.owner.encryptionKey)),
283
+ );
284
+ const owner: AppOwner = { ...result.owner, writeKey, encryptionKey };
285
+
286
+ // Update the last owner for future login attempts
287
+ await setLastOwnerId(ownerId, options);
288
+
289
+ // Return the owner and associated username
290
+ return { owner, username };
291
+ },
292
+
293
+ getProfiles: async (options) => {
294
+ // Get all owner ids and associated usernames
295
+ const [ids, names] = await Promise.all([
296
+ getOwnerIds(options),
297
+ getOwnerNames(options),
298
+ ]);
299
+
300
+ // Return the list of profiles (usually used for login UX)
301
+ return ids.map((ownerId) => ({
302
+ ownerId,
303
+ username: names[ownerId] ?? "",
304
+ }));
305
+ },
306
+
307
+ clearAll: async (options) => {
308
+ // Delete all owners and associated metadata (scoped to the service)
309
+ await clearAuthStore(options);
310
+ },
311
+ };
312
+ };
313
+
314
+ export const localAuth_Namespace = "evolu";
315
+
316
+ export const localAuthDefaultOptions: LocalAuthOptions = {
317
+ service: localAuth_Namespace,
318
+ keychainGroup: localAuth_Namespace,
319
+ androidBiometricsStrongOnly: true,
320
+ iosSynchronizable: true,
321
+ webAuthnUsername: "Evolu User",
322
+ authenticationPrompt: {
323
+ title: "Authenticate as |USERNAME|",
324
+ },
325
+ };
326
+
327
+ const localAuthMetakeyLastOwner = "_last_owner";
328
+ const localAuthMetakeyOwnerNames = "_owner_names";
329
+
330
+ export interface AuthResult {
331
+ /** The app owner created during registration. */
332
+ readonly owner: AppOwner | undefined;
333
+ /** The name provided by the user during registration. */
334
+ readonly username: string;
335
+ }
336
+
337
+ export interface AuthList {
338
+ /** The app owner ID. */
339
+ readonly ownerId: OwnerId;
340
+ /** The name provided by the user during registration. */
341
+ readonly username: string;
342
+ }
343
+
344
+ /* Types below based off of react-native-sensitive-info */
345
+
346
+ export interface LocalAuthOptions {
347
+ /**
348
+ * Native: Namespaces the stored entry. Defaults to the bundle identifier
349
+ * (when available) or `default`.
350
+ */
351
+ readonly service?: string;
352
+
353
+ /** IOS: Enable keychain item synchronization via iCloud. */
354
+ readonly iosSynchronizable?: boolean;
355
+
356
+ /** IOS: Custom keychain access group. */
357
+ readonly keychainGroup?: string;
358
+
359
+ /**
360
+ * Native: Desired access-control policy. The native implementation will
361
+ * automatically fall back to the strongest supported policy for the current
362
+ * device (Secure Enclave ➝ Biometry ➝ Device Credential ➝ None).
363
+ */
364
+ readonly accessControl?: AccessControl;
365
+
366
+ /**
367
+ * Android: Fine tune whether the hardware-authenticated key should require
368
+ * biometrics only.
369
+ */
370
+ readonly androidBiometricsStrongOnly?: boolean;
371
+
372
+ /**
373
+ * Native: Optional prompt configuration that will be shown when protected
374
+ * keys require user presence.
375
+ */
376
+ readonly authenticationPrompt?: AuthenticationPrompt;
377
+
378
+ /** Web: The relying party ID for WebAuthn. Defaults to the current hostname. */
379
+ readonly relyingPartyID?: string;
380
+
381
+ /** Web: The relying party name for WebAuthn. Defaults to 'Evolu'. */
382
+ readonly relyingPartyName?: string;
383
+
384
+ /** Web: The username for WebAuthn. Defaults to 'Evolu User'. */
385
+ readonly webAuthnUsername?: string;
386
+
387
+ /**
388
+ * Web: The user verification requirement for WebAuthn. Defaults to
389
+ * 'required'.
390
+ */
391
+ readonly webAuthnUserVerification?: UserVerificationRequirement;
392
+
393
+ /** Web: The authenticator attachment for WebAuthn. Defaults to 'platform'. */
394
+ readonly webAuthnAuthenticatorAttachment?: AuthenticatorAttachment;
395
+ }
396
+
397
+ export interface LocalAuthOptionsValues extends LocalAuthOptions {
398
+ /** When true, the stored value is returned for each item. Defaults to false. */
399
+ readonly includeValues?: boolean;
400
+ }
401
+
402
+ /**
403
+ * Configuration for the biometric/device credential prompt shown when a
404
+ * protected item is accessed.
405
+ */
406
+ export interface AuthenticationPrompt {
407
+ readonly title: string;
408
+ readonly subtitle?: string;
409
+ readonly description?: string;
410
+ readonly cancel?: string;
411
+ }
412
+
413
+ export interface SensitiveInfoGetRequest extends LocalAuthOptions {
414
+ readonly key: string;
415
+ /** Include the encrypted value when available. Defaults to true. */
416
+ readonly includeValue?: boolean;
417
+ }
418
+
419
+ export interface StorageMetadata {
420
+ readonly securityLevel: SecurityLevel;
421
+ readonly backend: StorageBackend;
422
+ readonly accessControl: AccessControl;
423
+ readonly timestamp: number;
424
+ }
425
+
426
+ export interface SensitiveInfoItem {
427
+ readonly key: string;
428
+ readonly service: string;
429
+ readonly value?: string;
430
+ readonly metadata: StorageMetadata;
431
+ }
432
+
433
+ export interface MutationResult {
434
+ readonly metadata: StorageMetadata;
435
+ }
436
+
437
+ /**
438
+ * Enumerates the highest security tier that was effectively applied while
439
+ * storing a value.
440
+ */
441
+ export type SecurityLevel =
442
+ | "secureEnclave"
443
+ | "strongBox"
444
+ | "biometry"
445
+ | "deviceCredential"
446
+ | "software";
447
+
448
+ /** Enumerates the native storage backend used to persist sensitive data. */
449
+ export type StorageBackend =
450
+ | "keychain"
451
+ | "androidKeystore"
452
+ | "encryptedSharedPreferences";
453
+
454
+ /**
455
+ * Enumerates the access-control policy enforced by the underlying secure
456
+ * storage.
457
+ */
458
+ export type AccessControl =
459
+ | "secureEnclaveBiometry"
460
+ | "biometryCurrentSet"
461
+ | "biometryAny"
462
+ | "devicePasscode"
463
+ | "none";