@push.rocks/smartsecret 1.4.0 → 1.6.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.
@@ -0,0 +1,1458 @@
1
+ import * as plugins from './smartsecret.plugins.js';
2
+ import { SmartSecretKernelStoreError, } from './smartsecret.kernel.error.js';
3
+ import { normalizeSmartSecretKernelAccount, normalizeSmartSecretKernelService, } from './smartsecret.kernel.protocol.js';
4
+ import { SmartSecretSealedFileStoreError, createSmartSecretSealedFileStoreError, } from './smartsecret.sealedfile.error.js';
5
+ export const smartSecretSealedFileMaximumEntryBytes = 512 * 1_024;
6
+ const schemaVersion = 1;
7
+ const profile = 'smartsecret-kernel-aes-256-gcm-file-v1';
8
+ const manifestName = 'manifest.json';
9
+ const relocationReceiptName = '.smartsecret-relocation.json';
10
+ const masterKeyBytes = 32;
11
+ const maximumEnvelopeBytes = 768 * 1_024;
12
+ const operationTimeoutMs = 60_000;
13
+ const canonicalDigestPattern = /^[A-Za-z0-9_-]{43}$/;
14
+ const entryFilePattern = /^[A-Za-z0-9_-]{43}\.sealed\.json$/;
15
+ const temporaryFilePattern = /^\.smartsecret-[A-Za-z0-9_-]{22}\.tmp$/;
16
+ const maximumPendingOperations = 64;
17
+ const encoder = new TextEncoder();
18
+ const sha256 = (...valuesArg) => {
19
+ const hash = plugins.crypto.createHash('sha256');
20
+ for (const value of valuesArg)
21
+ hash.update(value);
22
+ return new Uint8Array(hash.digest());
23
+ };
24
+ const digest = (...valuesArg) => Buffer.from(sha256(...valuesArg)).toString('base64url');
25
+ const fingerprint = (keyArg) => digest(encoder.encode('@push.rocks/smartsecret/sealed-file/master-key/v1\0'), keyArg);
26
+ const normalizeStoreId = (valueArg) => {
27
+ if (typeof valueArg !== 'string'
28
+ || !/^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/.test(valueArg))
29
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
30
+ return valueArg;
31
+ };
32
+ const normalizeDirectoryPath = (valueArg) => {
33
+ if (typeof valueArg !== 'string'
34
+ || !plugins.path.isAbsolute(valueArg)
35
+ || plugins.path.resolve(valueArg) !== valueArg
36
+ || valueArg === plugins.path.parse(valueArg).root)
37
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
38
+ return valueArg;
39
+ };
40
+ const dataPropertyValue = (objectArg, keyArg) => {
41
+ let current = objectArg;
42
+ while (current) {
43
+ const descriptor = Object.getOwnPropertyDescriptor(current, keyArg);
44
+ if (descriptor) {
45
+ if (!('value' in descriptor)) {
46
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
47
+ }
48
+ return descriptor.value;
49
+ }
50
+ current = Object.getPrototypeOf(current);
51
+ }
52
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
53
+ };
54
+ const normalizeOptions = (optionsArg) => {
55
+ try {
56
+ if (!optionsArg || typeof optionsArg !== 'object' || Array.isArray(optionsArg)) {
57
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
58
+ }
59
+ const keys = Reflect.ownKeys(optionsArg);
60
+ if (keys.length !== 3
61
+ || keys.some((keyArg) => typeof keyArg !== 'string')
62
+ || !['kernelStore', 'storeId', 'directoryPath'].every((keyArg) => keys.includes(keyArg)))
63
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
64
+ const values = Object.create(null);
65
+ for (const key of keys) {
66
+ const descriptor = Object.getOwnPropertyDescriptor(optionsArg, key);
67
+ if (!descriptor?.enumerable || !('value' in descriptor)) {
68
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
69
+ }
70
+ values[key] = descriptor.value;
71
+ }
72
+ const kernelStoreValue = values.kernelStore;
73
+ if (!kernelStoreValue
74
+ || typeof kernelStoreValue !== 'object')
75
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
76
+ const service = normalizeSmartSecretKernelService(dataPropertyValue(kernelStoreValue, 'service'));
77
+ const getEntry = dataPropertyValue(kernelStoreValue, 'getEntry');
78
+ const setEntry = dataPropertyValue(kernelStoreValue, 'setEntry');
79
+ const deleteEntry = dataPropertyValue(kernelStoreValue, 'deleteEntry');
80
+ if (typeof getEntry !== 'function'
81
+ || typeof setEntry !== 'function'
82
+ || typeof deleteEntry !== 'function')
83
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
84
+ const kernelStore = {
85
+ service,
86
+ getEntry: (accountArg, operationOptionsArg) => Reflect.apply(getEntry, kernelStoreValue, [accountArg, operationOptionsArg]),
87
+ setEntry: (accountArg, valueArg, operationOptionsArg) => Reflect.apply(setEntry, kernelStoreValue, [accountArg, valueArg, operationOptionsArg]),
88
+ deleteEntry: (accountArg, operationOptionsArg) => Reflect.apply(deleteEntry, kernelStoreValue, [accountArg, operationOptionsArg]),
89
+ };
90
+ const storeId = normalizeStoreId(values.storeId);
91
+ const directoryPath = normalizeDirectoryPath(values.directoryPath);
92
+ const identity = encoder.encode(`${service}\0${storeId}\0${directoryPath}`);
93
+ return {
94
+ kernelStore,
95
+ service,
96
+ storeId,
97
+ directoryPath,
98
+ masterKeyAccount: `sealed-file-master:v1:${digest(identity)}`,
99
+ mutexNamespace: `smartsecret-sealed-file:v1:${digest(encoder.encode(directoryPath))}`,
100
+ };
101
+ }
102
+ catch {
103
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
104
+ }
105
+ };
106
+ const normalizeRelocationOptions = (optionsArg) => {
107
+ try {
108
+ if (!optionsArg || typeof optionsArg !== 'object' || Array.isArray(optionsArg)) {
109
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
110
+ }
111
+ const expectedKeys = [
112
+ 'kernelStore',
113
+ 'storeId',
114
+ 'sourceDirectoryPath',
115
+ 'destinationDirectoryPath',
116
+ ];
117
+ const keys = Reflect.ownKeys(optionsArg);
118
+ if (keys.length !== expectedKeys.length
119
+ || keys.some((keyArg) => typeof keyArg !== 'string')
120
+ || expectedKeys.some((keyArg) => !keys.includes(keyArg)))
121
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
122
+ const values = Object.create(null);
123
+ for (const key of keys) {
124
+ const descriptor = Object.getOwnPropertyDescriptor(optionsArg, key);
125
+ if (!descriptor?.enumerable || !('value' in descriptor)) {
126
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
127
+ }
128
+ values[key] = descriptor.value;
129
+ }
130
+ const kernelStoreValue = values.kernelStore;
131
+ if (!kernelStoreValue || typeof kernelStoreValue !== 'object') {
132
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
133
+ }
134
+ const moveEntry = dataPropertyValue(kernelStoreValue, 'moveEntry');
135
+ if (typeof moveEntry !== 'function') {
136
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
137
+ }
138
+ const source = normalizeOptions({
139
+ kernelStore: kernelStoreValue,
140
+ storeId: values.storeId,
141
+ directoryPath: values.sourceDirectoryPath,
142
+ });
143
+ const destination = normalizeOptions({
144
+ kernelStore: kernelStoreValue,
145
+ storeId: values.storeId,
146
+ directoryPath: values.destinationDirectoryPath,
147
+ });
148
+ if (source.directoryPath === destination.directoryPath) {
149
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
150
+ }
151
+ const kernelStore = {
152
+ ...source.kernelStore,
153
+ moveEntry: (sourceAccountArg, destinationAccountArg, operationOptionsArg) => Reflect.apply(moveEntry, kernelStoreValue, [sourceAccountArg, destinationAccountArg, operationOptionsArg]),
154
+ };
155
+ source.kernelStore = kernelStore;
156
+ destination.kernelStore = kernelStore;
157
+ return { kernelStore, source, destination };
158
+ }
159
+ catch (errorArg) {
160
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
161
+ throw errorArg;
162
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
163
+ }
164
+ };
165
+ const exactObject = (valueArg, keysArg, errorCodeArg) => {
166
+ try {
167
+ if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
168
+ throw createSmartSecretSealedFileStoreError(errorCodeArg);
169
+ }
170
+ const prototype = Object.getPrototypeOf(valueArg);
171
+ const keys = Reflect.ownKeys(valueArg);
172
+ if ((prototype !== Object.prototype && prototype !== null)
173
+ || keys.length !== keysArg.length
174
+ || keys.some((keyArg) => typeof keyArg !== 'string')
175
+ || keysArg.some((keyArg) => !keys.includes(keyArg)))
176
+ throw createSmartSecretSealedFileStoreError(errorCodeArg);
177
+ const result = Object.create(null);
178
+ for (const key of keys) {
179
+ const descriptor = Object.getOwnPropertyDescriptor(valueArg, key);
180
+ if (!descriptor?.enumerable || !('value' in descriptor)) {
181
+ throw createSmartSecretSealedFileStoreError(errorCodeArg);
182
+ }
183
+ result[key] = descriptor.value;
184
+ }
185
+ return result;
186
+ }
187
+ catch (errorArg) {
188
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
189
+ throw errorArg;
190
+ throw createSmartSecretSealedFileStoreError(errorCodeArg);
191
+ }
192
+ };
193
+ const decodeBase64Url = (valueArg, maximumBytesArg, exactBytesArg) => {
194
+ if (typeof valueArg !== 'string'
195
+ || !/^[A-Za-z0-9_-]*$/.test(valueArg)
196
+ || valueArg.length % 4 === 1
197
+ || valueArg.length > Math.ceil(maximumBytesArg * 4 / 3))
198
+ throw createSmartSecretSealedFileStoreError('ENVELOPE_INVALID');
199
+ const decoded = Buffer.from(valueArg, 'base64url');
200
+ if (decoded.byteLength > maximumBytesArg
201
+ || (exactBytesArg !== undefined && decoded.byteLength !== exactBytesArg)
202
+ || decoded.toString('base64url') !== valueArg) {
203
+ decoded.fill(0);
204
+ throw createSmartSecretSealedFileStoreError('ENVELOPE_INVALID');
205
+ }
206
+ const result = new Uint8Array(decoded);
207
+ decoded.fill(0);
208
+ return result;
209
+ };
210
+ const parseEnvelope = (valueArg) => {
211
+ const value = exactObject(valueArg, [
212
+ 'schemaVersion',
213
+ 'profile',
214
+ 'entryId',
215
+ 'masterKeyFingerprint',
216
+ 'nonce',
217
+ 'ciphertext',
218
+ 'tag',
219
+ ], 'ENVELOPE_INVALID');
220
+ if (value.schemaVersion !== schemaVersion
221
+ || value.profile !== profile
222
+ || typeof value.entryId !== 'string'
223
+ || !canonicalDigestPattern.test(value.entryId)
224
+ || typeof value.masterKeyFingerprint !== 'string'
225
+ || !canonicalDigestPattern.test(value.masterKeyFingerprint))
226
+ throw createSmartSecretSealedFileStoreError('ENVELOPE_INVALID');
227
+ let nonce;
228
+ let ciphertext;
229
+ let tag;
230
+ try {
231
+ nonce = decodeBase64Url(value.nonce, 12, 12);
232
+ ciphertext = decodeBase64Url(value.ciphertext, smartSecretSealedFileMaximumEntryBytes);
233
+ tag = decodeBase64Url(value.tag, 16, 16);
234
+ return {
235
+ envelope: {
236
+ schemaVersion,
237
+ profile,
238
+ entryId: value.entryId,
239
+ masterKeyFingerprint: value.masterKeyFingerprint,
240
+ nonce: value.nonce,
241
+ ciphertext: value.ciphertext,
242
+ tag: value.tag,
243
+ },
244
+ encryptedData: { nonce, ciphertext, tag },
245
+ };
246
+ }
247
+ catch (errorArg) {
248
+ nonce?.fill(0);
249
+ ciphertext?.fill(0);
250
+ tag?.fill(0);
251
+ throw errorArg;
252
+ }
253
+ };
254
+ const encodeBase64Url = (valueArg) => {
255
+ const copy = Buffer.from(valueArg);
256
+ try {
257
+ return copy.toString('base64url');
258
+ }
259
+ finally {
260
+ copy.fill(0);
261
+ }
262
+ };
263
+ const encodeEncryptedData = (valueArg) => ({
264
+ nonce: encodeBase64Url(valueArg.nonce),
265
+ ciphertext: encodeBase64Url(valueArg.ciphertext),
266
+ tag: encodeBase64Url(valueArg.tag),
267
+ });
268
+ const entryId = (optionsArg, accountArg) => digest(encoder.encode('@push.rocks/smartsecret/sealed-file/entry/v1\0'), encoder.encode(optionsArg.service), new Uint8Array([0]), encoder.encode(optionsArg.storeId), new Uint8Array([0]), encoder.encode(accountArg));
269
+ const entryAad = (optionsArg, accountArg, entryIdArg, fingerprintArg) => encoder.encode(JSON.stringify({
270
+ schemaVersion,
271
+ profile,
272
+ service: optionsArg.service,
273
+ storeId: optionsArg.storeId,
274
+ account: accountArg,
275
+ entryId: entryIdArg,
276
+ masterKeyFingerprint: fingerprintArg,
277
+ }));
278
+ const manifestFor = (optionsArg, fingerprintArg) => ({
279
+ schemaVersion,
280
+ profile,
281
+ serviceDigest: digest(encoder.encode(optionsArg.service)),
282
+ storeId: optionsArg.storeId,
283
+ masterKeyFingerprint: fingerprintArg,
284
+ });
285
+ const directoryIdentity = (statsArg) => ({
286
+ device: statsArg.dev.toString(10),
287
+ inode: statsArg.ino.toString(10),
288
+ });
289
+ const directoryIdentitiesEqual = (leftArg, rightArg) => leftArg.device === rightArg.device && leftArg.inode === rightArg.inode;
290
+ const relocationReceiptFor = (optionsArg, fingerprintArg, identityArg) => ({
291
+ schemaVersion,
292
+ kind: 'relocation',
293
+ profile,
294
+ serviceDigest: digest(encoder.encode(optionsArg.source.service)),
295
+ storeId: optionsArg.source.storeId,
296
+ sourcePathDigest: digest(encoder.encode(optionsArg.source.directoryPath)),
297
+ destinationPathDigest: digest(encoder.encode(optionsArg.destination.directoryPath)),
298
+ masterKeyFingerprint: fingerprintArg,
299
+ ...identityArg,
300
+ });
301
+ const parseRelocationReceipt = (valueArg, optionsArg, fingerprintArg, identityArg) => {
302
+ const value = exactObject(valueArg, [
303
+ 'schemaVersion',
304
+ 'kind',
305
+ 'profile',
306
+ 'serviceDigest',
307
+ 'storeId',
308
+ 'sourcePathDigest',
309
+ 'destinationPathDigest',
310
+ 'masterKeyFingerprint',
311
+ 'device',
312
+ 'inode',
313
+ ], 'FILESYSTEM_FAILED');
314
+ const expected = relocationReceiptFor(optionsArg, fingerprintArg, identityArg);
315
+ if (value.schemaVersion !== expected.schemaVersion
316
+ || value.kind !== expected.kind
317
+ || value.profile !== expected.profile
318
+ || value.serviceDigest !== expected.serviceDigest
319
+ || value.storeId !== expected.storeId
320
+ || value.sourcePathDigest !== expected.sourcePathDigest
321
+ || value.destinationPathDigest !== expected.destinationPathDigest
322
+ || value.masterKeyFingerprint !== expected.masterKeyFingerprint
323
+ || value.device !== expected.device
324
+ || value.inode !== expected.inode)
325
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
326
+ return value;
327
+ };
328
+ const parseManifest = (valueArg, optionsArg) => {
329
+ const value = exactObject(valueArg, [
330
+ 'schemaVersion',
331
+ 'profile',
332
+ 'serviceDigest',
333
+ 'storeId',
334
+ 'masterKeyFingerprint',
335
+ ], 'FILESYSTEM_FAILED');
336
+ if (value.schemaVersion !== schemaVersion
337
+ || value.profile !== profile
338
+ || value.serviceDigest !== digest(encoder.encode(optionsArg.service))
339
+ || value.storeId !== optionsArg.storeId
340
+ || typeof value.masterKeyFingerprint !== 'string'
341
+ || !canonicalDigestPattern.test(value.masterKeyFingerprint))
342
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
343
+ return value;
344
+ };
345
+ const mapKernelError = (errorArg) => {
346
+ if (!(errorArg instanceof SmartSecretKernelStoreError)) {
347
+ return createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
348
+ }
349
+ if (errorArg.code === 'MUTATION_OUTCOME_UNKNOWN') {
350
+ return createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
351
+ }
352
+ if (errorArg.code === 'INVALID_ARGUMENT') {
353
+ return createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
354
+ }
355
+ return createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
356
+ };
357
+ const mapMutexError = (errorArg) => {
358
+ if (errorArg instanceof plugins.smartipc.NamedMutexError) {
359
+ if (errorArg.code === 'ABORTED' || errorArg.code === 'TIMEOUT') {
360
+ return createSmartSecretSealedFileStoreError('MUTEX_FAILED');
361
+ }
362
+ }
363
+ return createSmartSecretSealedFileStoreError('MUTEX_FAILED');
364
+ };
365
+ const directoryHandlePath = (directoryHandleArg, nameArg) => nameArg
366
+ ? plugins.path.join(`/proc/self/fd/${directoryHandleArg.fd}`, nameArg)
367
+ : `/proc/self/fd/${directoryHandleArg.fd}`;
368
+ const mutationOutcomeUnknown = (errorArg) => errorArg instanceof SmartSecretSealedFileStoreError
369
+ && errorArg.code === 'MUTATION_OUTCOME_UNKNOWN';
370
+ const preferCleanupError = (operationErrorArg, cleanupErrorArg) => mutationOutcomeUnknown(operationErrorArg) ? operationErrorArg : cleanupErrorArg;
371
+ const closeFileHandle = async (handleArg) => {
372
+ try {
373
+ await handleArg.close();
374
+ }
375
+ catch {
376
+ try {
377
+ await handleArg.close();
378
+ }
379
+ catch { }
380
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
381
+ }
382
+ };
383
+ const closeFileHandleWithError = async (handleArg, operationErrorArg) => {
384
+ try {
385
+ await closeFileHandle(handleArg);
386
+ return operationErrorArg;
387
+ }
388
+ catch (errorArg) {
389
+ return preferCleanupError(operationErrorArg, errorArg);
390
+ }
391
+ };
392
+ const wipeDiscardedResult = (valueArg) => {
393
+ if (valueArg instanceof Uint8Array)
394
+ valueArg.fill(0);
395
+ };
396
+ const validateDirectory = (statsArg, effectiveUidArg, finalArg) => {
397
+ if (!statsArg.isDirectory()) {
398
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
399
+ }
400
+ const mode = statsArg.mode & 4095n;
401
+ if (finalArg) {
402
+ if (statsArg.uid !== effectiveUidArg || mode !== 448n) {
403
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
404
+ }
405
+ return;
406
+ }
407
+ if (statsArg.uid !== 0n && statsArg.uid !== effectiveUidArg) {
408
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
409
+ }
410
+ if ((mode & 18n) !== 0n
411
+ && !(statsArg.uid === 0n && (mode & 512n) !== 0n))
412
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
413
+ };
414
+ const openDirectory = async (directoryPathArg, createArg) => {
415
+ let currentHandle;
416
+ try {
417
+ const effectiveUid = process.geteuid?.();
418
+ if (!Number.isSafeInteger(effectiveUid) || effectiveUid < 0) {
419
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
420
+ }
421
+ const root = plugins.path.parse(directoryPathArg).root;
422
+ const components = plugins.path.relative(root, directoryPathArg)
423
+ .split(plugins.path.sep)
424
+ .filter(Boolean);
425
+ currentHandle = await plugins.fs.promises.open(root, plugins.fs.constants.O_RDONLY
426
+ | plugins.fs.constants.O_DIRECTORY
427
+ | plugins.fs.constants.O_NOFOLLOW);
428
+ validateDirectory(await currentHandle.stat({ bigint: true }), BigInt(effectiveUid), false);
429
+ for (let index = 0; index < components.length; index++) {
430
+ const componentPath = directoryHandlePath(currentHandle, components[index]);
431
+ if (createArg) {
432
+ try {
433
+ await plugins.fs.promises.mkdir(componentPath, { mode: 0o700 });
434
+ }
435
+ catch (errorArg) {
436
+ if (errorArg.code !== 'EEXIST')
437
+ throw errorArg;
438
+ }
439
+ }
440
+ let nextHandle;
441
+ try {
442
+ nextHandle = await plugins.fs.promises.open(componentPath, plugins.fs.constants.O_RDONLY
443
+ | plugins.fs.constants.O_DIRECTORY
444
+ | plugins.fs.constants.O_NOFOLLOW);
445
+ validateDirectory(await nextHandle.stat({ bigint: true }), BigInt(effectiveUid), index === components.length - 1);
446
+ await closeFileHandle(currentHandle);
447
+ currentHandle = nextHandle;
448
+ nextHandle = undefined;
449
+ }
450
+ finally {
451
+ if (nextHandle)
452
+ await closeFileHandle(nextHandle);
453
+ }
454
+ }
455
+ const result = currentHandle;
456
+ currentHandle = undefined;
457
+ return result;
458
+ }
459
+ catch (errorArg) {
460
+ let operationError = errorArg instanceof SmartSecretSealedFileStoreError
461
+ ? errorArg
462
+ : createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
463
+ if (currentHandle) {
464
+ operationError = await closeFileHandleWithError(currentHandle, operationError);
465
+ }
466
+ throw operationError;
467
+ }
468
+ };
469
+ const ensureDirectory = (directoryPathArg) => openDirectory(directoryPathArg, true);
470
+ const openExistingDirectory = (directoryPathArg) => openDirectory(directoryPathArg, false);
471
+ const openChildDirectoryIfPresent = async (parentHandleArg, nameArg) => {
472
+ let handle;
473
+ try {
474
+ try {
475
+ handle = await plugins.fs.promises.open(directoryHandlePath(parentHandleArg, nameArg), plugins.fs.constants.O_RDONLY
476
+ | plugins.fs.constants.O_DIRECTORY
477
+ | plugins.fs.constants.O_NOFOLLOW);
478
+ }
479
+ catch (errorArg) {
480
+ if (errorArg.code === 'ENOENT')
481
+ return undefined;
482
+ throw errorArg;
483
+ }
484
+ const effectiveUid = process.geteuid?.();
485
+ if (!Number.isSafeInteger(effectiveUid) || effectiveUid < 0) {
486
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
487
+ }
488
+ validateDirectory(await handle.stat({ bigint: true }), BigInt(effectiveUid), true);
489
+ const result = handle;
490
+ handle = undefined;
491
+ return result;
492
+ }
493
+ catch (errorArg) {
494
+ let operationError = errorArg instanceof SmartSecretSealedFileStoreError
495
+ ? errorArg
496
+ : createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
497
+ if (handle)
498
+ operationError = await closeFileHandleWithError(handle, operationError);
499
+ throw operationError;
500
+ }
501
+ };
502
+ const readStrictJsonFile = async (directoryHandleArg, fileNameArg, maximumBytesArg) => {
503
+ let handle;
504
+ let bytes;
505
+ let result;
506
+ let operationError;
507
+ try {
508
+ try {
509
+ handle = await plugins.fs.promises.open(directoryHandlePath(directoryHandleArg, fileNameArg), plugins.fs.constants.O_RDONLY | plugins.fs.constants.O_NOFOLLOW);
510
+ }
511
+ catch (errorArg) {
512
+ if (errorArg.code === 'ENOENT')
513
+ return undefined;
514
+ throw errorArg;
515
+ }
516
+ const stats = await handle.stat();
517
+ const effectiveUid = process.geteuid?.();
518
+ if (!stats.isFile()
519
+ || stats.nlink !== 1
520
+ || stats.size < 1
521
+ || stats.size > maximumBytesArg
522
+ || (effectiveUid !== undefined && stats.uid !== effectiveUid)
523
+ || (stats.mode & 0o7777) !== 0o600)
524
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
525
+ bytes = await handle.readFile();
526
+ if (bytes.byteLength !== stats.size) {
527
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
528
+ }
529
+ result = JSON.parse(bytes.toString('utf8'));
530
+ }
531
+ catch (errorArg) {
532
+ operationError = errorArg instanceof SmartSecretSealedFileStoreError
533
+ ? errorArg
534
+ : createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
535
+ }
536
+ bytes?.fill(0);
537
+ if (handle) {
538
+ try {
539
+ await closeFileHandle(handle);
540
+ }
541
+ catch (errorArg) {
542
+ operationError = preferCleanupError(operationError, errorArg);
543
+ }
544
+ }
545
+ if (operationError)
546
+ throw operationError;
547
+ return result;
548
+ };
549
+ const atomicWriteJson = async (directoryHandleArg, targetNameArg, valueArg) => {
550
+ const temporaryName = `.smartsecret-${plugins.crypto.randomBytes(16).toString('base64url')}.tmp`;
551
+ const temporaryPath = directoryHandlePath(directoryHandleArg, temporaryName);
552
+ const targetPath = directoryHandlePath(directoryHandleArg, targetNameArg);
553
+ let handle;
554
+ let bytes;
555
+ let renamed = false;
556
+ let mutationApplied = false;
557
+ let operationError;
558
+ try {
559
+ bytes = Buffer.from(JSON.stringify(valueArg), 'utf8');
560
+ handle = await plugins.fs.promises.open(temporaryPath, plugins.fs.constants.O_WRONLY
561
+ | plugins.fs.constants.O_CREAT
562
+ | plugins.fs.constants.O_EXCL
563
+ | plugins.fs.constants.O_NOFOLLOW, 0o600);
564
+ const stats = await handle.stat();
565
+ const effectiveUid = process.geteuid?.();
566
+ if (!stats.isFile()
567
+ || stats.nlink !== 1
568
+ || (effectiveUid !== undefined && stats.uid !== effectiveUid)
569
+ || (stats.mode & 0o7777) !== 0o600) {
570
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
571
+ }
572
+ await handle.writeFile(bytes);
573
+ await handle.sync();
574
+ await closeFileHandle(handle);
575
+ handle = undefined;
576
+ await plugins.fs.promises.rename(temporaryPath, targetPath);
577
+ renamed = true;
578
+ mutationApplied = true;
579
+ await directoryHandleArg.sync();
580
+ }
581
+ catch (errorArg) {
582
+ operationError = errorArg instanceof SmartSecretSealedFileStoreError
583
+ ? errorArg
584
+ : createSmartSecretSealedFileStoreError(mutationApplied ? 'MUTATION_OUTCOME_UNKNOWN' : 'FILESYSTEM_FAILED');
585
+ }
586
+ bytes?.fill(0);
587
+ if (handle) {
588
+ try {
589
+ await closeFileHandle(handle);
590
+ }
591
+ catch (errorArg) {
592
+ operationError = preferCleanupError(operationError, errorArg);
593
+ }
594
+ }
595
+ if (!renamed) {
596
+ try {
597
+ await plugins.fs.promises.unlink(temporaryPath);
598
+ await directoryHandleArg.sync();
599
+ }
600
+ catch (errorArg) {
601
+ if (errorArg.code !== 'ENOENT') {
602
+ operationError = createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
603
+ }
604
+ }
605
+ }
606
+ if (operationError)
607
+ throw operationError;
608
+ };
609
+ const removeAndSync = async (directoryHandleArg, fileNameArg) => {
610
+ try {
611
+ await plugins.fs.promises.unlink(directoryHandlePath(directoryHandleArg, fileNameArg));
612
+ try {
613
+ await directoryHandleArg.sync();
614
+ }
615
+ catch {
616
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
617
+ }
618
+ return true;
619
+ }
620
+ catch (errorArg) {
621
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
622
+ throw errorArg;
623
+ if (errorArg.code === 'ENOENT')
624
+ return false;
625
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
626
+ }
627
+ };
628
+ const listOwnedFiles = async (directoryHandleArg, allowRelocationReceiptArg = false) => {
629
+ try {
630
+ const names = await plugins.fs.promises.readdir(directoryHandlePath(directoryHandleArg));
631
+ if (names.some((nameArg) => (nameArg !== manifestName
632
+ && !(allowRelocationReceiptArg && nameArg === relocationReceiptName)
633
+ && !entryFilePattern.test(nameArg)
634
+ && !temporaryFilePattern.test(nameArg))))
635
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
636
+ return names;
637
+ }
638
+ catch (errorArg) {
639
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
640
+ throw errorArg;
641
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
642
+ }
643
+ };
644
+ const acquireLease = async (optionsArg, deadlineArg = performance.now() + operationTimeoutMs) => {
645
+ const remainingMs = deadlineArg - performance.now();
646
+ if (remainingMs <= 0) {
647
+ throw createSmartSecretSealedFileStoreError('MUTEX_FAILED');
648
+ }
649
+ try {
650
+ const mutex = new plugins.smartipc.NamedMutex(optionsArg.mutexNamespace);
651
+ const lease = await mutex.acquire({ timeoutMs: Math.max(0, Math.floor(remainingMs)) });
652
+ if (performance.now() >= deadlineArg) {
653
+ await lease.release().catch(() => undefined);
654
+ throw createSmartSecretSealedFileStoreError('MUTEX_FAILED');
655
+ }
656
+ return lease;
657
+ }
658
+ catch (errorArg) {
659
+ throw mapMutexError(errorArg);
660
+ }
661
+ };
662
+ const readMasterKey = async (optionsArg) => {
663
+ let value;
664
+ try {
665
+ value = await optionsArg.kernelStore.getEntry(optionsArg.masterKeyAccount);
666
+ }
667
+ catch (errorArg) {
668
+ throw mapKernelError(errorArg);
669
+ }
670
+ if (value === null)
671
+ return null;
672
+ let result;
673
+ try {
674
+ if (!(value instanceof Uint8Array)) {
675
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
676
+ }
677
+ result = new Uint8Array(value);
678
+ try {
679
+ value.fill(0);
680
+ }
681
+ catch { }
682
+ if (result.byteLength !== masterKeyBytes) {
683
+ result.fill(0);
684
+ result = undefined;
685
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
686
+ }
687
+ return result;
688
+ }
689
+ catch (errorArg) {
690
+ result?.fill(0);
691
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
692
+ throw errorArg;
693
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
694
+ }
695
+ };
696
+ const mapRelocationKernelError = (errorArg) => {
697
+ if (!(errorArg instanceof SmartSecretKernelStoreError)) {
698
+ return createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
699
+ }
700
+ if (errorArg.code === 'MUTATION_OUTCOME_UNKNOWN') {
701
+ return createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
702
+ }
703
+ if (errorArg.code === 'TARGET_CONFLICT' || errorArg.code === 'SOURCE_CHANGED') {
704
+ return createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
705
+ }
706
+ if (errorArg.code === 'INVALID_ARGUMENT') {
707
+ return createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
708
+ }
709
+ return createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
710
+ };
711
+ const acquireRelocationLeases = async (optionsArg) => {
712
+ const deadline = performance.now() + operationTimeoutMs;
713
+ const ordered = [optionsArg.source, optionsArg.destination]
714
+ .sort((leftArg, rightArg) => leftArg.mutexNamespace < rightArg.mutexNamespace
715
+ ? -1
716
+ : leftArg.mutexNamespace > rightArg.mutexNamespace
717
+ ? 1
718
+ : 0);
719
+ const leases = [];
720
+ try {
721
+ for (const options of ordered)
722
+ leases.push(await acquireLease(options, deadline));
723
+ return leases;
724
+ }
725
+ catch (errorArg) {
726
+ let operationError = errorArg;
727
+ for (const lease of leases.reverse()) {
728
+ try {
729
+ await lease.release();
730
+ }
731
+ catch {
732
+ operationError = preferCleanupError(operationError, createSmartSecretSealedFileStoreError('MUTEX_FAILED'));
733
+ }
734
+ }
735
+ throw operationError;
736
+ }
737
+ };
738
+ const inspectRelocationDirectory = async (directoryHandleArg, optionsArg) => {
739
+ const names = await listOwnedFiles(directoryHandleArg, true);
740
+ if (!names.includes(manifestName)) {
741
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
742
+ }
743
+ const manifestValue = await readStrictJsonFile(directoryHandleArg, manifestName, 4 * 1_024);
744
+ if (manifestValue === undefined) {
745
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
746
+ }
747
+ const receiptValue = names.includes(relocationReceiptName)
748
+ ? await readStrictJsonFile(directoryHandleArg, relocationReceiptName, 4 * 1_024)
749
+ : undefined;
750
+ if (names.includes(relocationReceiptName) && receiptValue === undefined) {
751
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
752
+ }
753
+ return {
754
+ manifest: parseManifest(manifestValue, optionsArg),
755
+ ...(receiptValue === undefined ? {} : { receiptValue }),
756
+ };
757
+ };
758
+ const readRelocationMasterKey = async (sourceArg, destinationArg, expectedFingerprintArg) => {
759
+ let sourceKey = null;
760
+ let destinationKey = null;
761
+ try {
762
+ sourceKey = await readMasterKey(sourceArg);
763
+ destinationKey = await readMasterKey(destinationArg);
764
+ if (!sourceKey && !destinationKey) {
765
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_UNAVAILABLE');
766
+ }
767
+ if ((sourceKey && fingerprint(sourceKey) !== expectedFingerprintArg)
768
+ || (destinationKey && fingerprint(destinationKey) !== expectedFingerprintArg)
769
+ || (sourceKey
770
+ && destinationKey
771
+ && !plugins.crypto.timingSafeEqual(sourceKey, destinationKey)))
772
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
773
+ return {
774
+ key: new Uint8Array(sourceKey ?? destinationKey),
775
+ sourcePresent: sourceKey !== null,
776
+ destinationPresent: destinationKey !== null,
777
+ };
778
+ }
779
+ finally {
780
+ sourceKey?.fill(0);
781
+ destinationKey?.fill(0);
782
+ }
783
+ };
784
+ const syncRelocationParents = async (sourceParentHandleArg, sourceParentPathArg, destinationParentHandleArg, destinationParentPathArg) => {
785
+ try {
786
+ await sourceParentHandleArg.sync();
787
+ if (sourceParentPathArg !== destinationParentPathArg) {
788
+ await destinationParentHandleArg.sync();
789
+ }
790
+ }
791
+ catch {
792
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
793
+ }
794
+ };
795
+ const assertOpenChildIdentity = async (parentHandleArg, nameArg, childHandleArg) => {
796
+ try {
797
+ const [pathStats, handleStats] = await Promise.all([
798
+ plugins.fs.promises.lstat(directoryHandlePath(parentHandleArg, nameArg), { bigint: true }),
799
+ childHandleArg.stat({ bigint: true }),
800
+ ]);
801
+ if (pathStats.isSymbolicLink()
802
+ || !pathStats.isDirectory()
803
+ || pathStats.dev !== handleStats.dev
804
+ || pathStats.ino !== handleStats.ino)
805
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
806
+ return directoryIdentity(handleStats);
807
+ }
808
+ catch (errorArg) {
809
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
810
+ throw errorArg;
811
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
812
+ }
813
+ };
814
+ const readChildIdentity = async (parentHandleArg, nameArg) => {
815
+ try {
816
+ const stats = await plugins.fs.promises.lstat(directoryHandlePath(parentHandleArg, nameArg), { bigint: true });
817
+ if (stats.isSymbolicLink() || !stats.isDirectory()) {
818
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
819
+ }
820
+ return directoryIdentity(stats);
821
+ }
822
+ catch (errorArg) {
823
+ if (errorArg.code === 'ENOENT')
824
+ return undefined;
825
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
826
+ throw errorArg;
827
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
828
+ }
829
+ };
830
+ const assertChildAbsent = async (parentHandleArg, nameArg) => {
831
+ try {
832
+ await plugins.fs.promises.lstat(directoryHandlePath(parentHandleArg, nameArg));
833
+ }
834
+ catch (errorArg) {
835
+ if (errorArg.code === 'ENOENT')
836
+ return;
837
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
838
+ }
839
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
840
+ };
841
+ const createMasterKey = async (optionsArg) => {
842
+ const generated = plugins.smartcrypto.generateAes256GcmKey();
843
+ let written = false;
844
+ try {
845
+ try {
846
+ await optionsArg.kernelStore.setEntry(optionsArg.masterKeyAccount, generated);
847
+ written = true;
848
+ }
849
+ catch (errorArg) {
850
+ throw mapKernelError(errorArg);
851
+ }
852
+ const readback = await readMasterKey(optionsArg);
853
+ if (!readback
854
+ || !plugins.crypto.timingSafeEqual(readback, generated)) {
855
+ readback?.fill(0);
856
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
857
+ }
858
+ return readback;
859
+ }
860
+ catch (errorArg) {
861
+ if (written) {
862
+ try {
863
+ await optionsArg.kernelStore.deleteEntry(optionsArg.masterKeyAccount);
864
+ }
865
+ catch (deleteErrorArg) {
866
+ throw mapKernelError(deleteErrorArg);
867
+ }
868
+ }
869
+ throw errorArg;
870
+ }
871
+ finally {
872
+ generated.fill(0);
873
+ }
874
+ };
875
+ const bootstrapUnderLease = async (optionsArg, existingIdentityArg, allowRelocationReceiptArg = false) => {
876
+ const directoryHandle = existingIdentityArg
877
+ ? await openExistingDirectory(optionsArg.directoryPath)
878
+ : await ensureDirectory(optionsArg.directoryPath);
879
+ let key = null;
880
+ let result;
881
+ let createdMasterKey = false;
882
+ let operationError;
883
+ try {
884
+ if (existingIdentityArg) {
885
+ const currentIdentity = directoryIdentity(await directoryHandle.stat({ bigint: true }));
886
+ if (!directoryIdentitiesEqual(currentIdentity, existingIdentityArg)) {
887
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
888
+ }
889
+ }
890
+ const names = await listOwnedFiles(directoryHandle, allowRelocationReceiptArg);
891
+ const manifestValue = await readStrictJsonFile(directoryHandle, manifestName, 4 * 1_024);
892
+ const manifest = manifestValue === undefined ? undefined : parseManifest(manifestValue, optionsArg);
893
+ key = await readMasterKey(optionsArg);
894
+ if (!key) {
895
+ if (names.length > 0) {
896
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_UNAVAILABLE');
897
+ }
898
+ key = await createMasterKey(optionsArg);
899
+ createdMasterKey = true;
900
+ }
901
+ if (key.byteLength !== masterKeyBytes) {
902
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
903
+ }
904
+ const keyFingerprint = fingerprint(key);
905
+ if (manifest && manifest.masterKeyFingerprint !== keyFingerprint) {
906
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
907
+ }
908
+ for (const name of names.filter((nameArg) => temporaryFilePattern.test(nameArg))) {
909
+ await removeAndSync(directoryHandle, name);
910
+ }
911
+ if (!manifest) {
912
+ await atomicWriteJson(directoryHandle, manifestName, manifestFor(optionsArg, keyFingerprint));
913
+ }
914
+ result = new Uint8Array(key);
915
+ key.fill(0);
916
+ key = null;
917
+ }
918
+ catch (errorArg) {
919
+ operationError = errorArg;
920
+ }
921
+ key?.fill(0);
922
+ operationError = await closeFileHandleWithError(directoryHandle, operationError);
923
+ if (operationError) {
924
+ result?.fill(0);
925
+ result = undefined;
926
+ if (createdMasterKey && !mutationOutcomeUnknown(operationError)) {
927
+ try {
928
+ await optionsArg.kernelStore.deleteEntry(optionsArg.masterKeyAccount);
929
+ }
930
+ catch (deleteErrorArg) {
931
+ const deleteError = mapKernelError(deleteErrorArg);
932
+ throw preferCleanupError(operationError, deleteError);
933
+ }
934
+ }
935
+ throw operationError;
936
+ }
937
+ return result;
938
+ };
939
+ /**
940
+ * Stores one small master key in a strict kernel store and authenticated
941
+ * ciphertext in a caller-owned private directory. The kernel store lifecycle
942
+ * remains owned by the caller.
943
+ */
944
+ export class SmartSecretSealedFileStore {
945
+ constructor(options, masterKey) {
946
+ this.options = options;
947
+ this.masterKey = masterKey;
948
+ this.lifecycleState = 'ready';
949
+ this.operationTail = Promise.resolve();
950
+ this.pendingOperations = 0;
951
+ this.service = options.service;
952
+ this.storeId = options.storeId;
953
+ this.directoryPath = options.directoryPath;
954
+ }
955
+ static async create(optionsArg) {
956
+ const options = normalizeOptions(optionsArg);
957
+ if (process.platform !== 'linux' || typeof process.geteuid !== 'function') {
958
+ throw createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
959
+ }
960
+ const lease = await acquireLease(options);
961
+ let key;
962
+ let operationError;
963
+ try {
964
+ key = await bootstrapUnderLease(options);
965
+ }
966
+ catch (errorArg) {
967
+ operationError = errorArg;
968
+ }
969
+ try {
970
+ await lease.release();
971
+ }
972
+ catch {
973
+ operationError = preferCleanupError(operationError, createSmartSecretSealedFileStoreError('MUTEX_FAILED'));
974
+ }
975
+ if (operationError) {
976
+ key?.fill(0);
977
+ throw operationError;
978
+ }
979
+ const store = new SmartSecretSealedFileStore(options, key);
980
+ key = undefined;
981
+ return store;
982
+ }
983
+ /** Moves an initialized store and rebinds its exact kernel master key. */
984
+ static async relocate(optionsArg) {
985
+ const options = normalizeRelocationOptions(optionsArg);
986
+ if (process.platform !== 'linux' || typeof process.geteuid !== 'function') {
987
+ throw createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
988
+ }
989
+ const leases = await acquireRelocationLeases(options);
990
+ let sourceParentHandle;
991
+ let destinationParentHandle;
992
+ let sourceDirectoryHandle;
993
+ let destinationDirectoryHandle;
994
+ let expectedKey;
995
+ let expectedIdentity;
996
+ let resultKey;
997
+ let mutationPossible = false;
998
+ let operationError;
999
+ const sourceParentPath = plugins.path.dirname(options.source.directoryPath);
1000
+ const destinationParentPath = plugins.path.dirname(options.destination.directoryPath);
1001
+ const sourceName = plugins.path.basename(options.source.directoryPath);
1002
+ const destinationName = plugins.path.basename(options.destination.directoryPath);
1003
+ try {
1004
+ sourceParentHandle = await openExistingDirectory(sourceParentPath);
1005
+ destinationParentHandle = await openExistingDirectory(destinationParentPath);
1006
+ const [sourceParentStats, destinationParentStats] = await Promise.all([
1007
+ sourceParentHandle.stat({ bigint: true }),
1008
+ destinationParentHandle.stat({ bigint: true }),
1009
+ ]);
1010
+ if (sourceParentStats.dev !== destinationParentStats.dev) {
1011
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1012
+ }
1013
+ sourceDirectoryHandle = await openChildDirectoryIfPresent(sourceParentHandle, sourceName);
1014
+ destinationDirectoryHandle = await openChildDirectoryIfPresent(destinationParentHandle, destinationName);
1015
+ if (Boolean(sourceDirectoryHandle) === Boolean(destinationDirectoryHandle)) {
1016
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1017
+ }
1018
+ const storeAtSource = sourceDirectoryHandle !== undefined;
1019
+ const currentOptions = storeAtSource ? options.source : options.destination;
1020
+ const currentHandle = sourceDirectoryHandle ?? destinationDirectoryHandle;
1021
+ expectedIdentity = await assertOpenChildIdentity(storeAtSource ? sourceParentHandle : destinationParentHandle, storeAtSource ? sourceName : destinationName, currentHandle);
1022
+ if (expectedIdentity.device !== sourceParentStats.dev.toString(10)) {
1023
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1024
+ }
1025
+ const inspection = await inspectRelocationDirectory(currentHandle, currentOptions);
1026
+ const keyState = await readRelocationMasterKey(options.source, options.destination, inspection.manifest.masterKeyFingerprint);
1027
+ expectedKey = keyState.key;
1028
+ let receipt = inspection.receiptValue === undefined
1029
+ ? undefined
1030
+ : parseRelocationReceipt(inspection.receiptValue, options, inspection.manifest.masterKeyFingerprint, expectedIdentity);
1031
+ if (storeAtSource) {
1032
+ if (!keyState.sourcePresent) {
1033
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_UNAVAILABLE');
1034
+ }
1035
+ if (!receipt) {
1036
+ await atomicWriteJson(currentHandle, relocationReceiptName, relocationReceiptFor(options, inspection.manifest.masterKeyFingerprint, expectedIdentity));
1037
+ mutationPossible = true;
1038
+ const receiptValue = await readStrictJsonFile(currentHandle, relocationReceiptName, 4 * 1_024);
1039
+ if (receiptValue === undefined) {
1040
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
1041
+ }
1042
+ receipt = parseRelocationReceipt(receiptValue, options, inspection.manifest.masterKeyFingerprint, expectedIdentity);
1043
+ }
1044
+ await assertOpenChildIdentity(sourceParentHandle, sourceName, sourceDirectoryHandle);
1045
+ await assertChildAbsent(destinationParentHandle, destinationName);
1046
+ try {
1047
+ await plugins.fs.promises.rename(directoryHandlePath(sourceParentHandle, sourceName), directoryHandlePath(destinationParentHandle, destinationName));
1048
+ mutationPossible = true;
1049
+ }
1050
+ catch {
1051
+ const [sourceAfter, destinationAfter] = await Promise.all([
1052
+ readChildIdentity(sourceParentHandle, sourceName),
1053
+ readChildIdentity(destinationParentHandle, destinationName),
1054
+ ]);
1055
+ if (sourceAfter
1056
+ && directoryIdentitiesEqual(sourceAfter, expectedIdentity)
1057
+ && destinationAfter === undefined) {
1058
+ try {
1059
+ if (!await removeAndSync(currentHandle, relocationReceiptName)) {
1060
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
1061
+ }
1062
+ }
1063
+ catch (errorArg) {
1064
+ if (mutationOutcomeUnknown(errorArg))
1065
+ throw errorArg;
1066
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
1067
+ }
1068
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1069
+ }
1070
+ if (sourceAfter === undefined
1071
+ && destinationAfter
1072
+ && directoryIdentitiesEqual(destinationAfter, expectedIdentity)) {
1073
+ mutationPossible = true;
1074
+ }
1075
+ else {
1076
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
1077
+ }
1078
+ }
1079
+ }
1080
+ else {
1081
+ if (!receipt && (keyState.sourcePresent || !keyState.destinationPresent)) {
1082
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1083
+ }
1084
+ }
1085
+ await syncRelocationParents(sourceParentHandle, sourceParentPath, destinationParentHandle, destinationParentPath);
1086
+ mutationPossible = true;
1087
+ let moveStatus;
1088
+ try {
1089
+ moveStatus = await options.kernelStore.moveEntry(options.source.masterKeyAccount, options.destination.masterKeyAccount);
1090
+ }
1091
+ catch (errorArg) {
1092
+ throw mapRelocationKernelError(errorArg);
1093
+ }
1094
+ if (moveStatus === 'sourceAbsent') {
1095
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_UNAVAILABLE');
1096
+ }
1097
+ const destinationKey = await readMasterKey(options.destination);
1098
+ try {
1099
+ if (!destinationKey || !plugins.crypto.timingSafeEqual(destinationKey, expectedKey)) {
1100
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
1101
+ }
1102
+ }
1103
+ finally {
1104
+ destinationKey?.fill(0);
1105
+ }
1106
+ resultKey = await bootstrapUnderLease(options.destination, expectedIdentity, Boolean(receipt));
1107
+ if (!plugins.crypto.timingSafeEqual(resultKey, expectedKey)) {
1108
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
1109
+ }
1110
+ if (receipt) {
1111
+ try {
1112
+ if (!await removeAndSync(currentHandle, relocationReceiptName)) {
1113
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
1114
+ }
1115
+ }
1116
+ catch (errorArg) {
1117
+ if (mutationOutcomeUnknown(errorArg))
1118
+ throw errorArg;
1119
+ throw createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN');
1120
+ }
1121
+ }
1122
+ }
1123
+ catch (errorArg) {
1124
+ operationError = errorArg;
1125
+ }
1126
+ for (const handle of [
1127
+ sourceDirectoryHandle,
1128
+ destinationDirectoryHandle,
1129
+ sourceParentHandle,
1130
+ destinationParentHandle,
1131
+ ]) {
1132
+ if (!handle)
1133
+ continue;
1134
+ try {
1135
+ await closeFileHandle(handle);
1136
+ }
1137
+ catch (errorArg) {
1138
+ operationError = preferCleanupError(operationError, mutationPossible
1139
+ ? createSmartSecretSealedFileStoreError('MUTATION_OUTCOME_UNKNOWN')
1140
+ : errorArg);
1141
+ }
1142
+ }
1143
+ for (const lease of leases.reverse()) {
1144
+ try {
1145
+ await lease.release();
1146
+ }
1147
+ catch {
1148
+ operationError = preferCleanupError(operationError, createSmartSecretSealedFileStoreError(mutationPossible ? 'MUTATION_OUTCOME_UNKNOWN' : 'MUTEX_FAILED'));
1149
+ }
1150
+ }
1151
+ expectedKey?.fill(0);
1152
+ if (operationError) {
1153
+ resultKey?.fill(0);
1154
+ throw operationError;
1155
+ }
1156
+ const store = new SmartSecretSealedFileStore(options.destination, resultKey);
1157
+ resultKey = undefined;
1158
+ return store;
1159
+ }
1160
+ /** Explicitly discards this store's ciphertext and kernel master key. */
1161
+ static async reset(optionsArg) {
1162
+ const options = normalizeOptions(optionsArg);
1163
+ if (process.platform !== 'linux' || typeof process.geteuid !== 'function') {
1164
+ throw createSmartSecretSealedFileStoreError('KERNEL_UNAVAILABLE');
1165
+ }
1166
+ const lease = await acquireLease(options);
1167
+ let key;
1168
+ let operationError;
1169
+ try {
1170
+ const directoryHandle = await ensureDirectory(options.directoryPath);
1171
+ try {
1172
+ const names = await listOwnedFiles(directoryHandle);
1173
+ if (names.some((nameArg) => (nameArg === manifestName || entryFilePattern.test(nameArg)))) {
1174
+ const manifestValue = await readStrictJsonFile(directoryHandle, manifestName, 4 * 1_024);
1175
+ if (manifestValue === undefined) {
1176
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1177
+ }
1178
+ parseManifest(manifestValue, options);
1179
+ }
1180
+ try {
1181
+ await options.kernelStore.deleteEntry(options.masterKeyAccount);
1182
+ }
1183
+ catch (errorArg) {
1184
+ throw mapKernelError(errorArg);
1185
+ }
1186
+ const deletionOrder = names.filter((nameArg) => nameArg !== manifestName);
1187
+ if (names.includes(manifestName))
1188
+ deletionOrder.push(manifestName);
1189
+ for (const name of deletionOrder) {
1190
+ await removeAndSync(directoryHandle, name);
1191
+ }
1192
+ }
1193
+ catch (errorArg) {
1194
+ operationError = errorArg;
1195
+ }
1196
+ operationError = await closeFileHandleWithError(directoryHandle, operationError);
1197
+ if (operationError)
1198
+ throw operationError;
1199
+ key = await bootstrapUnderLease(options);
1200
+ }
1201
+ catch (errorArg) {
1202
+ operationError = errorArg;
1203
+ }
1204
+ try {
1205
+ await lease.release();
1206
+ }
1207
+ catch {
1208
+ operationError = preferCleanupError(operationError, createSmartSecretSealedFileStoreError('MUTEX_FAILED'));
1209
+ }
1210
+ if (operationError) {
1211
+ key?.fill(0);
1212
+ throw operationError;
1213
+ }
1214
+ const store = new SmartSecretSealedFileStore(options, key);
1215
+ key = undefined;
1216
+ return store;
1217
+ }
1218
+ getEntry(accountArg) {
1219
+ let account;
1220
+ try {
1221
+ account = normalizeSmartSecretKernelAccount(accountArg);
1222
+ }
1223
+ catch {
1224
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
1225
+ }
1226
+ return this.reserveOperation((deadlineArg, markAcquiredArg) => this.withLease(deadlineArg, markAcquiredArg, async () => {
1227
+ const directoryHandle = await openExistingDirectory(this.directoryPath);
1228
+ const id = entryId(this.options, account);
1229
+ let value;
1230
+ let operationError;
1231
+ try {
1232
+ await this.verifyManifest(directoryHandle);
1233
+ value = await readStrictJsonFile(directoryHandle, `${id}.sealed.json`, maximumEnvelopeBytes);
1234
+ }
1235
+ catch (errorArg) {
1236
+ operationError = errorArg;
1237
+ }
1238
+ operationError = await closeFileHandleWithError(directoryHandle, operationError);
1239
+ if (operationError)
1240
+ throw operationError;
1241
+ if (value === undefined)
1242
+ return null;
1243
+ const parsed = parseEnvelope(value);
1244
+ const aad = entryAad(this.options, account, id, fingerprint(this.masterKey));
1245
+ try {
1246
+ if (parsed.envelope.entryId !== id
1247
+ || parsed.envelope.masterKeyFingerprint !== fingerprint(this.masterKey))
1248
+ throw createSmartSecretSealedFileStoreError('ENVELOPE_INVALID');
1249
+ try {
1250
+ return await plugins.smartcrypto.aesGcmDecrypt({
1251
+ key: this.masterKey,
1252
+ encryptedData: parsed.encryptedData,
1253
+ aad,
1254
+ });
1255
+ }
1256
+ catch {
1257
+ throw createSmartSecretSealedFileStoreError('AUTHENTICATION_FAILED');
1258
+ }
1259
+ }
1260
+ finally {
1261
+ aad.fill(0);
1262
+ parsed.encryptedData.nonce.fill(0);
1263
+ parsed.encryptedData.ciphertext.fill(0);
1264
+ parsed.encryptedData.tag.fill(0);
1265
+ }
1266
+ }));
1267
+ }
1268
+ setEntry(accountArg, valueArg) {
1269
+ let account;
1270
+ try {
1271
+ account = normalizeSmartSecretKernelAccount(accountArg);
1272
+ }
1273
+ catch {
1274
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
1275
+ }
1276
+ let value;
1277
+ try {
1278
+ if (!(valueArg instanceof Uint8Array)) {
1279
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
1280
+ }
1281
+ if (valueArg.byteLength > smartSecretSealedFileMaximumEntryBytes) {
1282
+ throw createSmartSecretSealedFileStoreError('SIZE_LIMIT_EXCEEDED');
1283
+ }
1284
+ value = new Uint8Array(valueArg);
1285
+ }
1286
+ catch (errorArg) {
1287
+ if (errorArg instanceof SmartSecretSealedFileStoreError)
1288
+ throw errorArg;
1289
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
1290
+ }
1291
+ let result;
1292
+ try {
1293
+ result = this.reserveOperation((deadlineArg, markAcquiredArg) => this.withLease(deadlineArg, markAcquiredArg, async () => {
1294
+ const directoryHandle = await openExistingDirectory(this.directoryPath);
1295
+ let encrypted;
1296
+ const id = entryId(this.options, account);
1297
+ const keyFingerprint = fingerprint(this.masterKey);
1298
+ const aad = entryAad(this.options, account, id, keyFingerprint);
1299
+ let operationError;
1300
+ try {
1301
+ await this.verifyManifest(directoryHandle);
1302
+ try {
1303
+ encrypted = await plugins.smartcrypto.aesGcmEncrypt({
1304
+ key: this.masterKey,
1305
+ plaintext: value,
1306
+ aad,
1307
+ });
1308
+ }
1309
+ catch {
1310
+ throw createSmartSecretSealedFileStoreError('AUTHENTICATION_FAILED');
1311
+ }
1312
+ const envelope = {
1313
+ schemaVersion,
1314
+ profile,
1315
+ entryId: id,
1316
+ masterKeyFingerprint: keyFingerprint,
1317
+ ...encodeEncryptedData(encrypted),
1318
+ };
1319
+ await atomicWriteJson(directoryHandle, `${id}.sealed.json`, envelope);
1320
+ }
1321
+ catch (errorArg) {
1322
+ operationError = errorArg;
1323
+ }
1324
+ try {
1325
+ aad.fill(0);
1326
+ encrypted?.nonce.fill(0);
1327
+ encrypted?.ciphertext.fill(0);
1328
+ encrypted?.tag.fill(0);
1329
+ }
1330
+ finally {
1331
+ operationError = await closeFileHandleWithError(directoryHandle, operationError);
1332
+ }
1333
+ if (operationError)
1334
+ throw operationError;
1335
+ }));
1336
+ }
1337
+ catch (errorArg) {
1338
+ value.fill(0);
1339
+ throw errorArg;
1340
+ }
1341
+ return result.finally(() => value.fill(0));
1342
+ }
1343
+ deleteEntry(accountArg) {
1344
+ let account;
1345
+ try {
1346
+ account = normalizeSmartSecretKernelAccount(accountArg);
1347
+ }
1348
+ catch {
1349
+ throw createSmartSecretSealedFileStoreError('INVALID_ARGUMENT');
1350
+ }
1351
+ return this.reserveOperation((deadlineArg, markAcquiredArg) => this.withLease(deadlineArg, markAcquiredArg, async () => {
1352
+ const directoryHandle = await openExistingDirectory(this.directoryPath);
1353
+ let result;
1354
+ let operationError;
1355
+ try {
1356
+ await this.verifyManifest(directoryHandle);
1357
+ const id = entryId(this.options, account);
1358
+ result = await removeAndSync(directoryHandle, `${id}.sealed.json`);
1359
+ }
1360
+ catch (errorArg) {
1361
+ operationError = errorArg;
1362
+ }
1363
+ operationError = await closeFileHandleWithError(directoryHandle, operationError);
1364
+ if (operationError)
1365
+ throw operationError;
1366
+ return result;
1367
+ }));
1368
+ }
1369
+ close() {
1370
+ if (this.closePromise)
1371
+ return this.closePromise;
1372
+ this.lifecycleState = 'closing';
1373
+ const operationTail = this.operationTail;
1374
+ const closePromise = operationTail.finally(() => {
1375
+ this.masterKey.fill(0);
1376
+ this.lifecycleState = 'closed';
1377
+ });
1378
+ this.closePromise = closePromise;
1379
+ return closePromise;
1380
+ }
1381
+ reserveOperation(operationArg) {
1382
+ if (this.lifecycleState !== 'ready') {
1383
+ throw createSmartSecretSealedFileStoreError('STORE_CLOSED');
1384
+ }
1385
+ if (this.pendingOperations >= maximumPendingOperations) {
1386
+ throw createSmartSecretSealedFileStoreError('OPERATION_LIMIT_REACHED');
1387
+ }
1388
+ this.pendingOperations += 1;
1389
+ const deadline = performance.now() + operationTimeoutMs;
1390
+ let admissionExpired = false;
1391
+ let admissionTimer;
1392
+ let rejectAdmission;
1393
+ const admissionTimeout = new Promise((_resolveArg, rejectArg) => {
1394
+ rejectAdmission = rejectArg;
1395
+ });
1396
+ const clearAdmissionTimer = () => {
1397
+ if (admissionTimer) {
1398
+ clearTimeout(admissionTimer);
1399
+ admissionTimer = undefined;
1400
+ }
1401
+ };
1402
+ const markAcquired = () => clearAdmissionTimer();
1403
+ admissionTimer = setTimeout(() => {
1404
+ admissionExpired = true;
1405
+ admissionTimer = undefined;
1406
+ rejectAdmission(createSmartSecretSealedFileStoreError('MUTEX_FAILED'));
1407
+ }, operationTimeoutMs);
1408
+ const execution = this.operationTail.then(() => {
1409
+ if (admissionExpired || performance.now() >= deadline) {
1410
+ throw createSmartSecretSealedFileStoreError('MUTEX_FAILED');
1411
+ }
1412
+ return operationArg(deadline, markAcquired);
1413
+ });
1414
+ this.operationTail = execution.then(() => undefined, () => undefined);
1415
+ execution.then(() => {
1416
+ clearAdmissionTimer();
1417
+ this.pendingOperations -= 1;
1418
+ }, () => {
1419
+ clearAdmissionTimer();
1420
+ this.pendingOperations -= 1;
1421
+ });
1422
+ return Promise.race([execution, admissionTimeout]);
1423
+ }
1424
+ async withLease(deadlineArg, markAcquiredArg, operationArg) {
1425
+ const lease = await acquireLease(this.options, deadlineArg);
1426
+ markAcquiredArg();
1427
+ let result;
1428
+ let operationError;
1429
+ try {
1430
+ result = await operationArg();
1431
+ }
1432
+ catch (errorArg) {
1433
+ operationError = errorArg;
1434
+ }
1435
+ try {
1436
+ await lease.release();
1437
+ }
1438
+ catch {
1439
+ wipeDiscardedResult(result);
1440
+ if (mutationOutcomeUnknown(operationError))
1441
+ throw operationError;
1442
+ throw createSmartSecretSealedFileStoreError('MUTEX_FAILED');
1443
+ }
1444
+ if (operationError)
1445
+ throw operationError;
1446
+ return result;
1447
+ }
1448
+ async verifyManifest(directoryHandleArg) {
1449
+ const value = await readStrictJsonFile(directoryHandleArg, manifestName, 4 * 1_024);
1450
+ if (value === undefined)
1451
+ throw createSmartSecretSealedFileStoreError('FILESYSTEM_FAILED');
1452
+ const manifest = parseManifest(value, this.options);
1453
+ if (manifest.masterKeyFingerprint !== fingerprint(this.masterKey)) {
1454
+ throw createSmartSecretSealedFileStoreError('MASTER_KEY_CONFLICT');
1455
+ }
1456
+ }
1457
+ }
1458
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzZWNyZXQuc2VhbGVkZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c2VjcmV0LnNlYWxlZGZpbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSwwQkFBMEIsQ0FBQztBQUNwRCxPQUFPLEVBQ0wsMkJBQTJCLEdBQzVCLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUNMLGlDQUFpQyxFQUNqQyxpQ0FBaUMsR0FHbEMsTUFBTSxrQ0FBa0MsQ0FBQztBQUMxQyxPQUFPLEVBQ0wsK0JBQStCLEVBQy9CLHFDQUFxQyxHQUN0QyxNQUFNLG1DQUFtQyxDQUFDO0FBRTNDLE1BQU0sQ0FBQyxNQUFNLHNDQUFzQyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFFbEUsTUFBTSxhQUFhLEdBQUcsQ0FBVSxDQUFDO0FBQ2pDLE1BQU0sT0FBTyxHQUFHLHdDQUFpRCxDQUFDO0FBQ2xFLE1BQU0sWUFBWSxHQUFHLGVBQWUsQ0FBQztBQUNyQyxNQUFNLHFCQUFxQixHQUFHLDhCQUE4QixDQUFDO0FBQzdELE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQztBQUMxQixNQUFNLG9CQUFvQixHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFDekMsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUM7QUFDbEMsTUFBTSxzQkFBc0IsR0FBRyxxQkFBcUIsQ0FBQztBQUNyRCxNQUFNLGdCQUFnQixHQUFHLG1DQUFtQyxDQUFDO0FBQzdELE1BQU0sb0JBQW9CLEdBQUcsd0NBQXdDLENBQUM7QUFDdEUsTUFBTSx3QkFBd0IsR0FBRyxFQUFFLENBQUM7QUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztBQXdHbEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLFNBQXVCLEVBQWMsRUFBRTtJQUN4RCxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FB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