@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.
- package/package.json +4 -3
- package/src/lib/appConstants.d.ts +1 -1
- package/src/lib/appConstants.js +1 -1
- package/src/lib/application.d.ts +3 -14
- package/src/lib/application.d.ts.map +1 -1
- package/src/lib/application.js +91 -34
- package/src/lib/application.js.map +1 -1
- package/src/lib/constants.d.ts.map +1 -1
- package/src/lib/constants.js +1 -1
- package/src/lib/constants.js.map +1 -1
- package/src/lib/databaseInit.d.ts +7 -11
- package/src/lib/databaseInit.d.ts.map +1 -1
- package/src/lib/databaseInit.js +41 -107
- package/src/lib/databaseInit.js.map +1 -1
- package/src/lib/datastore/block-document-store-factory.d.ts +3 -0
- package/src/lib/datastore/block-document-store-factory.d.ts.map +1 -1
- package/src/lib/datastore/block-document-store-factory.js +15 -18
- package/src/lib/datastore/block-document-store-factory.js.map +1 -1
- package/src/lib/datastore/block-document-store.d.ts +2 -191
- package/src/lib/datastore/block-document-store.d.ts.map +1 -1
- package/src/lib/datastore/block-document-store.js +4 -628
- package/src/lib/datastore/block-document-store.js.map +1 -1
- package/src/lib/datastore/document-store.d.ts +1 -62
- package/src/lib/datastore/document-store.d.ts.map +1 -1
- package/src/lib/datastore/memory-document-store.d.ts +1 -8
- package/src/lib/datastore/memory-document-store.d.ts.map +1 -1
- package/src/lib/datastore/memory-document-store.js +3 -214
- package/src/lib/datastore/memory-document-store.js.map +1 -1
- package/src/lib/environment.d.ts +4 -47
- package/src/lib/environment.d.ts.map +1 -1
- package/src/lib/environment.js +2 -136
- package/src/lib/environment.js.map +1 -1
- package/src/lib/interfaces/environment.d.ts +3 -25
- package/src/lib/interfaces/environment.d.ts.map +1 -1
- package/src/lib/interfaces/responses/emailGatewayResponses.d.ts +30 -0
- package/src/lib/interfaces/responses/emailGatewayResponses.d.ts.map +1 -0
- package/src/lib/interfaces/responses/emailGatewayResponses.js +3 -0
- package/src/lib/interfaces/responses/emailGatewayResponses.js.map +1 -0
- package/src/lib/interfaces/responses/index.d.ts +1 -0
- package/src/lib/interfaces/responses/index.d.ts.map +1 -1
- package/src/lib/middleware/index.d.ts +1 -1
- package/src/lib/middleware/index.d.ts.map +1 -1
- package/src/lib/middleware/index.js +3 -2
- package/src/lib/middleware/index.js.map +1 -1
- package/src/lib/middleware/validateBody.d.ts +1 -12
- package/src/lib/middleware/validateBody.d.ts.map +1 -1
- package/src/lib/middleware/validateBody.js +4 -32
- package/src/lib/middleware/validateBody.js.map +1 -1
- package/src/lib/middlewares.d.ts.map +1 -1
- package/src/lib/middlewares.js +7 -1
- package/src/lib/middlewares.js.map +1 -1
- package/src/lib/plugins/brightchain-database-plugin.d.ts +27 -79
- package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
- package/src/lib/plugins/brightchain-database-plugin.js +32 -103
- package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
- package/src/lib/routers/app.d.ts.map +1 -1
- package/src/lib/routers/app.js +1 -0
- package/src/lib/routers/app.js.map +1 -1
- package/src/lib/services/emailGateway/antiSpamFilter.d.ts +229 -0
- package/src/lib/services/emailGateway/antiSpamFilter.d.ts.map +1 -0
- package/src/lib/services/emailGateway/antiSpamFilter.js +325 -0
- package/src/lib/services/emailGateway/antiSpamFilter.js.map +1 -0
- package/src/lib/services/emailGateway/bounceProcessor.d.ts +182 -0
- package/src/lib/services/emailGateway/bounceProcessor.d.ts.map +1 -0
- package/src/lib/services/emailGateway/bounceProcessor.js +391 -0
- package/src/lib/services/emailGateway/bounceProcessor.js.map +1 -0
- package/src/lib/services/emailGateway/emailAuthVerifier.d.ts +99 -0
- package/src/lib/services/emailGateway/emailAuthVerifier.d.ts.map +1 -0
- package/src/lib/services/emailGateway/emailAuthVerifier.js +202 -0
- package/src/lib/services/emailGateway/emailAuthVerifier.js.map +1 -0
- package/src/lib/services/emailGateway/emailGatewayConfig.d.ts +74 -0
- package/src/lib/services/emailGateway/emailGatewayConfig.d.ts.map +1 -0
- package/src/lib/services/emailGateway/emailGatewayConfig.js +107 -0
- package/src/lib/services/emailGateway/emailGatewayConfig.js.map +1 -0
- package/src/lib/services/emailGateway/emailGatewayService.d.ts +209 -0
- package/src/lib/services/emailGateway/emailGatewayService.d.ts.map +1 -0
- package/src/lib/services/emailGateway/emailGatewayService.js +254 -0
- package/src/lib/services/emailGateway/emailGatewayService.js.map +1 -0
- package/src/lib/services/emailGateway/gatewayObservability.d.ts +123 -0
- package/src/lib/services/emailGateway/gatewayObservability.d.ts.map +1 -0
- package/src/lib/services/emailGateway/gatewayObservability.js +186 -0
- package/src/lib/services/emailGateway/gatewayObservability.js.map +1 -0
- package/src/lib/services/emailGateway/inboundProcessor.d.ts +113 -0
- package/src/lib/services/emailGateway/inboundProcessor.d.ts.map +1 -0
- package/src/lib/services/emailGateway/inboundProcessor.js +298 -0
- package/src/lib/services/emailGateway/inboundProcessor.js.map +1 -0
- package/src/lib/services/emailGateway/index.d.ts +23 -0
- package/src/lib/services/emailGateway/index.d.ts.map +1 -0
- package/src/lib/services/emailGateway/index.js +26 -0
- package/src/lib/services/emailGateway/index.js.map +1 -0
- package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts +122 -0
- package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts.map +1 -0
- package/src/lib/services/emailGateway/outboundDeliveryWorker.js +110 -0
- package/src/lib/services/emailGateway/outboundDeliveryWorker.js.map +1 -0
- package/src/lib/services/emailGateway/outboundQueue.d.ts +135 -0
- package/src/lib/services/emailGateway/outboundQueue.d.ts.map +1 -0
- package/src/lib/services/emailGateway/outboundQueue.js +227 -0
- package/src/lib/services/emailGateway/outboundQueue.js.map +1 -0
- package/src/lib/services/emailGateway/outboundQueueStore.d.ts +110 -0
- package/src/lib/services/emailGateway/outboundQueueStore.d.ts.map +1 -0
- package/src/lib/services/emailGateway/outboundQueueStore.js +131 -0
- package/src/lib/services/emailGateway/outboundQueueStore.js.map +1 -0
- package/src/lib/services/emailGateway/recipientLookupService.d.ts +146 -0
- package/src/lib/services/emailGateway/recipientLookupService.d.ts.map +1 -0
- package/src/lib/services/emailGateway/recipientLookupService.js +307 -0
- package/src/lib/services/emailGateway/recipientLookupService.js.map +1 -0
- package/src/lib/services/emailGateway/retryBackoff.d.ts +79 -0
- package/src/lib/services/emailGateway/retryBackoff.d.ts.map +1 -0
- package/src/lib/services/emailGateway/retryBackoff.js +77 -0
- package/src/lib/services/emailGateway/retryBackoff.js.map +1 -0
- package/src/lib/services/index.d.ts +1 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +1 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/quorumDatabaseAdapter.d.ts +7 -1
- package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -1
- package/src/lib/services/quorumDatabaseAdapter.js +83 -0
- package/src/lib/services/quorumDatabaseAdapter.js.map +1 -1
- package/src/lib/services/sessionAdapter.d.ts +2 -61
- package/src/lib/services/sessionAdapter.d.ts.map +1 -1
- package/src/lib/services/sessionAdapter.js +2 -102
- package/src/lib/services/sessionAdapter.js.map +1 -1
- package/src/lib/shared-types.d.ts +7 -15
- package/src/lib/shared-types.d.ts.map +1 -1
- package/src/lib/types/backend-id.d.ts +1 -2
- package/src/lib/types/backend-id.d.ts.map +1 -1
- package/src/lib/validation/userValidation.d.ts +2 -43
- package/src/lib/validation/userValidation.d.ts.map +1 -1
- package/src/lib/validation/userValidation.js +6 -144
- 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"}
|