@brightchain/brightchain-lib 0.29.27 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/package.json +2 -2
  2. package/src/lib/constants.d.ts +3 -26
  3. package/src/lib/constants.d.ts.map +1 -1
  4. package/src/lib/constants.js +2 -1
  5. package/src/lib/constants.js.map +1 -1
  6. package/src/lib/db/collection.d.ts +1 -1
  7. package/src/lib/db/collection.d.ts.map +1 -1
  8. package/src/lib/db/collection.js +2 -1
  9. package/src/lib/db/collection.js.map +1 -1
  10. package/src/lib/enumerations/brightChainStrings.d.ts +18 -0
  11. package/src/lib/enumerations/brightChainStrings.d.ts.map +1 -1
  12. package/src/lib/enumerations/brightChainStrings.js +20 -0
  13. package/src/lib/enumerations/brightChainStrings.js.map +1 -1
  14. package/src/lib/enumerations/friendRequestStatus.d.ts +7 -0
  15. package/src/lib/enumerations/friendRequestStatus.d.ts.map +1 -0
  16. package/src/lib/enumerations/friendRequestStatus.js +11 -0
  17. package/src/lib/enumerations/friendRequestStatus.js.map +1 -0
  18. package/src/lib/enumerations/friendsErrorCode.d.ts +10 -0
  19. package/src/lib/enumerations/friendsErrorCode.d.ts.map +1 -0
  20. package/src/lib/enumerations/friendsErrorCode.js +14 -0
  21. package/src/lib/enumerations/friendsErrorCode.js.map +1 -0
  22. package/src/lib/enumerations/friendshipStatus.d.ts +7 -0
  23. package/src/lib/enumerations/friendshipStatus.d.ts.map +1 -0
  24. package/src/lib/enumerations/friendshipStatus.js +11 -0
  25. package/src/lib/enumerations/friendshipStatus.js.map +1 -0
  26. package/src/lib/enumerations/index.d.ts +3 -0
  27. package/src/lib/enumerations/index.d.ts.map +1 -1
  28. package/src/lib/enumerations/index.js +4 -0
  29. package/src/lib/enumerations/index.js.map +1 -1
  30. package/src/lib/errors/friendsServiceError.d.ts +20 -0
  31. package/src/lib/errors/friendsServiceError.d.ts.map +1 -0
  32. package/src/lib/errors/friendsServiceError.js +48 -0
  33. package/src/lib/errors/friendsServiceError.js.map +1 -0
  34. package/src/lib/errors/index.d.ts +5 -0
  35. package/src/lib/errors/index.d.ts.map +1 -1
  36. package/src/lib/errors/index.js +8 -0
  37. package/src/lib/errors/index.js.map +1 -1
  38. package/src/lib/i18n/strings/englishUs.d.ts.map +1 -1
  39. package/src/lib/i18n/strings/englishUs.js +20 -0
  40. package/src/lib/i18n/strings/englishUs.js.map +1 -1
  41. package/src/lib/i18n/strings/french.d.ts.map +1 -1
  42. package/src/lib/i18n/strings/french.js +20 -0
  43. package/src/lib/i18n/strings/french.js.map +1 -1
  44. package/src/lib/i18n/strings/german.d.ts.map +1 -1
  45. package/src/lib/i18n/strings/german.js +20 -0
  46. package/src/lib/i18n/strings/german.js.map +1 -1
  47. package/src/lib/i18n/strings/japanese.d.ts.map +1 -1
  48. package/src/lib/i18n/strings/japanese.js +20 -0
  49. package/src/lib/i18n/strings/japanese.js.map +1 -1
  50. package/src/lib/i18n/strings/mandarin.d.ts.map +1 -1
  51. package/src/lib/i18n/strings/mandarin.js +20 -0
  52. package/src/lib/i18n/strings/mandarin.js.map +1 -1
  53. package/src/lib/i18n/strings/spanish.d.ts.map +1 -1
  54. package/src/lib/i18n/strings/spanish.js +20 -0
  55. package/src/lib/i18n/strings/spanish.js.map +1 -1
  56. package/src/lib/i18n/strings/ukrainian.d.ts.map +1 -1
  57. package/src/lib/i18n/strings/ukrainian.js +20 -0
  58. package/src/lib/i18n/strings/ukrainian.js.map +1 -1
  59. package/src/lib/interfaces/appSubsystemPlugin.d.ts +69 -0
  60. package/src/lib/interfaces/appSubsystemPlugin.d.ts.map +1 -0
  61. package/src/lib/interfaces/appSubsystemPlugin.js +3 -0
  62. package/src/lib/interfaces/appSubsystemPlugin.js.map +1 -0
  63. package/src/lib/interfaces/communication.d.ts +2 -0
  64. package/src/lib/interfaces/communication.d.ts.map +1 -1
  65. package/src/lib/interfaces/constants.d.ts +2 -0
  66. package/src/lib/interfaces/constants.d.ts.map +1 -1
  67. package/src/lib/interfaces/friends/baseFriendRequest.d.ts +13 -0
  68. package/src/lib/interfaces/friends/baseFriendRequest.d.ts.map +1 -0
  69. package/src/lib/interfaces/friends/baseFriendRequest.js +3 -0
  70. package/src/lib/interfaces/friends/baseFriendRequest.js.map +1 -0
  71. package/src/lib/interfaces/friends/baseFriendship.d.ts +11 -0
  72. package/src/lib/interfaces/friends/baseFriendship.d.ts.map +1 -0
  73. package/src/lib/interfaces/friends/baseFriendship.js +3 -0
  74. package/src/lib/interfaces/friends/baseFriendship.js.map +1 -0
  75. package/src/lib/interfaces/friends/friendsService.d.ts +32 -0
  76. package/src/lib/interfaces/friends/friendsService.d.ts.map +1 -0
  77. package/src/lib/interfaces/friends/friendsService.js +3 -0
  78. package/src/lib/interfaces/friends/friendsService.js.map +1 -0
  79. package/src/lib/interfaces/friends/friendsSuggestionProvider.d.ts +17 -0
  80. package/src/lib/interfaces/friends/friendsSuggestionProvider.d.ts.map +1 -0
  81. package/src/lib/interfaces/friends/friendsSuggestionProvider.js +3 -0
  82. package/src/lib/interfaces/friends/friendsSuggestionProvider.js.map +1 -0
  83. package/src/lib/interfaces/friends/index.d.ts +6 -0
  84. package/src/lib/interfaces/friends/index.d.ts.map +1 -0
  85. package/src/lib/interfaces/friends/index.js +3 -0
  86. package/src/lib/interfaces/friends/index.js.map +1 -0
  87. package/src/lib/interfaces/friends/pagination.d.ts +11 -0
  88. package/src/lib/interfaces/friends/pagination.d.ts.map +1 -0
  89. package/src/lib/interfaces/friends/pagination.js +3 -0
  90. package/src/lib/interfaces/friends/pagination.js.map +1 -0
  91. package/src/lib/interfaces/index.d.ts +2 -0
  92. package/src/lib/interfaces/index.d.ts.map +1 -1
  93. package/src/lib/interfaces/storage/documentTypes.d.ts +4 -0
  94. package/src/lib/interfaces/storage/documentTypes.d.ts.map +1 -1
  95. package/src/lib/services/communication/channelService.d.ts +16 -2
  96. package/src/lib/services/communication/channelService.d.ts.map +1 -1
  97. package/src/lib/services/communication/channelService.js +78 -13
  98. package/src/lib/services/communication/channelService.js.map +1 -1
  99. package/src/lib/services/communication/conversationService.d.ts.map +1 -1
  100. package/src/lib/services/communication/conversationService.js +32 -2
  101. package/src/lib/services/communication/conversationService.js.map +1 -1
  102. package/src/lib/services/communication/groupService.d.ts.map +1 -1
  103. package/src/lib/services/communication/groupService.js +28 -2
  104. package/src/lib/services/communication/groupService.js.map +1 -1
  105. package/src/lib/services/communication/serverService.js +4 -6
  106. package/src/lib/services/communication/serverService.js.map +1 -1
  107. package/src/lib/services/copyOnWrite.service.d.ts +110 -0
  108. package/src/lib/services/copyOnWrite.service.d.ts.map +1 -0
  109. package/src/lib/services/copyOnWrite.service.js +256 -0
  110. package/src/lib/services/copyOnWrite.service.js.map +1 -0
  111. package/src/lib/services/index.d.ts +1 -0
  112. package/src/lib/services/index.d.ts.map +1 -1
  113. package/src/lib/services/index.js +1 -0
  114. package/src/lib/services/index.js.map +1 -1
  115. package/src/lib/services/memberStore.d.ts +7 -1
  116. package/src/lib/services/memberStore.d.ts.map +1 -1
  117. package/src/lib/services/memberStore.js +57 -1
  118. package/src/lib/services/memberStore.js.map +1 -1
  119. package/src/lib/utils/index.d.ts +6 -0
  120. package/src/lib/utils/index.d.ts.map +1 -1
  121. package/src/lib/utils/index.js +9 -0
  122. package/src/lib/utils/index.js.map +1 -1
  123. package/src/lib/utils/sortPair.d.ts +6 -0
  124. package/src/lib/utils/sortPair.d.ts.map +1 -0
  125. package/src/lib/utils/sortPair.js +11 -0
  126. package/src/lib/utils/sortPair.js.map +1 -0
@@ -0,0 +1,110 @@
1
+ import { Member, type PlatformID } from '@digitaldefiance/ecies-lib';
2
+ import { ConstituentBlockListBlock } from '../blocks/cbl';
3
+ import { ExtendedCBL } from '../blocks/extendedCbl';
4
+ import { InMemoryBlockTuple } from '../blocks/memoryTuple';
5
+ import { RandomBlock } from '../blocks/random';
6
+ import { WhitenedBlock } from '../blocks/whitened';
7
+ import { BlockSize } from '../enumerations/blockSize';
8
+ import { Checksum } from '../types/checksum';
9
+ import type { CBLService } from './cblService';
10
+ import type { ChecksumService } from './checksum.service';
11
+ /**
12
+ * Result of a CopyOnWrite operation.
13
+ * Contains the new CBL and metadata about what changed.
14
+ */
15
+ export interface CopyOnWriteResult<TID extends PlatformID = Uint8Array> {
16
+ /** The new CBL referencing both reused and new blocks */
17
+ cbl: ConstituentBlockListBlock<TID> | ExtendedCBL<TID>;
18
+ /** Number of tuples reused from the original CBL */
19
+ reusedTupleCount: number;
20
+ /** Number of new tuples created for changed data */
21
+ newTupleCount: number;
22
+ /** Total number of tuples in the new CBL */
23
+ totalTupleCount: number;
24
+ }
25
+ /**
26
+ * Options for the CopyOnWrite operation.
27
+ */
28
+ export interface CopyOnWriteOptions {
29
+ /** If true, create an ExtendedCBL with file metadata */
30
+ createExtendedCbl?: boolean;
31
+ /** File name for ExtendedCBL */
32
+ fileName?: string;
33
+ /** MIME type for ExtendedCBL */
34
+ mimeType?: string;
35
+ }
36
+ /**
37
+ * CopyOnWriteService provides efficient versioning for CBL-based data.
38
+ *
39
+ * When data changes, instead of re-creating all blocks from scratch, this service:
40
+ * 1. Reads the new data in block-sized chunks
41
+ * 2. Compares each chunk against the corresponding original block data
42
+ * (recovered by XORing the tuple's constituent blocks)
43
+ * 3. Reuses the original tuple addresses for unchanged blocks
44
+ * 4. Creates new tuples only for blocks whose data has changed
45
+ * 5. Produces a new CBL that references both old (reused) and new block addresses
46
+ *
47
+ * This is analogous to copy-on-write in operating systems: we share unchanged
48
+ * pages and only allocate new storage for modified pages.
49
+ *
50
+ * The tuple size (typically 3) means each "logical block" in the CBL is
51
+ * represented by `tupleSize` addresses. When we say "reuse a tuple," we
52
+ * mean we copy all `tupleSize` addresses from the old CBL into the new one.
53
+ *
54
+ * @typeParam TID - The platform ID type (defaults to Uint8Array)
55
+ */
56
+ export declare class CopyOnWriteService<TID extends PlatformID = Uint8Array> {
57
+ private readonly checksumService;
58
+ private readonly cblService;
59
+ constructor(checksumService?: ChecksumService, cblService?: CBLService<TID>);
60
+ /**
61
+ * Create a new version of a CBL by applying changes from new data,
62
+ * reusing unchanged blocks from the original CBL.
63
+ *
64
+ * @param originalCbl - The existing CBL to base the new version on
65
+ * @param newData - The complete new data as a Uint8Array
66
+ * @param creator - The member creating the new version
67
+ * @param blockSize - The block size to use (must match the original CBL's block size)
68
+ * @param getBlockData - Function to retrieve raw block data by checksum from the store
69
+ * @param whitenedBlockSource - Function to get whitened blocks for new tuples
70
+ * @param randomBlockSource - Function to get random blocks for new tuples
71
+ * @param persistTuple - Function to persist newly created tuples
72
+ * @param options - Optional settings for extended CBL creation
73
+ * @returns The new CBL and statistics about reuse
74
+ */
75
+ newVersion(originalCbl: ConstituentBlockListBlock<TID>, newData: Uint8Array, creator: Member<TID>, blockSize: BlockSize, getBlockData: (checksum: Checksum) => Promise<Uint8Array>, whitenedBlockSource: () => WhitenedBlock | undefined, randomBlockSource: () => RandomBlock, persistTuple: (tuple: InMemoryBlockTuple) => Promise<void>, options?: CopyOnWriteOptions): Promise<CopyOnWriteResult<TID>>;
76
+ /**
77
+ * Recover the original plaintext data from a tuple by XORing all
78
+ * constituent blocks together.
79
+ *
80
+ * In the OFF system, a tuple of `tupleSize` blocks is stored such that
81
+ * XORing all blocks together recovers the original data:
82
+ * plaintext = block[0] XOR block[1] XOR ... XOR block[tupleSize-1]
83
+ *
84
+ * @param tupleAddresses - The checksums of the blocks in the tuple
85
+ * @param getBlockData - Function to retrieve raw block data by checksum
86
+ * @returns The recovered plaintext data
87
+ */
88
+ private recoverTupleData;
89
+ /**
90
+ * Compare two block-sized byte arrays for equality.
91
+ * Uses constant-length comparison (always checks all bytes).
92
+ */
93
+ private blocksEqual;
94
+ /**
95
+ * Create a new tuple for a data block by XORing it with whitener/random blocks,
96
+ * then persist the tuple.
97
+ *
98
+ * @returns The checksums of all blocks in the new tuple (in order)
99
+ */
100
+ private createNewTuple;
101
+ /**
102
+ * Convert an array of Checksums to a concatenated Uint8Array buffer.
103
+ */
104
+ private addressesToBuffer;
105
+ /**
106
+ * Helper to convert a Readable stream to Uint8Array.
107
+ */
108
+ private streamToUint8Array;
109
+ }
110
+ //# sourceMappingURL=copyOnWrite.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyOnWrite.service.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/copyOnWrite.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAInD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IACpE,yDAAyD;IACzD,GAAG,EAAE,yBAAyB,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IACvD,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAkB,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IACjE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;gBAG3C,eAAe,CAAC,EAAE,eAAe,EACjC,UAAU,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC;IAQ9B;;;;;;;;;;;;;;OAcG;IACU,UAAU,CACrB,WAAW,EAAE,yBAAyB,CAAC,GAAG,CAAC,EAC3C,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,EACpB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,UAAU,CAAC,EACzD,mBAAmB,EAAE,MAAM,aAAa,GAAG,SAAS,EACpD,iBAAiB,EAAE,MAAM,WAAW,EACpC,YAAY,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,EAC1D,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IA0HlC;;;;;;;;;;;OAWG;YACW,gBAAgB;IA2B9B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;;;OAKG;YACW,cAAc;IAkD5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;YACW,kBAAkB;CAcjC"}
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CopyOnWriteService = void 0;
4
+ const cbl_1 = require("../blocks/cbl");
5
+ const extendedCbl_1 = require("../blocks/extendedCbl");
6
+ const memoryTuple_1 = require("../blocks/memoryTuple");
7
+ const rawData_1 = require("../blocks/rawData");
8
+ const constants_1 = require("../constants");
9
+ const blockEncryptionType_1 = require("../enumerations/blockEncryptionType");
10
+ const globalServiceProvider_1 = require("./globalServiceProvider");
11
+ /**
12
+ * CopyOnWriteService provides efficient versioning for CBL-based data.
13
+ *
14
+ * When data changes, instead of re-creating all blocks from scratch, this service:
15
+ * 1. Reads the new data in block-sized chunks
16
+ * 2. Compares each chunk against the corresponding original block data
17
+ * (recovered by XORing the tuple's constituent blocks)
18
+ * 3. Reuses the original tuple addresses for unchanged blocks
19
+ * 4. Creates new tuples only for blocks whose data has changed
20
+ * 5. Produces a new CBL that references both old (reused) and new block addresses
21
+ *
22
+ * This is analogous to copy-on-write in operating systems: we share unchanged
23
+ * pages and only allocate new storage for modified pages.
24
+ *
25
+ * The tuple size (typically 3) means each "logical block" in the CBL is
26
+ * represented by `tupleSize` addresses. When we say "reuse a tuple," we
27
+ * mean we copy all `tupleSize` addresses from the old CBL into the new one.
28
+ *
29
+ * @typeParam TID - The platform ID type (defaults to Uint8Array)
30
+ */
31
+ class CopyOnWriteService {
32
+ checksumService;
33
+ cblService;
34
+ constructor(checksumService, cblService) {
35
+ this.checksumService =
36
+ checksumService ?? (0, globalServiceProvider_1.getGlobalServiceProvider)().checksumService;
37
+ this.cblService =
38
+ cblService ?? (0, globalServiceProvider_1.getGlobalServiceProvider)().cblService;
39
+ }
40
+ /**
41
+ * Create a new version of a CBL by applying changes from new data,
42
+ * reusing unchanged blocks from the original CBL.
43
+ *
44
+ * @param originalCbl - The existing CBL to base the new version on
45
+ * @param newData - The complete new data as a Uint8Array
46
+ * @param creator - The member creating the new version
47
+ * @param blockSize - The block size to use (must match the original CBL's block size)
48
+ * @param getBlockData - Function to retrieve raw block data by checksum from the store
49
+ * @param whitenedBlockSource - Function to get whitened blocks for new tuples
50
+ * @param randomBlockSource - Function to get random blocks for new tuples
51
+ * @param persistTuple - Function to persist newly created tuples
52
+ * @param options - Optional settings for extended CBL creation
53
+ * @returns The new CBL and statistics about reuse
54
+ */
55
+ async newVersion(originalCbl, newData, creator, blockSize, getBlockData, whitenedBlockSource, randomBlockSource, persistTuple, options) {
56
+ const now = new Date();
57
+ const tupleSize = originalCbl.tupleSize;
58
+ const originalAddresses = originalCbl.addresses;
59
+ const blockSizeBytes = blockSize;
60
+ // Calculate how many logical blocks (tuples) the original CBL has
61
+ const originalTupleCount = Math.floor(originalAddresses.length / tupleSize);
62
+ // Calculate how many logical blocks the new data needs
63
+ const newTotalBlocks = Math.ceil(newData.length / blockSizeBytes);
64
+ // We'll build the new address list tuple by tuple
65
+ const newAddressList = [];
66
+ let reusedTupleCount = 0;
67
+ let newTupleCount = 0;
68
+ for (let tupleIndex = 0; tupleIndex < newTotalBlocks; tupleIndex++) {
69
+ // Extract the new data chunk for this block position
70
+ const chunkStart = tupleIndex * blockSizeBytes;
71
+ const chunkEnd = Math.min(chunkStart + blockSizeBytes, newData.length);
72
+ let newChunk = newData.slice(chunkStart, chunkEnd);
73
+ // Pad the last chunk if needed
74
+ if (newChunk.length < blockSizeBytes) {
75
+ const padded = new Uint8Array(blockSizeBytes);
76
+ padded.set(newChunk);
77
+ // Remaining bytes are zero-filled (deterministic padding for comparison)
78
+ newChunk = padded;
79
+ }
80
+ // Check if we can reuse the original tuple at this position
81
+ let reused = false;
82
+ if (tupleIndex < originalTupleCount) {
83
+ const originalTupleStart = tupleIndex * tupleSize;
84
+ const originalTupleAddresses = originalAddresses.slice(originalTupleStart, originalTupleStart + tupleSize);
85
+ // Recover the original plaintext by XORing all blocks in the tuple
86
+ try {
87
+ const originalPlaintext = await this.recoverTupleData(originalTupleAddresses, getBlockData);
88
+ // Compare: if the data is identical, reuse the old addresses
89
+ if (this.blocksEqual(newChunk, originalPlaintext)) {
90
+ for (const addr of originalTupleAddresses) {
91
+ newAddressList.push(addr);
92
+ }
93
+ reusedTupleCount++;
94
+ reused = true;
95
+ }
96
+ }
97
+ catch {
98
+ // If we can't recover the original data (block missing, etc.),
99
+ // fall through to create a new tuple
100
+ }
101
+ }
102
+ if (!reused) {
103
+ // Create a new tuple for this changed block
104
+ const tupleAddresses = await this.createNewTuple(newChunk, blockSize, creator, whitenedBlockSource, randomBlockSource, persistTuple, now);
105
+ for (const addr of tupleAddresses) {
106
+ newAddressList.push(addr);
107
+ }
108
+ newTupleCount++;
109
+ }
110
+ }
111
+ // Build the address list buffer
112
+ const addressListBuffer = this.addressesToBuffer(newAddressList);
113
+ // Create the new CBL header
114
+ const isExtended = options?.createExtendedCbl && options.fileName;
115
+ const extendedInfo = isExtended
116
+ ? {
117
+ fileName: options.fileName,
118
+ mimeType: options?.mimeType ?? 'application/octet-stream',
119
+ }
120
+ : undefined;
121
+ const { headerData } = this.cblService.makeCblHeader(creator, now, newAddressList.length, newData.length, addressListBuffer, blockSize, blockEncryptionType_1.BlockEncryptionType.None, extendedInfo, tupleSize);
122
+ // Assemble the full CBL data: header + address list
123
+ const cblData = new Uint8Array(headerData.length + addressListBuffer.length);
124
+ cblData.set(headerData, 0);
125
+ cblData.set(addressListBuffer, headerData.length);
126
+ // Create the CBL block
127
+ const cbl = isExtended
128
+ ? new extendedCbl_1.ExtendedCBL(cblData, creator, blockSize)
129
+ : new cbl_1.ConstituentBlockListBlock(cblData, creator, blockSize);
130
+ return {
131
+ cbl,
132
+ reusedTupleCount,
133
+ newTupleCount,
134
+ totalTupleCount: reusedTupleCount + newTupleCount,
135
+ };
136
+ }
137
+ /**
138
+ * Recover the original plaintext data from a tuple by XORing all
139
+ * constituent blocks together.
140
+ *
141
+ * In the OFF system, a tuple of `tupleSize` blocks is stored such that
142
+ * XORing all blocks together recovers the original data:
143
+ * plaintext = block[0] XOR block[1] XOR ... XOR block[tupleSize-1]
144
+ *
145
+ * @param tupleAddresses - The checksums of the blocks in the tuple
146
+ * @param getBlockData - Function to retrieve raw block data by checksum
147
+ * @returns The recovered plaintext data
148
+ */
149
+ async recoverTupleData(tupleAddresses, getBlockData) {
150
+ if (tupleAddresses.length === 0) {
151
+ throw new Error('Cannot recover data from empty tuple');
152
+ }
153
+ // Load all blocks in the tuple
154
+ const blockDataArrays = await Promise.all(tupleAddresses.map((addr) => getBlockData(addr)));
155
+ // XOR all blocks together to recover the plaintext
156
+ const result = new Uint8Array(blockDataArrays[0].length);
157
+ result.set(blockDataArrays[0]);
158
+ for (let i = 1; i < blockDataArrays.length; i++) {
159
+ const current = blockDataArrays[i];
160
+ for (let j = 0; j < result.length; j++) {
161
+ result[j] ^= current[j];
162
+ }
163
+ }
164
+ return result;
165
+ }
166
+ /**
167
+ * Compare two block-sized byte arrays for equality.
168
+ * Uses constant-length comparison (always checks all bytes).
169
+ */
170
+ blocksEqual(a, b) {
171
+ if (a.length !== b.length) {
172
+ return false;
173
+ }
174
+ let equal = true;
175
+ for (let i = 0; i < a.length; i++) {
176
+ if (a[i] !== b[i]) {
177
+ equal = false;
178
+ // Don't break early — we compare all bytes for consistency,
179
+ // though this isn't a security-sensitive comparison
180
+ break;
181
+ }
182
+ }
183
+ return equal;
184
+ }
185
+ /**
186
+ * Create a new tuple for a data block by XORing it with whitener/random blocks,
187
+ * then persist the tuple.
188
+ *
189
+ * @returns The checksums of all blocks in the new tuple (in order)
190
+ */
191
+ async createNewTuple(data, blockSize, creator, whitenedBlockSource, randomBlockSource, persistTuple, dateCreated) {
192
+ // Gather whitener/random blocks for the tuple (tupleSize - 1 blocks)
193
+ const companions = [];
194
+ for (let i = 0; i < constants_1.TUPLE.SIZE - 1; i++) {
195
+ const whitened = whitenedBlockSource();
196
+ if (whitened) {
197
+ companions.push(whitened);
198
+ }
199
+ else {
200
+ companions.push(randomBlockSource());
201
+ }
202
+ }
203
+ // XOR the data with all companion blocks to produce the "prime" block
204
+ let xored = new Uint8Array(data);
205
+ for (const companion of companions) {
206
+ const companionData = companion.data instanceof Uint8Array
207
+ ? companion.data
208
+ : await this.streamToUint8Array(companion.data);
209
+ for (let j = 0; j < xored.length; j++) {
210
+ xored[j] ^= companionData[j];
211
+ }
212
+ }
213
+ // Create the prime (XORed result) block
214
+ const primeChecksum = this.checksumService.calculateChecksum(xored);
215
+ const primeBlock = new rawData_1.RawDataBlock(blockSize, xored, dateCreated, primeChecksum);
216
+ // Build the tuple: [prime, ...companions]
217
+ const allBlocks = [primeBlock, ...companions];
218
+ const tuple = new memoryTuple_1.InMemoryBlockTuple(allBlocks);
219
+ await persistTuple(tuple);
220
+ // Return all block checksums in tuple order
221
+ return allBlocks.map((block) => block.idChecksum);
222
+ }
223
+ /**
224
+ * Convert an array of Checksums to a concatenated Uint8Array buffer.
225
+ */
226
+ addressesToBuffer(addresses) {
227
+ const buffers = addresses.map((addr) => addr.toUint8Array());
228
+ const totalLength = buffers.reduce((sum, buf) => sum + buf.length, 0);
229
+ const result = new Uint8Array(totalLength);
230
+ let offset = 0;
231
+ for (const buf of buffers) {
232
+ result.set(buf, offset);
233
+ offset += buf.length;
234
+ }
235
+ return result;
236
+ }
237
+ /**
238
+ * Helper to convert a Readable stream to Uint8Array.
239
+ */
240
+ async streamToUint8Array(readable) {
241
+ const chunks = [];
242
+ for await (const chunk of readable) {
243
+ chunks.push(new Uint8Array(chunk));
244
+ }
245
+ const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
246
+ const result = new Uint8Array(totalLength);
247
+ let offset = 0;
248
+ for (const chunk of chunks) {
249
+ result.set(chunk, offset);
250
+ offset += chunk.length;
251
+ }
252
+ return result;
253
+ }
254
+ }
255
+ exports.CopyOnWriteService = CopyOnWriteService;
256
+ //# sourceMappingURL=copyOnWrite.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyOnWrite.service.js","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/copyOnWrite.service.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ export * from './brightTrustService';
7
7
  export * from './brightTrustStateMachine';
8
8
  export * from './cblService';
9
9
  export * from './checksum.service';
10
+ export * from './copyOnWrite.service';
10
11
  export * from './crypto';
11
12
  export * from './fec.service';
12
13
  export * from './identitySealingPipeline';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AAGtB,cAAc,cAAc,CAAC;AAG7B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AAGtB,cAAc,cAAc,CAAC;AAG7B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,YAAY,CAAC"}
@@ -10,6 +10,7 @@ tslib_1.__exportStar(require("./brightTrustService"), exports);
10
10
  tslib_1.__exportStar(require("./brightTrustStateMachine"), exports);
11
11
  tslib_1.__exportStar(require("./cblService"), exports);
12
12
  tslib_1.__exportStar(require("./checksum.service"), exports);
13
+ tslib_1.__exportStar(require("./copyOnWrite.service"), exports);
13
14
  tslib_1.__exportStar(require("./crypto"), exports);
14
15
  tslib_1.__exportStar(require("./fec.service"), exports);
15
16
  tslib_1.__exportStar(require("./identitySealingPipeline"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,4DAAkC;AAClC,kEAAwC;AACxC,+DAAqC;AACrC,yDAA+B;AAC/B,+DAAqC;AACrC,oEAA0C;AAC1C,uDAA6B;AAC7B,6DAAmC;AACnC,mDAAyB;AACzB,wDAA8B;AAC9B,oEAA0C;AAC1C,8DAAoC;AACpC,mDAAyB;AACzB,mEAAyC;AACzC,wDAA8B;AAC9B,sDAA4B;AAC5B,4DAAkC;AAClC,6DAAmC;AACnC,2DAAiC;AACjC,8DAAoC;AACpC,0DAAgC;AAChC,gEAAsC;AACtC,wDAA8B;AAC9B,gDAAsB;AAEtB,4CAA4C;AAC5C,uDAA6B;AAE7B,8DAA8D;AAC9D,0DAAgC;AAEhC,6DAA6D;AAC7D,qDAA2B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,4DAAkC;AAClC,kEAAwC;AACxC,+DAAqC;AACrC,yDAA+B;AAC/B,+DAAqC;AACrC,oEAA0C;AAC1C,uDAA6B;AAC7B,6DAAmC;AACnC,gEAAsC;AACtC,mDAAyB;AACzB,wDAA8B;AAC9B,oEAA0C;AAC1C,8DAAoC;AACpC,mDAAyB;AACzB,mEAAyC;AACzC,wDAA8B;AAC9B,sDAA4B;AAC5B,4DAAkC;AAClC,6DAAmC;AACnC,2DAAiC;AACjC,8DAAoC;AACpC,0DAAgC;AAChC,gEAAsC;AACtC,wDAA8B;AAC9B,gDAAsB;AAEtB,4CAA4C;AAC5C,uDAA6B;AAE7B,8DAA8D;AAC9D,0DAAgC;AAEhC,6DAA6D;AAC7D,qDAA2B"}
@@ -109,7 +109,13 @@ export declare class MemberStore<TID extends PlatformID = Uint8Array> implements
109
109
  */
110
110
  deleteMember(id: TID): Promise<void>;
111
111
  /**
112
- * Update the member index
112
+ * Update the member index.
113
+ *
114
+ * Updates the in-memory indexes AND persists the entry to the
115
+ * `member_index` BrightDb collection (when `_db` is available) so that
116
+ * the data survives server restarts. Without this DB write, members
117
+ * created via `createMember()` / `register()` only existed in memory
118
+ * and were lost on restart.
113
119
  */
114
120
  updateIndex(entry: IMemberIndexEntry<TID>): Promise<void>;
115
121
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"memberStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/memberStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EACN,UAAU,EACV,YAAY,EAEb,MAAM,4BAA4B,CAAC;AAmBpC,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,iCAAiC,EAEjC,gCAAgC,EAEjC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAKrE;;GAEG;AACH,qBAAa,WAAW,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAC1D,YAAW,YAAY,CAAC,GAAG,CAAC;IAE5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,wEAAwE;IACxE,OAAO,CAAC,GAAG,CAAwB;IAEnC;;;;;;;;OAQG;IACH,OAAO,CAAC,SAAS;gBAoBL,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,cAAc;IASxD;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;OAIG;IACI,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAItC;;;;;;;;OAQG;YACW,yBAAyB;IA6DvC;;OAEG;IACU,YAAY,CACvB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC;QAAE,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;IAyVxE;;;;;;;;OAQG;IACU,SAAS,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAwErD;;;;;;;;;OASG;IACU,qBAAqB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA4CnE;;;;;;;;OAQG;IACU,gBAAgB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC;QAC9C,aAAa,EAAE,gCAAgC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAC5D,cAAc,EAAE,iCAAiC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;KAC/D,CAAC;IAoLF;;;;;;;;;;OAUG;IACU,YAAY,CACvB,EAAE,EAAE,GAAG,EACP,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAiLhB;;OAEG;IACU,YAAY,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjD;;OAEG;IACU,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2CtE;;;;;;;OAOG;IACU,UAAU,CACrB,QAAQ,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAClC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;IAmFnC;;;;;;OAMG;YACW,iBAAiB;IAsF/B;;OAEG;IAEU,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD;;OAEG;IACU,gBAAgB,CAC3B,QAAQ,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;CAIjB"}
1
+ {"version":3,"file":"memberStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/memberStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EACN,UAAU,EACV,YAAY,EAEb,MAAM,4BAA4B,CAAC;AAmBpC,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,iCAAiC,EAEjC,gCAAgC,EAEjC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAKrE;;GAEG;AACH,qBAAa,WAAW,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAC1D,YAAW,YAAY,CAAC,GAAG,CAAC;IAE5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,wEAAwE;IACxE,OAAO,CAAC,GAAG,CAAwB;IAEnC;;;;;;;;OAQG;IACH,OAAO,CAAC,SAAS;gBAoBL,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,cAAc;IASxD;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;OAIG;IACI,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAItC;;;;;;;;OAQG;YACW,yBAAyB;IA6DvC;;OAEG;IACU,YAAY,CACvB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC;QAAE,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;IAyVxE;;;;;;;;OAQG;IACU,SAAS,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAwErD;;;;;;;;;OASG;IACU,qBAAqB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA2DnE;;;;;;;;OAQG;IACU,gBAAgB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC;QAC9C,aAAa,EAAE,gCAAgC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAC5D,cAAc,EAAE,iCAAiC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;KAC/D,CAAC;IAoLF;;;;;;;;;;OAUG;IACU,YAAY,CACvB,EAAE,EAAE,GAAG,EACP,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAiLhB;;OAEG;IACU,YAAY,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjD;;;;;;;;OAQG;IACU,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFtE;;;;;;;OAOG;IACU,UAAU,CACrB,QAAQ,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAClC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;IAmFnC;;;;;;OAMG;YACW,iBAAiB;IAsF/B;;OAEG;IAEU,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD;;OAEG;IACU,gBAAgB,CAC3B,QAAQ,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;CAIjB"}
@@ -524,6 +524,16 @@ class MemberStore {
524
524
  console.info(`[MemberStore] getMemberPublicKeyHex: found publicKey in users collection for id=${idHex}`);
525
525
  return userDoc.publicKey;
526
526
  }
527
+ // Document exists but publicKey is empty/missing
528
+ if (userDoc) {
529
+ console.warn(`[MemberStore] getMemberPublicKeyHex: user document found for id=${idHex} but publicKey is empty`);
530
+ }
531
+ else {
532
+ console.warn(`[MemberStore] getMemberPublicKeyHex: no user document found in users collection for id=${idHex}`);
533
+ }
534
+ }
535
+ else {
536
+ console.warn('[MemberStore] getMemberPublicKeyHex: no DB reference set, skipping fast path');
527
537
  }
528
538
  // Fallback — reconstruct from CBL blocks (works for createMember() members)
529
539
  try {
@@ -860,7 +870,13 @@ class MemberStore {
860
870
  // The garbage collector will handle unreferenced blocks
861
871
  }
862
872
  /**
863
- * Update the member index
873
+ * Update the member index.
874
+ *
875
+ * Updates the in-memory indexes AND persists the entry to the
876
+ * `member_index` BrightDb collection (when `_db` is available) so that
877
+ * the data survives server restarts. Without this DB write, members
878
+ * created via `createMember()` / `register()` only existed in memory
879
+ * and were lost on restart.
864
880
  */
865
881
  async updateIndex(entry) {
866
882
  const provider = service_provider_1.ServiceProvider.getInstance().idProvider;
@@ -899,6 +915,46 @@ class MemberStore {
899
915
  }
900
916
  // Update member index
901
917
  this.memberIndex.set(id, entry);
918
+ // ── Persist to the member_index BrightDb collection ──────────────
919
+ // This ensures the entry survives server restarts. The _queryIndexFromDb
920
+ // fallback queries this collection when the in-memory index is empty.
921
+ if (this._db) {
922
+ try {
923
+ const indexCol = this._db.collection('member_index');
924
+ const doc = {
925
+ id,
926
+ publicCBL: entry.publicCBL.toHex(),
927
+ privateCBL: entry.privateCBL.toHex(),
928
+ ...(entry.publicProfileCBL
929
+ ? { publicProfileCBL: entry.publicProfileCBL.toHex() }
930
+ : {}),
931
+ ...(entry.privateProfileCBL
932
+ ? { privateProfileCBL: entry.privateProfileCBL.toHex() }
933
+ : {}),
934
+ poolId: this._db.name ?? '',
935
+ type: entry.type,
936
+ status: entry.status,
937
+ lastUpdate: entry.lastUpdate.toISOString(),
938
+ ...(entry.region ? { region: entry.region } : {}),
939
+ reputation: entry.reputation,
940
+ };
941
+ // Upsert: try update first, insert if not found
942
+ const existing = await indexCol.findOne({ id });
943
+ if (existing) {
944
+ await indexCol.updateOne({ id }, { $set: doc });
945
+ }
946
+ else {
947
+ await indexCol.insertOne(doc);
948
+ }
949
+ }
950
+ catch (err) {
951
+ // Log but don't fail — the in-memory index is already updated.
952
+ // On restart, _queryIndexFromDb will miss this entry, but the
953
+ // users collection doc (written separately) may still allow
954
+ // partial recovery.
955
+ console.warn('[MemberStore] Failed to persist member_index entry to DB:', err instanceof Error ? err.message : String(err));
956
+ }
957
+ }
902
958
  }
903
959
  /**
904
960
  * Query the member index.