@brightchain/brightchain-api-lib 0.25.0 → 0.26.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 (116) hide show
  1. package/package.json +4 -3
  2. package/src/lib/application.d.ts +3 -14
  3. package/src/lib/application.d.ts.map +1 -1
  4. package/src/lib/application.js +89 -34
  5. package/src/lib/application.js.map +1 -1
  6. package/src/lib/databaseInit.d.ts +7 -11
  7. package/src/lib/databaseInit.d.ts.map +1 -1
  8. package/src/lib/databaseInit.js +41 -107
  9. package/src/lib/databaseInit.js.map +1 -1
  10. package/src/lib/datastore/block-document-store-factory.d.ts +3 -0
  11. package/src/lib/datastore/block-document-store-factory.d.ts.map +1 -1
  12. package/src/lib/datastore/block-document-store-factory.js +15 -18
  13. package/src/lib/datastore/block-document-store-factory.js.map +1 -1
  14. package/src/lib/datastore/block-document-store.d.ts +2 -191
  15. package/src/lib/datastore/block-document-store.d.ts.map +1 -1
  16. package/src/lib/datastore/block-document-store.js +4 -628
  17. package/src/lib/datastore/block-document-store.js.map +1 -1
  18. package/src/lib/datastore/document-store.d.ts +1 -62
  19. package/src/lib/datastore/document-store.d.ts.map +1 -1
  20. package/src/lib/datastore/memory-document-store.d.ts +1 -8
  21. package/src/lib/datastore/memory-document-store.d.ts.map +1 -1
  22. package/src/lib/datastore/memory-document-store.js +3 -214
  23. package/src/lib/datastore/memory-document-store.js.map +1 -1
  24. package/src/lib/environment.d.ts +4 -47
  25. package/src/lib/environment.d.ts.map +1 -1
  26. package/src/lib/environment.js +2 -136
  27. package/src/lib/environment.js.map +1 -1
  28. package/src/lib/interfaces/environment.d.ts +3 -25
  29. package/src/lib/interfaces/environment.d.ts.map +1 -1
  30. package/src/lib/middleware/index.d.ts +1 -1
  31. package/src/lib/middleware/index.d.ts.map +1 -1
  32. package/src/lib/middleware/index.js +3 -2
  33. package/src/lib/middleware/index.js.map +1 -1
  34. package/src/lib/middleware/validateBody.d.ts +1 -12
  35. package/src/lib/middleware/validateBody.d.ts.map +1 -1
  36. package/src/lib/middleware/validateBody.js +4 -32
  37. package/src/lib/middleware/validateBody.js.map +1 -1
  38. package/src/lib/middlewares.d.ts.map +1 -1
  39. package/src/lib/middlewares.js +7 -1
  40. package/src/lib/middlewares.js.map +1 -1
  41. package/src/lib/plugins/brightchain-database-plugin.d.ts +27 -79
  42. package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
  43. package/src/lib/plugins/brightchain-database-plugin.js +27 -97
  44. package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
  45. package/src/lib/services/emailGateway/antiSpamFilter.d.ts +229 -0
  46. package/src/lib/services/emailGateway/antiSpamFilter.d.ts.map +1 -0
  47. package/src/lib/services/emailGateway/antiSpamFilter.js +325 -0
  48. package/src/lib/services/emailGateway/antiSpamFilter.js.map +1 -0
  49. package/src/lib/services/emailGateway/bounceProcessor.d.ts +171 -0
  50. package/src/lib/services/emailGateway/bounceProcessor.d.ts.map +1 -0
  51. package/src/lib/services/emailGateway/bounceProcessor.js +378 -0
  52. package/src/lib/services/emailGateway/bounceProcessor.js.map +1 -0
  53. package/src/lib/services/emailGateway/emailAuthVerifier.d.ts +99 -0
  54. package/src/lib/services/emailGateway/emailAuthVerifier.d.ts.map +1 -0
  55. package/src/lib/services/emailGateway/emailAuthVerifier.js +202 -0
  56. package/src/lib/services/emailGateway/emailAuthVerifier.js.map +1 -0
  57. package/src/lib/services/emailGateway/emailGatewayConfig.d.ts +73 -0
  58. package/src/lib/services/emailGateway/emailGatewayConfig.d.ts.map +1 -0
  59. package/src/lib/services/emailGateway/emailGatewayConfig.js +107 -0
  60. package/src/lib/services/emailGateway/emailGatewayConfig.js.map +1 -0
  61. package/src/lib/services/emailGateway/emailGatewayService.d.ts +152 -0
  62. package/src/lib/services/emailGateway/emailGatewayService.d.ts.map +1 -0
  63. package/src/lib/services/emailGateway/emailGatewayService.js +201 -0
  64. package/src/lib/services/emailGateway/emailGatewayService.js.map +1 -0
  65. package/src/lib/services/emailGateway/gatewayObservability.d.ts +123 -0
  66. package/src/lib/services/emailGateway/gatewayObservability.d.ts.map +1 -0
  67. package/src/lib/services/emailGateway/gatewayObservability.js +186 -0
  68. package/src/lib/services/emailGateway/gatewayObservability.js.map +1 -0
  69. package/src/lib/services/emailGateway/inboundProcessor.d.ts +113 -0
  70. package/src/lib/services/emailGateway/inboundProcessor.d.ts.map +1 -0
  71. package/src/lib/services/emailGateway/inboundProcessor.js +298 -0
  72. package/src/lib/services/emailGateway/inboundProcessor.js.map +1 -0
  73. package/src/lib/services/emailGateway/index.d.ts +23 -0
  74. package/src/lib/services/emailGateway/index.d.ts.map +1 -0
  75. package/src/lib/services/emailGateway/index.js +26 -0
  76. package/src/lib/services/emailGateway/index.js.map +1 -0
  77. package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts +111 -0
  78. package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts.map +1 -0
  79. package/src/lib/services/emailGateway/outboundDeliveryWorker.js +97 -0
  80. package/src/lib/services/emailGateway/outboundDeliveryWorker.js.map +1 -0
  81. package/src/lib/services/emailGateway/outboundQueue.d.ts +135 -0
  82. package/src/lib/services/emailGateway/outboundQueue.d.ts.map +1 -0
  83. package/src/lib/services/emailGateway/outboundQueue.js +227 -0
  84. package/src/lib/services/emailGateway/outboundQueue.js.map +1 -0
  85. package/src/lib/services/emailGateway/outboundQueueStore.d.ts +110 -0
  86. package/src/lib/services/emailGateway/outboundQueueStore.d.ts.map +1 -0
  87. package/src/lib/services/emailGateway/outboundQueueStore.js +131 -0
  88. package/src/lib/services/emailGateway/outboundQueueStore.js.map +1 -0
  89. package/src/lib/services/emailGateway/recipientLookupService.d.ts +135 -0
  90. package/src/lib/services/emailGateway/recipientLookupService.d.ts.map +1 -0
  91. package/src/lib/services/emailGateway/recipientLookupService.js +294 -0
  92. package/src/lib/services/emailGateway/recipientLookupService.js.map +1 -0
  93. package/src/lib/services/emailGateway/retryBackoff.d.ts +79 -0
  94. package/src/lib/services/emailGateway/retryBackoff.d.ts.map +1 -0
  95. package/src/lib/services/emailGateway/retryBackoff.js +77 -0
  96. package/src/lib/services/emailGateway/retryBackoff.js.map +1 -0
  97. package/src/lib/services/index.d.ts +1 -0
  98. package/src/lib/services/index.d.ts.map +1 -1
  99. package/src/lib/services/index.js +1 -0
  100. package/src/lib/services/index.js.map +1 -1
  101. package/src/lib/services/quorumDatabaseAdapter.d.ts +7 -1
  102. package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -1
  103. package/src/lib/services/quorumDatabaseAdapter.js +83 -0
  104. package/src/lib/services/quorumDatabaseAdapter.js.map +1 -1
  105. package/src/lib/services/sessionAdapter.d.ts +2 -61
  106. package/src/lib/services/sessionAdapter.d.ts.map +1 -1
  107. package/src/lib/services/sessionAdapter.js +2 -102
  108. package/src/lib/services/sessionAdapter.js.map +1 -1
  109. package/src/lib/shared-types.d.ts +7 -15
  110. package/src/lib/shared-types.d.ts.map +1 -1
  111. package/src/lib/types/backend-id.d.ts +1 -2
  112. package/src/lib/types/backend-id.d.ts.map +1 -1
  113. package/src/lib/validation/userValidation.d.ts +2 -43
  114. package/src/lib/validation/userValidation.d.ts.map +1 -1
  115. package/src/lib/validation/userValidation.js +6 -144
  116. package/src/lib/validation/userValidation.js.map +1 -1
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ /**
3
+ * EmailGatewayService — orchestrator that bridges BrightChain's internal
4
+ * gossip-based messaging with external SMTP email delivery via Postfix.
5
+ *
6
+ * Responsibilities:
7
+ * - Listen for gossip announcements containing outbound email
8
+ * - Extract message blocks from the Block Store
9
+ * - Detect external recipients by comparing domain against canonicalDomain
10
+ * - Enqueue outbound messages for SMTP delivery
11
+ *
12
+ * @see Requirements 1.1, 1.2, 1.4
13
+ * @module emailGatewayService
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.EmailGatewayService = void 0;
17
+ const brightchain_lib_1 = require("@brightchain/brightchain-lib");
18
+ // ─── EmailGatewayService ────────────────────────────────────────────────────
19
+ /**
20
+ * Orchestrator service for the Email Gateway.
21
+ *
22
+ * Listens for gossip announcements that carry outbound email, extracts the
23
+ * message content from the Block Store, identifies external recipients by
24
+ * comparing their domain against the configured `canonicalDomain`, and
25
+ * enqueues qualifying messages in the OutboundQueue for SMTP delivery.
26
+ *
27
+ * Lifecycle:
28
+ * - `start()` registers the gossip announcement listener
29
+ * - `stop()` removes the listener and performs cleanup
30
+ *
31
+ * @see Requirements 1.1, 1.2, 1.4
32
+ */
33
+ class EmailGatewayService {
34
+ config;
35
+ gossipService;
36
+ blockStore;
37
+ emailMessageService;
38
+ outboundQueue;
39
+ /** Bound reference kept so we can unsubscribe on stop(). */
40
+ boundAnnouncementHandler;
41
+ /** Whether the service is currently running. */
42
+ running = false;
43
+ /**
44
+ * @param config - Gateway configuration (canonical domain, limits, etc.)
45
+ * @param gossipService - Gossip protocol service for subscribing to announcements
46
+ * @param blockStore - Block store for retrieving message content blocks
47
+ * @param emailMessageService - Email message service for retrieving email metadata
48
+ * @param outboundQueue - Queue for outbound SMTP delivery (optional; set later via `setOutboundQueue`)
49
+ */
50
+ constructor(config, gossipService, blockStore, emailMessageService, outboundQueue) {
51
+ this.config = config;
52
+ this.gossipService = gossipService;
53
+ this.blockStore = blockStore;
54
+ this.emailMessageService = emailMessageService;
55
+ this.outboundQueue = outboundQueue;
56
+ // Bind once so the same reference is used for on/off.
57
+ this.boundAnnouncementHandler = this.handleAnnouncement.bind(this);
58
+ }
59
+ // ─── Lifecycle ──────────────────────────────────────────────────────
60
+ /**
61
+ * Start the gateway service.
62
+ *
63
+ * Registers a gossip announcement listener that intercepts outbound
64
+ * email announcements and delegates them to the outbound queue.
65
+ */
66
+ start() {
67
+ if (this.running) {
68
+ return;
69
+ }
70
+ this.gossipService.onMessageDelivery(this.boundAnnouncementHandler);
71
+ this.running = true;
72
+ }
73
+ /**
74
+ * Stop the gateway service.
75
+ *
76
+ * Removes the gossip listener and marks the service as stopped.
77
+ */
78
+ stop() {
79
+ if (!this.running) {
80
+ return;
81
+ }
82
+ this.gossipService.offMessageDelivery(this.boundAnnouncementHandler);
83
+ this.running = false;
84
+ }
85
+ /**
86
+ * Whether the service is currently running.
87
+ */
88
+ isRunning() {
89
+ return this.running;
90
+ }
91
+ /**
92
+ * Wire the outbound queue after construction.
93
+ *
94
+ * Useful when the queue is created after the gateway service (e.g.
95
+ * during staged initialisation).
96
+ */
97
+ setOutboundQueue(queue) {
98
+ this.outboundQueue = queue;
99
+ }
100
+ // ─── Domain Check ──────────────────────────────────────────────────
101
+ /**
102
+ * Determine whether an email address is external (not on the canonical domain).
103
+ *
104
+ * Extracts the domain portion of the address and compares it
105
+ * case-insensitively against `config.canonicalDomain`.
106
+ *
107
+ * @param emailAddress - A full email address (e.g. `alice@example.com`)
108
+ * @returns `true` when the address belongs to an external domain
109
+ *
110
+ * @see Requirement 1.1 — detect recipients whose domain ≠ canonical domain
111
+ */
112
+ isExternalRecipient(emailAddress) {
113
+ const atIndex = emailAddress.lastIndexOf('@');
114
+ if (atIndex === -1) {
115
+ // Malformed address — treat as external to be safe.
116
+ return true;
117
+ }
118
+ const domain = emailAddress.slice(atIndex + 1).toLowerCase();
119
+ return domain !== this.config.canonicalDomain.toLowerCase();
120
+ }
121
+ /**
122
+ * Partition a list of email addresses into internal and external groups.
123
+ *
124
+ * @param addresses - Array of email addresses
125
+ * @returns Object with `internal` and `external` arrays
126
+ *
127
+ * @see Requirement 1.4 — mixed internal/external recipient handling
128
+ */
129
+ partitionRecipients(addresses) {
130
+ const internal = [];
131
+ const external = [];
132
+ for (const addr of addresses) {
133
+ if (this.isExternalRecipient(addr)) {
134
+ external.push(addr);
135
+ }
136
+ else {
137
+ internal.push(addr);
138
+ }
139
+ }
140
+ return { internal, external };
141
+ }
142
+ // ─── Gossip Announcement Handler ───────────────────────────────────
143
+ /**
144
+ * Handle a gossip message-delivery announcement.
145
+ *
146
+ * When an announcement carries `messageDelivery` metadata the handler:
147
+ * 1. Retrieves the email metadata from the EmailMessageService
148
+ * 2. Identifies external recipients
149
+ * 3. Enqueues the message in the OutboundQueue for SMTP delivery
150
+ *
151
+ * Internal-only messages are ignored — they are already delivered via gossip.
152
+ *
153
+ * @param announcement - The gossip BlockAnnouncement with messageDelivery metadata
154
+ *
155
+ * @see Requirement 1.2 — extract message from Block Store and enqueue
156
+ * @see Requirement 1.4 — route external recipients to gateway
157
+ */
158
+ async handleAnnouncement(announcement) {
159
+ const delivery = announcement.messageDelivery;
160
+ if (!delivery) {
161
+ return;
162
+ }
163
+ // Retrieve the email metadata via the message ID.
164
+ const metadata = await this.emailMessageService.getEmail(delivery.messageId);
165
+ if (!metadata) {
166
+ // Message not found — nothing to route.
167
+ return;
168
+ }
169
+ // Collect all recipient addresses from the metadata.
170
+ const allRecipients = [
171
+ ...metadata.to.map((m) => m.address),
172
+ ...(metadata.cc ?? []).map((m) => m.address),
173
+ ...(metadata.bcc ?? []).map((m) => m.address),
174
+ ];
175
+ // Partition into internal / external.
176
+ const { external } = this.partitionRecipients(allRecipients);
177
+ if (external.length === 0) {
178
+ // Purely internal delivery — nothing for the gateway to do.
179
+ return;
180
+ }
181
+ if (!this.outboundQueue) {
182
+ // Queue not wired yet — cannot enqueue. This is a configuration issue.
183
+ // In production this would be logged/alerted; for now we silently skip.
184
+ return;
185
+ }
186
+ // Build the queue item and enqueue.
187
+ const queueItem = {
188
+ messageId: metadata.messageId,
189
+ from: metadata.from.address,
190
+ to: external,
191
+ subject: metadata.subject,
192
+ metadata,
193
+ enqueuedAt: new Date(),
194
+ status: brightchain_lib_1.OutboundDeliveryStatus.Queued,
195
+ retryCount: 0,
196
+ };
197
+ await this.outboundQueue.enqueue(queueItem);
198
+ }
199
+ }
200
+ exports.EmailGatewayService = EmailGatewayService;
201
+ //# sourceMappingURL=emailGatewayService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emailGatewayService.js","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/emailGatewayService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Gateway Observability
3
+ *
4
+ * Provides unified logging, metrics collection, and alerting for all
5
+ * Email Gateway components. Wraps the existing `IMessageLogger`,
6
+ * `IMessageMetricsCollector`, and `AlertMonitor` services to add
7
+ * gateway-specific observability.
8
+ *
9
+ * @see Requirements 10.1, 10.2, 10.3, 10.4, 10.5
10
+ * @module gatewayObservability
11
+ */
12
+ import type { IEmailAuthenticationResult } from '@brightchain/brightchain-lib';
13
+ import { type IMessageLogger, type IMessageMetricsCollector, AlertMonitor } from '@brightchain/brightchain-lib';
14
+ /**
15
+ * Gateway-specific metrics snapshot exposed by `GatewayObservability`.
16
+ *
17
+ * @see Requirement 10.3
18
+ */
19
+ export interface IGatewayMetricsSnapshot {
20
+ /** Current number of messages in the outbound queue */
21
+ outboundQueueDepth: number;
22
+ /** Total successful deliveries since last reset */
23
+ deliverySuccessCount: number;
24
+ /** Total failed deliveries since last reset */
25
+ deliveryFailureCount: number;
26
+ /** Delivery success rate (0–1) */
27
+ deliverySuccessRate: number;
28
+ /** Delivery failure rate (0–1) */
29
+ deliveryFailureRate: number;
30
+ /** Average delivery latency in milliseconds */
31
+ averageDeliveryLatencyMs: number;
32
+ /** Total spam rejections since last reset */
33
+ spamRejectionCount: number;
34
+ /** Spam rejection rate (0–1, relative to total inbound) */
35
+ spamRejectionRate: number;
36
+ /** Total inbound messages processed since last reset */
37
+ totalInboundProcessed: number;
38
+ }
39
+ /**
40
+ * Centralised observability for the Email Gateway.
41
+ *
42
+ * Integrates with the existing `IMessageLogger`, `IMessageMetricsCollector`,
43
+ * and `AlertMonitor` services so that all gateway events flow through the
44
+ * same infrastructure used by the rest of BrightChain.
45
+ *
46
+ * @see Requirements 10.1, 10.2, 10.3, 10.4, 10.5
47
+ */
48
+ export declare class GatewayObservability {
49
+ private readonly logger;
50
+ private readonly metrics;
51
+ private readonly alertMonitor;
52
+ private _outboundQueueDepth;
53
+ private _deliverySuccessCount;
54
+ private _deliveryFailureCount;
55
+ private _totalDeliveryLatencyMs;
56
+ private _spamRejectionCount;
57
+ private _totalInboundProcessed;
58
+ constructor(logger: IMessageLogger, metrics: IMessageMetricsCollector, alertMonitor: AlertMonitor);
59
+ /**
60
+ * Log an outbound delivery attempt.
61
+ *
62
+ * Delegates to `IMessageLogger.logMessageCreated` for consistent logging
63
+ * and records the attempt in the metrics collector.
64
+ *
65
+ * @see Requirement 10.1
66
+ */
67
+ logOutboundAttempt(recipient: string, statusCode: number, retryCount: number, timestamp: Date): void;
68
+ /**
69
+ * Log an inbound email processing event.
70
+ *
71
+ * @see Requirement 10.2
72
+ */
73
+ logInboundProcessing(sender: string, recipient: string, spamScore: number, authResults: IEmailAuthenticationResult, accepted: boolean): void;
74
+ /**
75
+ * Record the current outbound queue depth.
76
+ *
77
+ * @see Requirement 10.3
78
+ */
79
+ recordQueueDepth(depth: number): void;
80
+ /**
81
+ * Record a successful delivery and its latency.
82
+ *
83
+ * @see Requirement 10.3
84
+ */
85
+ recordDeliverySuccess(latencyMs?: number): void;
86
+ /**
87
+ * Record a delivery failure.
88
+ *
89
+ * @see Requirement 10.3
90
+ */
91
+ recordDeliveryFailure(): void;
92
+ /**
93
+ * Record delivery latency in milliseconds.
94
+ *
95
+ * @see Requirement 10.3
96
+ */
97
+ recordDeliveryLatency(ms: number): void;
98
+ /**
99
+ * Record a spam rejection.
100
+ *
101
+ * @see Requirement 10.3
102
+ */
103
+ recordSpamRejection(): void;
104
+ /**
105
+ * Emit an alert when delivery fails after all retries are exhausted.
106
+ *
107
+ * Delegates to the existing `AlertMonitor` for consistent alerting.
108
+ *
109
+ * @see Requirement 10.5
110
+ */
111
+ alertDeliveryExhausted(messageId: string, recipient: string, retryCount: number): void;
112
+ /**
113
+ * Return a point-in-time snapshot of all gateway-specific metrics.
114
+ *
115
+ * @see Requirement 10.3
116
+ */
117
+ getMetricsSnapshot(): IGatewayMetricsSnapshot;
118
+ /**
119
+ * Reset all gateway-specific counters.
120
+ */
121
+ reset(): void;
122
+ }
123
+ //# sourceMappingURL=gatewayObservability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gatewayObservability.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/gatewayObservability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC/E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,YAAY,EACb,MAAM,8BAA8B,CAAC;AAEtC;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kCAAkC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,wBAAwB,EAAE,MAAM,CAAC;IACjC,6CAA6C;IAC7C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IAU7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAV/B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,uBAAuB,CAAK;IACpC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,sBAAsB,CAAK;gBAGhB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,wBAAwB,EACjC,YAAY,EAAE,YAAY;IAK7C;;;;;;;OAOG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,IAAI,GACd,IAAI;IA2BP;;;;OAIG;IACH,oBAAoB,CAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,0BAA0B,EACvC,QAAQ,EAAE,OAAO,GAChB,IAAI;IAoBP;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKrC;;;;OAIG;IACH,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAU/C;;;;OAIG;IACH,qBAAqB,IAAI,IAAI;IAK7B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKvC;;;;OAIG;IACH,mBAAmB,IAAI,IAAI;IAQ3B;;;;;;OAMG;IACH,sBAAsB,CACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,IAAI;IAqBP;;;;OAIG;IACH,kBAAkB,IAAI,uBAAuB;IAwB7C;;OAEG;IACH,KAAK,IAAI,IAAI;CASd"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ /**
3
+ * Gateway Observability
4
+ *
5
+ * Provides unified logging, metrics collection, and alerting for all
6
+ * Email Gateway components. Wraps the existing `IMessageLogger`,
7
+ * `IMessageMetricsCollector`, and `AlertMonitor` services to add
8
+ * gateway-specific observability.
9
+ *
10
+ * @see Requirements 10.1, 10.2, 10.3, 10.4, 10.5
11
+ * @module gatewayObservability
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.GatewayObservability = void 0;
15
+ /**
16
+ * Centralised observability for the Email Gateway.
17
+ *
18
+ * Integrates with the existing `IMessageLogger`, `IMessageMetricsCollector`,
19
+ * and `AlertMonitor` services so that all gateway events flow through the
20
+ * same infrastructure used by the rest of BrightChain.
21
+ *
22
+ * @see Requirements 10.1, 10.2, 10.3, 10.4, 10.5
23
+ */
24
+ class GatewayObservability {
25
+ logger;
26
+ metrics;
27
+ alertMonitor;
28
+ // Gateway-specific counters (Req 10.3)
29
+ _outboundQueueDepth = 0;
30
+ _deliverySuccessCount = 0;
31
+ _deliveryFailureCount = 0;
32
+ _totalDeliveryLatencyMs = 0;
33
+ _spamRejectionCount = 0;
34
+ _totalInboundProcessed = 0;
35
+ constructor(logger, metrics, alertMonitor) {
36
+ this.logger = logger;
37
+ this.metrics = metrics;
38
+ this.alertMonitor = alertMonitor;
39
+ }
40
+ // ── Outbound delivery logging (Req 10.1) ──────────────────────────
41
+ /**
42
+ * Log an outbound delivery attempt.
43
+ *
44
+ * Delegates to `IMessageLogger.logMessageCreated` for consistent logging
45
+ * and records the attempt in the metrics collector.
46
+ *
47
+ * @see Requirement 10.1
48
+ */
49
+ logOutboundAttempt(recipient, statusCode, retryCount, timestamp) {
50
+ // Use the existing logger infrastructure (Req 10.4)
51
+ this.logger.logMessageCreated(`outbound:${recipient}:${timestamp.toISOString()}`, 'gateway-outbound', 1);
52
+ this.logger.logRoutingDecision(`outbound:${recipient}`, `smtp-status:${statusCode}:retry:${retryCount}`, 1);
53
+ // Track success/failure in metrics (Req 10.3)
54
+ if (statusCode >= 200 && statusCode < 300) {
55
+ this._deliverySuccessCount++;
56
+ this.metrics.recordMessageDelivered(0);
57
+ }
58
+ else {
59
+ this._deliveryFailureCount++;
60
+ this.metrics.recordMessageFailed();
61
+ }
62
+ this.metrics.recordMessageSent();
63
+ }
64
+ // ── Inbound processing logging (Req 10.2) ─────────────────────────
65
+ /**
66
+ * Log an inbound email processing event.
67
+ *
68
+ * @see Requirement 10.2
69
+ */
70
+ logInboundProcessing(sender, recipient, spamScore, authResults, accepted) {
71
+ this._totalInboundProcessed++;
72
+ const messageId = `inbound:${sender}->${recipient}:${Date.now()}`;
73
+ // Log via existing logger (Req 10.4)
74
+ this.logger.logMessageCreated(messageId, sender, 1);
75
+ this.logger.logRoutingDecision(messageId, `spam:${spamScore}|spf:${authResults.spf.status}|dkim:${authResults.dkim.status}|dmarc:${authResults.dmarc.status}|${accepted ? 'accepted' : 'rejected'}`, 1);
76
+ if (!accepted) {
77
+ this.logger.logDeliveryFailure(messageId, recipient, 'rejected');
78
+ }
79
+ }
80
+ // ── Metrics recording (Req 10.3) ──────────────────────────────────
81
+ /**
82
+ * Record the current outbound queue depth.
83
+ *
84
+ * @see Requirement 10.3
85
+ */
86
+ recordQueueDepth(depth) {
87
+ this._outboundQueueDepth = depth;
88
+ this.metrics.recordStorageUtilization(depth);
89
+ }
90
+ /**
91
+ * Record a successful delivery and its latency.
92
+ *
93
+ * @see Requirement 10.3
94
+ */
95
+ recordDeliverySuccess(latencyMs) {
96
+ this._deliverySuccessCount++;
97
+ if (latencyMs !== undefined) {
98
+ this._totalDeliveryLatencyMs += latencyMs;
99
+ this.metrics.recordMessageDelivered(latencyMs);
100
+ }
101
+ else {
102
+ this.metrics.recordMessageDelivered(0);
103
+ }
104
+ }
105
+ /**
106
+ * Record a delivery failure.
107
+ *
108
+ * @see Requirement 10.3
109
+ */
110
+ recordDeliveryFailure() {
111
+ this._deliveryFailureCount++;
112
+ this.metrics.recordMessageFailed();
113
+ }
114
+ /**
115
+ * Record delivery latency in milliseconds.
116
+ *
117
+ * @see Requirement 10.3
118
+ */
119
+ recordDeliveryLatency(ms) {
120
+ this._totalDeliveryLatencyMs += ms;
121
+ this.metrics.recordMessageDelivered(ms);
122
+ }
123
+ /**
124
+ * Record a spam rejection.
125
+ *
126
+ * @see Requirement 10.3
127
+ */
128
+ recordSpamRejection() {
129
+ this._spamRejectionCount++;
130
+ this._totalInboundProcessed++;
131
+ this.metrics.recordMessageFailed();
132
+ }
133
+ // ── Alert emission (Req 10.5) ─────────────────────────────────────
134
+ /**
135
+ * Emit an alert when delivery fails after all retries are exhausted.
136
+ *
137
+ * Delegates to the existing `AlertMonitor` for consistent alerting.
138
+ *
139
+ * @see Requirement 10.5
140
+ */
141
+ alertDeliveryExhausted(messageId, recipient, retryCount) {
142
+ // Use AlertMonitor's failure rate check to trigger handler (Req 10.5)
143
+ this.alertMonitor.checkFailureRate(this._deliverySuccessCount, this._deliveryFailureCount);
144
+ // Also emit a specific event-emission alert with context
145
+ this.alertMonitor.checkEventEmission(`Delivery exhausted: messageId=${messageId}, recipient=${recipient}, retries=${retryCount}`);
146
+ // Log via existing logger
147
+ this.logger.logDeliveryFailure(messageId, recipient, `retries exhausted after ${retryCount} attempts`);
148
+ }
149
+ // ── Metrics snapshot (Req 10.3) ───────────────────────────────────
150
+ /**
151
+ * Return a point-in-time snapshot of all gateway-specific metrics.
152
+ *
153
+ * @see Requirement 10.3
154
+ */
155
+ getMetricsSnapshot() {
156
+ const totalDeliveries = this._deliverySuccessCount + this._deliveryFailureCount;
157
+ const deliveredCount = this._deliverySuccessCount;
158
+ return {
159
+ outboundQueueDepth: this._outboundQueueDepth,
160
+ deliverySuccessCount: this._deliverySuccessCount,
161
+ deliveryFailureCount: this._deliveryFailureCount,
162
+ deliverySuccessRate: totalDeliveries > 0 ? deliveredCount / totalDeliveries : 0,
163
+ deliveryFailureRate: totalDeliveries > 0 ? this._deliveryFailureCount / totalDeliveries : 0,
164
+ averageDeliveryLatencyMs: deliveredCount > 0 ? this._totalDeliveryLatencyMs / deliveredCount : 0,
165
+ spamRejectionCount: this._spamRejectionCount,
166
+ spamRejectionRate: this._totalInboundProcessed > 0
167
+ ? this._spamRejectionCount / this._totalInboundProcessed
168
+ : 0,
169
+ totalInboundProcessed: this._totalInboundProcessed,
170
+ };
171
+ }
172
+ /**
173
+ * Reset all gateway-specific counters.
174
+ */
175
+ reset() {
176
+ this._outboundQueueDepth = 0;
177
+ this._deliverySuccessCount = 0;
178
+ this._deliveryFailureCount = 0;
179
+ this._totalDeliveryLatencyMs = 0;
180
+ this._spamRejectionCount = 0;
181
+ this._totalInboundProcessed = 0;
182
+ this.metrics.reset();
183
+ }
184
+ }
185
+ exports.GatewayObservability = GatewayObservability;
186
+ //# sourceMappingURL=gatewayObservability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gatewayObservability.js","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/gatewayObservability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * InboundProcessor — watches the Mail Drop Directory for new Maildir-format
3
+ * files deposited by Postfix, parses each message via EmailParser, stores
4
+ * content in the Block Store, creates metadata via EmailMessageService, and
5
+ * announces delivery to the recipient via the Gossip Protocol.
6
+ *
7
+ * On success the processed file is deleted from the Mail Drop Directory.
8
+ * On failure the file is moved to a configurable error directory and the
9
+ * failure reason is logged.
10
+ *
11
+ * A Set of processed filenames provides idempotency — the same file will
12
+ * not be processed twice even if the watcher fires duplicate events.
13
+ *
14
+ * @see Requirements 4.4, 4.5, 4.6, 4.7, 4.8, 4.9
15
+ * @module inboundProcessor
16
+ */
17
+ import type { IBlockStore, IGossipService } from '@brightchain/brightchain-lib';
18
+ import { EmailMessageService, EmailParser } from '@brightchain/brightchain-lib';
19
+ import type { IEmailAuthVerifier } from './emailAuthVerifier';
20
+ import type { IEmailGatewayConfig } from './emailGatewayConfig';
21
+ /**
22
+ * Watches the Mail Drop Directory for new inbound email files and processes
23
+ * them into the BrightChain internal messaging system.
24
+ *
25
+ * Processing pipeline per file:
26
+ * 1. Read raw file content
27
+ * 2. Parse RFC 5322 message via EmailParser
28
+ * 3. Store content in Block Store
29
+ * 4. Create metadata via EmailMessageService
30
+ * 5. Announce to recipient via Gossip Protocol
31
+ * 6. Delete file on success / move to error directory on failure
32
+ *
33
+ * @see Requirements 4.4, 4.5, 4.6, 4.7, 4.8, 4.9
34
+ */
35
+ export declare class InboundProcessor {
36
+ private readonly config;
37
+ private readonly emailMessageService;
38
+ private readonly blockStore;
39
+ private readonly gossipService;
40
+ private readonly parser;
41
+ /** Authentication verifier for SPF/DKIM/DMARC. Req 6.4, 6.5 */
42
+ private readonly authVerifier;
43
+ /** fs.watch handle — `null` when stopped. */
44
+ private watcher;
45
+ /** Whether the processor is currently running. */
46
+ private running;
47
+ /** Filenames that have already been processed (idempotency guard). Req 4.7 */
48
+ private readonly processedFiles;
49
+ constructor(config: IEmailGatewayConfig, emailParser: EmailParser | null, emailMessageService: EmailMessageService, blockStore: IBlockStore, gossipService: IGossipService, authVerifier?: IEmailAuthVerifier);
50
+ /**
51
+ * Start watching the Mail Drop Directory for new files.
52
+ *
53
+ * Creates the mail drop and error directories if they do not exist,
54
+ * then sets up an `fs.watch` listener that triggers processing for
55
+ * every new or renamed file.
56
+ *
57
+ * @see Requirement 4.5 — watch via inotify / fs.watch
58
+ */
59
+ start(): void;
60
+ /**
61
+ * Stop watching the Mail Drop Directory.
62
+ */
63
+ stop(): void;
64
+ /**
65
+ * Whether the processor is currently running.
66
+ */
67
+ isRunning(): boolean;
68
+ /**
69
+ * Process all files already present in the Mail Drop Directory.
70
+ * Called once on startup to handle files deposited while the processor
71
+ * was not running.
72
+ */
73
+ private processExistingFiles;
74
+ /**
75
+ * Process a single inbound email file.
76
+ *
77
+ * Idempotency: if the file has already been processed (tracked in
78
+ * `processedFiles`) the call is a no-op. Req 4.7
79
+ *
80
+ * @param filename - The filename (not full path) within the Mail Drop Directory
81
+ *
82
+ * @see Requirement 4.6 — parse, store, create metadata
83
+ * @see Requirement 4.7 — delete on success
84
+ * @see Requirement 4.8 — move to error directory on failure
85
+ * @see Requirement 4.9 — announce via gossip
86
+ */
87
+ processFile(filename: string): Promise<void>;
88
+ /**
89
+ * Merge authentication results into custom headers as a serialized
90
+ * `X-BrightChain-Auth-Results` header so the auth metadata is
91
+ * preserved alongside the message.
92
+ *
93
+ * @see Requirement 6.4
94
+ */
95
+ private mergeAuthHeaders;
96
+ /**
97
+ * Extract plain-text body from parsed email metadata.
98
+ */
99
+ private extractTextBody;
100
+ /**
101
+ * Extract HTML body from parsed email metadata.
102
+ */
103
+ private extractHtmlBody;
104
+ /**
105
+ * Get the set of processed filenames (for testing / inspection).
106
+ */
107
+ getProcessedFiles(): ReadonlySet<string>;
108
+ /**
109
+ * Clear the processed files set (for testing).
110
+ */
111
+ clearProcessedFiles(): void;
112
+ }
113
+ //# sourceMappingURL=inboundProcessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inboundProcessor.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/inboundProcessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAEV,WAAW,EAGX,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAIhE;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAgB;IAgBzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAnBhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC,+DAA+D;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAElD,6CAA6C;IAC7C,OAAO,CAAC,OAAO,CAA6B;IAE5C,kDAAkD;IAClD,OAAO,CAAC,OAAO,CAAS;IAExB,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;gBAGtC,MAAM,EAAE,mBAAmB,EAC5C,WAAW,EAAE,WAAW,GAAG,IAAI,EACd,mBAAmB,EAAE,mBAAmB,EACxC,UAAU,EAAE,WAAW,EACvB,aAAa,EAAE,cAAc,EAC9C,YAAY,CAAC,EAAE,kBAAkB;IAQnC;;;;;;;;OAQG;IACH,KAAK,IAAI,IAAI;IA4Bb;;OAEG;IACH,IAAI,IAAI,IAAI;IAWZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAMpB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;;;;;OAYG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4GlD;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,iBAAiB,IAAI,WAAW,CAAC,MAAM,CAAC;IAIxC;;OAEG;IACH,mBAAmB,IAAI,IAAI;CAG5B"}