@brightchain/brightchain-api-lib 0.25.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/package.json +4 -3
  2. package/src/lib/appConstants.d.ts +1 -1
  3. package/src/lib/appConstants.js +1 -1
  4. package/src/lib/application.d.ts +3 -14
  5. package/src/lib/application.d.ts.map +1 -1
  6. package/src/lib/application.js +91 -34
  7. package/src/lib/application.js.map +1 -1
  8. package/src/lib/constants.d.ts.map +1 -1
  9. package/src/lib/constants.js +1 -1
  10. package/src/lib/constants.js.map +1 -1
  11. package/src/lib/databaseInit.d.ts +7 -11
  12. package/src/lib/databaseInit.d.ts.map +1 -1
  13. package/src/lib/databaseInit.js +41 -107
  14. package/src/lib/databaseInit.js.map +1 -1
  15. package/src/lib/datastore/block-document-store-factory.d.ts +3 -0
  16. package/src/lib/datastore/block-document-store-factory.d.ts.map +1 -1
  17. package/src/lib/datastore/block-document-store-factory.js +15 -18
  18. package/src/lib/datastore/block-document-store-factory.js.map +1 -1
  19. package/src/lib/datastore/block-document-store.d.ts +2 -191
  20. package/src/lib/datastore/block-document-store.d.ts.map +1 -1
  21. package/src/lib/datastore/block-document-store.js +4 -628
  22. package/src/lib/datastore/block-document-store.js.map +1 -1
  23. package/src/lib/datastore/document-store.d.ts +1 -62
  24. package/src/lib/datastore/document-store.d.ts.map +1 -1
  25. package/src/lib/datastore/memory-document-store.d.ts +1 -8
  26. package/src/lib/datastore/memory-document-store.d.ts.map +1 -1
  27. package/src/lib/datastore/memory-document-store.js +3 -214
  28. package/src/lib/datastore/memory-document-store.js.map +1 -1
  29. package/src/lib/environment.d.ts +4 -47
  30. package/src/lib/environment.d.ts.map +1 -1
  31. package/src/lib/environment.js +2 -136
  32. package/src/lib/environment.js.map +1 -1
  33. package/src/lib/interfaces/environment.d.ts +3 -25
  34. package/src/lib/interfaces/environment.d.ts.map +1 -1
  35. package/src/lib/interfaces/responses/emailGatewayResponses.d.ts +30 -0
  36. package/src/lib/interfaces/responses/emailGatewayResponses.d.ts.map +1 -0
  37. package/src/lib/interfaces/responses/emailGatewayResponses.js +3 -0
  38. package/src/lib/interfaces/responses/emailGatewayResponses.js.map +1 -0
  39. package/src/lib/interfaces/responses/index.d.ts +1 -0
  40. package/src/lib/interfaces/responses/index.d.ts.map +1 -1
  41. package/src/lib/middleware/index.d.ts +1 -1
  42. package/src/lib/middleware/index.d.ts.map +1 -1
  43. package/src/lib/middleware/index.js +3 -2
  44. package/src/lib/middleware/index.js.map +1 -1
  45. package/src/lib/middleware/validateBody.d.ts +1 -12
  46. package/src/lib/middleware/validateBody.d.ts.map +1 -1
  47. package/src/lib/middleware/validateBody.js +4 -32
  48. package/src/lib/middleware/validateBody.js.map +1 -1
  49. package/src/lib/middlewares.d.ts.map +1 -1
  50. package/src/lib/middlewares.js +7 -1
  51. package/src/lib/middlewares.js.map +1 -1
  52. package/src/lib/plugins/brightchain-database-plugin.d.ts +27 -79
  53. package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
  54. package/src/lib/plugins/brightchain-database-plugin.js +32 -103
  55. package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
  56. package/src/lib/routers/app.d.ts.map +1 -1
  57. package/src/lib/routers/app.js +1 -0
  58. package/src/lib/routers/app.js.map +1 -1
  59. package/src/lib/services/emailGateway/antiSpamFilter.d.ts +229 -0
  60. package/src/lib/services/emailGateway/antiSpamFilter.d.ts.map +1 -0
  61. package/src/lib/services/emailGateway/antiSpamFilter.js +325 -0
  62. package/src/lib/services/emailGateway/antiSpamFilter.js.map +1 -0
  63. package/src/lib/services/emailGateway/bounceProcessor.d.ts +182 -0
  64. package/src/lib/services/emailGateway/bounceProcessor.d.ts.map +1 -0
  65. package/src/lib/services/emailGateway/bounceProcessor.js +391 -0
  66. package/src/lib/services/emailGateway/bounceProcessor.js.map +1 -0
  67. package/src/lib/services/emailGateway/emailAuthVerifier.d.ts +99 -0
  68. package/src/lib/services/emailGateway/emailAuthVerifier.d.ts.map +1 -0
  69. package/src/lib/services/emailGateway/emailAuthVerifier.js +202 -0
  70. package/src/lib/services/emailGateway/emailAuthVerifier.js.map +1 -0
  71. package/src/lib/services/emailGateway/emailGatewayConfig.d.ts +74 -0
  72. package/src/lib/services/emailGateway/emailGatewayConfig.d.ts.map +1 -0
  73. package/src/lib/services/emailGateway/emailGatewayConfig.js +107 -0
  74. package/src/lib/services/emailGateway/emailGatewayConfig.js.map +1 -0
  75. package/src/lib/services/emailGateway/emailGatewayService.d.ts +209 -0
  76. package/src/lib/services/emailGateway/emailGatewayService.d.ts.map +1 -0
  77. package/src/lib/services/emailGateway/emailGatewayService.js +254 -0
  78. package/src/lib/services/emailGateway/emailGatewayService.js.map +1 -0
  79. package/src/lib/services/emailGateway/gatewayObservability.d.ts +123 -0
  80. package/src/lib/services/emailGateway/gatewayObservability.d.ts.map +1 -0
  81. package/src/lib/services/emailGateway/gatewayObservability.js +186 -0
  82. package/src/lib/services/emailGateway/gatewayObservability.js.map +1 -0
  83. package/src/lib/services/emailGateway/inboundProcessor.d.ts +113 -0
  84. package/src/lib/services/emailGateway/inboundProcessor.d.ts.map +1 -0
  85. package/src/lib/services/emailGateway/inboundProcessor.js +298 -0
  86. package/src/lib/services/emailGateway/inboundProcessor.js.map +1 -0
  87. package/src/lib/services/emailGateway/index.d.ts +23 -0
  88. package/src/lib/services/emailGateway/index.d.ts.map +1 -0
  89. package/src/lib/services/emailGateway/index.js +26 -0
  90. package/src/lib/services/emailGateway/index.js.map +1 -0
  91. package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts +122 -0
  92. package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts.map +1 -0
  93. package/src/lib/services/emailGateway/outboundDeliveryWorker.js +110 -0
  94. package/src/lib/services/emailGateway/outboundDeliveryWorker.js.map +1 -0
  95. package/src/lib/services/emailGateway/outboundQueue.d.ts +135 -0
  96. package/src/lib/services/emailGateway/outboundQueue.d.ts.map +1 -0
  97. package/src/lib/services/emailGateway/outboundQueue.js +227 -0
  98. package/src/lib/services/emailGateway/outboundQueue.js.map +1 -0
  99. package/src/lib/services/emailGateway/outboundQueueStore.d.ts +110 -0
  100. package/src/lib/services/emailGateway/outboundQueueStore.d.ts.map +1 -0
  101. package/src/lib/services/emailGateway/outboundQueueStore.js +131 -0
  102. package/src/lib/services/emailGateway/outboundQueueStore.js.map +1 -0
  103. package/src/lib/services/emailGateway/recipientLookupService.d.ts +146 -0
  104. package/src/lib/services/emailGateway/recipientLookupService.d.ts.map +1 -0
  105. package/src/lib/services/emailGateway/recipientLookupService.js +307 -0
  106. package/src/lib/services/emailGateway/recipientLookupService.js.map +1 -0
  107. package/src/lib/services/emailGateway/retryBackoff.d.ts +79 -0
  108. package/src/lib/services/emailGateway/retryBackoff.d.ts.map +1 -0
  109. package/src/lib/services/emailGateway/retryBackoff.js +77 -0
  110. package/src/lib/services/emailGateway/retryBackoff.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/quorumDatabaseAdapter.d.ts +7 -1
  116. package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -1
  117. package/src/lib/services/quorumDatabaseAdapter.js +83 -0
  118. package/src/lib/services/quorumDatabaseAdapter.js.map +1 -1
  119. package/src/lib/services/sessionAdapter.d.ts +2 -61
  120. package/src/lib/services/sessionAdapter.d.ts.map +1 -1
  121. package/src/lib/services/sessionAdapter.js +2 -102
  122. package/src/lib/services/sessionAdapter.js.map +1 -1
  123. package/src/lib/shared-types.d.ts +7 -15
  124. package/src/lib/shared-types.d.ts.map +1 -1
  125. package/src/lib/types/backend-id.d.ts +1 -2
  126. package/src/lib/types/backend-id.d.ts.map +1 -1
  127. package/src/lib/validation/userValidation.d.ts +2 -43
  128. package/src/lib/validation/userValidation.d.ts.map +1 -1
  129. package/src/lib/validation/userValidation.js +6 -144
  130. package/src/lib/validation/userValidation.js.map +1 -1
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Outbound Queue Store — persistence interface and in-memory implementation
3
+ * for the outbound email delivery queue.
4
+ *
5
+ * The `IOutboundQueueStore` interface defines the contract for queue persistence,
6
+ * allowing different backends (in-memory for testing, database/filesystem for
7
+ * production) to be swapped without changing the queue logic.
8
+ *
9
+ * The `InMemoryOutboundQueueStore` provides a FIFO-ordered, Map-backed
10
+ * implementation suitable for unit/integration testing.
11
+ *
12
+ * @see Requirements 9.1, 9.3, 9.4
13
+ * @module outboundQueueStore
14
+ */
15
+ import type { IOutboundQueueItem } from './emailGatewayService';
16
+ /**
17
+ * Persistence interface for the outbound email delivery queue.
18
+ *
19
+ * Implementations must maintain FIFO ordering (Req 9.3) and support
20
+ * concurrent access patterns (Req 9.4). The store is responsible only
21
+ * for persistence — concurrency limiting and processing loops are
22
+ * handled by the `OutboundQueue` class (task 4.2).
23
+ *
24
+ * @see Requirements 9.1, 9.3, 9.4
25
+ */
26
+ export interface IOutboundQueueStore {
27
+ /**
28
+ * Add a message to the end of the queue.
29
+ *
30
+ * @param item - The outbound queue item to enqueue
31
+ * @throws If the store is unavailable (Req 9.5)
32
+ */
33
+ enqueue(item: IOutboundQueueItem): Promise<void>;
34
+ /**
35
+ * Remove and return the next item from the front of the queue
36
+ * that is in `Queued` status and ready for delivery.
37
+ *
38
+ * @returns The next queue item, or `undefined` if the queue is empty
39
+ * or no items are ready
40
+ */
41
+ dequeue(): Promise<IOutboundQueueItem | undefined>;
42
+ /**
43
+ * Return the next item from the front of the queue without removing it.
44
+ *
45
+ * @returns The next queue item, or `undefined` if the queue is empty
46
+ */
47
+ peek(): Promise<IOutboundQueueItem | undefined>;
48
+ /**
49
+ * Mark a message as successfully delivered and remove it from the queue.
50
+ *
51
+ * @param messageId - The RFC 5322 Message-ID of the completed message
52
+ */
53
+ markCompleted(messageId: string): Promise<void>;
54
+ /**
55
+ * Mark a message as permanently failed and remove it from the active queue.
56
+ *
57
+ * @param messageId - The RFC 5322 Message-ID of the failed message
58
+ * @param reason - Human-readable failure reason
59
+ */
60
+ markFailed(messageId: string, reason: string): Promise<void>;
61
+ /**
62
+ * Re-enqueue a message for retry with updated retry count and status.
63
+ *
64
+ * The item is placed at the end of the queue to maintain FIFO fairness
65
+ * among messages at the same priority level (Req 9.3).
66
+ *
67
+ * @param item - The updated queue item with incremented retryCount
68
+ */
69
+ requeue(item: IOutboundQueueItem): Promise<void>;
70
+ /**
71
+ * Return the current number of items in the queue.
72
+ *
73
+ * @returns The queue depth (number of pending items)
74
+ */
75
+ getQueueDepth(): Promise<number>;
76
+ /**
77
+ * Retrieve a queue item by its Message-ID.
78
+ *
79
+ * @param messageId - The RFC 5322 Message-ID to look up
80
+ * @returns The queue item, or `undefined` if not found
81
+ */
82
+ getByMessageId(messageId: string): Promise<IOutboundQueueItem | undefined>;
83
+ }
84
+ /**
85
+ * In-memory implementation of `IOutboundQueueStore` for testing.
86
+ *
87
+ * Uses a `Map` keyed by messageId for O(1) lookups and an insertion-ordered
88
+ * array (`queue`) to maintain strict FIFO ordering (Req 9.3).
89
+ *
90
+ * This implementation is NOT suitable for production — it does not survive
91
+ * process restarts (Req 9.1 requires durable storage). Use a database-backed
92
+ * or filesystem-backed implementation for production deployments.
93
+ *
94
+ * @see Requirements 9.1, 9.3, 9.4
95
+ */
96
+ export declare class InMemoryOutboundQueueStore implements IOutboundQueueStore {
97
+ /** Ordered list of message IDs representing FIFO queue order. */
98
+ private readonly queue;
99
+ /** Map from messageId → queue item for O(1) lookups. */
100
+ private readonly items;
101
+ enqueue(item: IOutboundQueueItem): Promise<void>;
102
+ dequeue(): Promise<IOutboundQueueItem | undefined>;
103
+ peek(): Promise<IOutboundQueueItem | undefined>;
104
+ markCompleted(messageId: string): Promise<void>;
105
+ markFailed(messageId: string, _reason: string): Promise<void>;
106
+ requeue(item: IOutboundQueueItem): Promise<void>;
107
+ getQueueDepth(): Promise<number>;
108
+ getByMessageId(messageId: string): Promise<IOutboundQueueItem | undefined>;
109
+ }
110
+ //# sourceMappingURL=outboundQueueStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboundQueueStore.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/outboundQueueStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IAEnD;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IAEhD;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;;;;;;OAOG;IACH,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC;;;;;OAKG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;CAC5E;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,YAAW,mBAAmB;IACpE,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IAEtC,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8C;IAE9D,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,OAAO,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAoClD,IAAI,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAW/C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/C,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhD,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAWhC,cAAc,CAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;CAI3C"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * Outbound Queue Store — persistence interface and in-memory implementation
4
+ * for the outbound email delivery queue.
5
+ *
6
+ * The `IOutboundQueueStore` interface defines the contract for queue persistence,
7
+ * allowing different backends (in-memory for testing, database/filesystem for
8
+ * production) to be swapped without changing the queue logic.
9
+ *
10
+ * The `InMemoryOutboundQueueStore` provides a FIFO-ordered, Map-backed
11
+ * implementation suitable for unit/integration testing.
12
+ *
13
+ * @see Requirements 9.1, 9.3, 9.4
14
+ * @module outboundQueueStore
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.InMemoryOutboundQueueStore = void 0;
18
+ const brightchain_lib_1 = require("@brightchain/brightchain-lib");
19
+ /**
20
+ * In-memory implementation of `IOutboundQueueStore` for testing.
21
+ *
22
+ * Uses a `Map` keyed by messageId for O(1) lookups and an insertion-ordered
23
+ * array (`queue`) to maintain strict FIFO ordering (Req 9.3).
24
+ *
25
+ * This implementation is NOT suitable for production — it does not survive
26
+ * process restarts (Req 9.1 requires durable storage). Use a database-backed
27
+ * or filesystem-backed implementation for production deployments.
28
+ *
29
+ * @see Requirements 9.1, 9.3, 9.4
30
+ */
31
+ class InMemoryOutboundQueueStore {
32
+ /** Ordered list of message IDs representing FIFO queue order. */
33
+ queue = [];
34
+ /** Map from messageId → queue item for O(1) lookups. */
35
+ items = new Map();
36
+ async enqueue(item) {
37
+ // If an item with the same messageId already exists, replace it
38
+ // (this can happen on requeue after status update).
39
+ if (!this.items.has(item.messageId)) {
40
+ this.queue.push(item.messageId);
41
+ }
42
+ this.items.set(item.messageId, { ...item });
43
+ }
44
+ async dequeue() {
45
+ // Walk the queue front-to-back to find the first item in Queued status
46
+ // that is ready for processing (nextAttemptAt <= now or not set).
47
+ const now = Date.now();
48
+ for (let i = 0; i < this.queue.length; i++) {
49
+ const messageId = this.queue[i];
50
+ const item = this.items.get(messageId);
51
+ if (!item) {
52
+ // Stale entry — item was removed (markCompleted/markFailed).
53
+ this.queue.splice(i, 1);
54
+ i--;
55
+ continue;
56
+ }
57
+ if (item.status !== brightchain_lib_1.OutboundDeliveryStatus.Queued) {
58
+ // Item exists but is not in Queued status — remove stale entry.
59
+ this.queue.splice(i, 1);
60
+ i--;
61
+ continue;
62
+ }
63
+ // Respect nextAttemptAt: skip items that are not yet ready.
64
+ if (item.nextAttemptAt && item.nextAttemptAt.getTime() > now) {
65
+ continue;
66
+ }
67
+ // Item is ready — remove from queue and return.
68
+ this.queue.splice(i, 1);
69
+ this.items.delete(messageId);
70
+ return { ...item };
71
+ }
72
+ return undefined;
73
+ }
74
+ async peek() {
75
+ // Walk the queue front-to-back to find the first item in Queued status.
76
+ for (const messageId of this.queue) {
77
+ const item = this.items.get(messageId);
78
+ if (item && item.status === brightchain_lib_1.OutboundDeliveryStatus.Queued) {
79
+ return { ...item };
80
+ }
81
+ }
82
+ return undefined;
83
+ }
84
+ async markCompleted(messageId) {
85
+ const item = this.items.get(messageId);
86
+ if (item) {
87
+ item.status = brightchain_lib_1.OutboundDeliveryStatus.Delivered;
88
+ this.items.delete(messageId);
89
+ const idx = this.queue.indexOf(messageId);
90
+ if (idx !== -1) {
91
+ this.queue.splice(idx, 1);
92
+ }
93
+ }
94
+ }
95
+ async markFailed(messageId, _reason) {
96
+ const item = this.items.get(messageId);
97
+ if (item) {
98
+ item.status = brightchain_lib_1.OutboundDeliveryStatus.PermanentFailure;
99
+ this.items.delete(messageId);
100
+ const idx = this.queue.indexOf(messageId);
101
+ if (idx !== -1) {
102
+ this.queue.splice(idx, 1);
103
+ }
104
+ }
105
+ }
106
+ async requeue(item) {
107
+ // Remove old position if present, then append to end for FIFO fairness.
108
+ const existingIdx = this.queue.indexOf(item.messageId);
109
+ if (existingIdx !== -1) {
110
+ this.queue.splice(existingIdx, 1);
111
+ }
112
+ this.queue.push(item.messageId);
113
+ this.items.set(item.messageId, { ...item });
114
+ }
115
+ async getQueueDepth() {
116
+ // Count only items that are still in the items map (not stale references).
117
+ let count = 0;
118
+ for (const messageId of this.queue) {
119
+ if (this.items.has(messageId)) {
120
+ count++;
121
+ }
122
+ }
123
+ return count;
124
+ }
125
+ async getByMessageId(messageId) {
126
+ const item = this.items.get(messageId);
127
+ return item ? { ...item } : undefined;
128
+ }
129
+ }
130
+ exports.InMemoryOutboundQueueStore = InMemoryOutboundQueueStore;
131
+ //# sourceMappingURL=outboundQueueStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboundQueueStore.js","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/outboundQueueStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * RecipientLookupService — TCP socketmap server for Postfix recipient validation.
3
+ *
4
+ * Implements the Postfix `socketmap` lookup protocol over TCP so that Postfix
5
+ * can validate whether a recipient address corresponds to a registered
6
+ * BrightChain user *before* accepting the message (preventing backscatter).
7
+ *
8
+ * Protocol (simplified):
9
+ * Client sends: `<name> <key>\n` (e.g. `virtual alice@brightchain.org\n`)
10
+ * Server responds: `OK <value>\n` | `NOTFOUND \n` | `TEMP <reason>\n`
11
+ *
12
+ * The service:
13
+ * - Listens on a configurable TCP port (default 2526) on localhost
14
+ * - Queries a user-registry dependency for the local part at the canonical domain
15
+ * - Caches positive results in an LRU cache with configurable TTL (default 300 s)
16
+ * - Responds within 5 seconds (timeout handling)
17
+ *
18
+ * @see Requirements 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 4.1, 4.2, 4.3
19
+ * @module recipientLookupService
20
+ */
21
+ import type { IRecipientLookupService } from '@brightchain/brightchain-lib';
22
+ import type { IEmailGatewayConfig } from './emailGatewayConfig';
23
+ import type { IDomainAwareComponent } from './emailGatewayService';
24
+ /**
25
+ * Minimal interface for querying the BrightChain user registry.
26
+ *
27
+ * Concrete implementations may delegate to `IMemberStore.queryIndex` or
28
+ * any other backing store. The recipient lookup service only needs to know
29
+ * whether a given email address belongs to a registered user.
30
+ */
31
+ export interface IUserRegistry {
32
+ /**
33
+ * Check whether `emailAddress` corresponds to a registered BrightChain user.
34
+ *
35
+ * @returns `true` if the user exists, `false` otherwise.
36
+ * @throws When the registry is unreachable (triggers TEMP response).
37
+ */
38
+ hasUser(emailAddress: string): Promise<boolean>;
39
+ }
40
+ /**
41
+ * Simple LRU cache for positive recipient lookup results.
42
+ *
43
+ * Only positive (`OK`) results are cached — negative and temporary results
44
+ * are always re-queried so that newly registered users are found promptly.
45
+ *
46
+ * @see Requirement 13.6
47
+ */
48
+ export declare class RecipientLookupCache {
49
+ private readonly maxSize;
50
+ private readonly ttlMs;
51
+ private readonly cache;
52
+ constructor(maxSize: number, ttlMs: number);
53
+ /**
54
+ * Retrieve a cached positive result for `key`.
55
+ *
56
+ * @returns `true` if the key is cached and not expired, `false` otherwise.
57
+ */
58
+ get(key: string): boolean;
59
+ /**
60
+ * Store a positive lookup result for `key`.
61
+ */
62
+ set(key: string): void;
63
+ /** Number of entries currently in the cache. */
64
+ get size(): number;
65
+ /** Remove all entries. */
66
+ clear(): void;
67
+ }
68
+ /**
69
+ * TCP socketmap server that Postfix queries to validate recipient addresses
70
+ * against the BrightChain user registry.
71
+ *
72
+ * Implements `IRecipientLookupService` from brightchain-lib for the `lookup`
73
+ * contract, and adds TCP server lifecycle (`start` / `stop`).
74
+ *
75
+ * @see Requirements 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7
76
+ */
77
+ export declare class RecipientLookupService implements IRecipientLookupService, IDomainAwareComponent {
78
+ private readonly config;
79
+ private readonly userRegistry;
80
+ private server;
81
+ private readonly cache;
82
+ private readonly port;
83
+ private canonicalDomain;
84
+ constructor(config: IEmailGatewayConfig, userRegistry: IUserRegistry);
85
+ /**
86
+ * Update the canonical domain used for recipient validation.
87
+ *
88
+ * Clears the lookup cache since cached entries may belong to the old domain.
89
+ *
90
+ * @param newDomain - The new canonical domain
91
+ *
92
+ * @see Requirement 8.5 — hot-reload canonical domain without restart
93
+ */
94
+ updateCanonicalDomain(newDomain: string): void;
95
+ /**
96
+ * Look up whether `emailAddress` corresponds to a registered BrightChain
97
+ * user at the canonical domain.
98
+ *
99
+ * 1. Check the LRU cache for a positive hit.
100
+ * 2. Query the user registry (with a 5-second timeout).
101
+ * 3. Cache positive results.
102
+ *
103
+ * @returns `'OK'` | `'NOTFOUND'` | `'TEMP'`
104
+ *
105
+ * @see Requirements 13.2, 13.3, 13.4, 13.5, 13.6
106
+ */
107
+ lookup(emailAddress: string): Promise<'OK' | 'NOTFOUND' | 'TEMP'>;
108
+ /**
109
+ * Start the TCP socketmap server on the configured port (localhost only).
110
+ *
111
+ * @see Requirement 13.1
112
+ */
113
+ start(): Promise<void>;
114
+ /**
115
+ * Stop the TCP server and clear the cache.
116
+ */
117
+ stop(): Promise<void>;
118
+ /** Whether the TCP server is currently listening. */
119
+ isRunning(): boolean;
120
+ /** Expose cache for testing purposes. */
121
+ getCache(): RecipientLookupCache;
122
+ /**
123
+ * Handle a single TCP connection from Postfix.
124
+ *
125
+ * Postfix socketmap protocol:
126
+ * Request: `<mapname> <key>\n`
127
+ * Response: `OK <value>\n` | `NOTFOUND \n` | `TEMP <reason>\n`
128
+ *
129
+ * The connection may carry multiple newline-delimited requests.
130
+ */
131
+ private handleConnection;
132
+ /**
133
+ * Parse a socketmap request line and return the response string.
134
+ *
135
+ * @param line - A single request line, e.g. `virtual alice@brightchain.org`
136
+ * @returns The response string, e.g. `OK alice@brightchain.org`
137
+ */
138
+ private handleRequest;
139
+ /**
140
+ * Race a promise against a timeout.
141
+ *
142
+ * @throws If the timeout fires first.
143
+ */
144
+ private withTimeout;
145
+ }
146
+ //# sourceMappingURL=recipientLookupService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipientLookupService.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/recipientLookupService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAInE;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjD;AAUD;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAI7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;gBAGpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM;IAGhC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAezB;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAetB,gDAAgD;IAChD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,0BAA0B;IAC1B,KAAK,IAAI,IAAI;CAGd;AAaD;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB,EAAE,qBAAqB;IAOzF,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAP/B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;gBAGb,MAAM,EAAE,mBAAmB,EAC3B,YAAY,EAAE,aAAa;IAU9C;;;;;;;;OAQG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAO9C;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;IAsCvE;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBtB;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcrB,qDAAqD;IACrD,SAAS,IAAI,OAAO;IAIpB,yCAAyC;IACzC,QAAQ,IAAI,oBAAoB;IAMhC;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAqCxB;;;;;OAKG;YACW,aAAa;IA0B3B;;;;OAIG;IACH,OAAO,CAAC,WAAW;CAiBpB"}