@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,209 @@
1
+ /**
2
+ * EmailGatewayService — orchestrator that bridges BrightChain's internal
3
+ * gossip-based messaging with external SMTP email delivery via Postfix.
4
+ *
5
+ * Responsibilities:
6
+ * - Listen for gossip announcements containing outbound email
7
+ * - Extract message blocks from the Block Store
8
+ * - Detect external recipients by comparing domain against canonicalDomain
9
+ * - Enqueue outbound messages for SMTP delivery
10
+ *
11
+ * @see Requirements 1.1, 1.2, 1.4
12
+ * @module emailGatewayService
13
+ */
14
+ import type { IBlockStore, IEmailMetadata, IGossipService } from '@brightchain/brightchain-lib';
15
+ import { EmailMessageService, OutboundDeliveryStatus } from '@brightchain/brightchain-lib';
16
+ import type { IEmailGatewayConfig } from './emailGatewayConfig';
17
+ /**
18
+ * Minimal interface for the outbound email queue.
19
+ *
20
+ * The full `OutboundQueue` class (task 4.2) will implement this.
21
+ * Using an interface here keeps the orchestrator decoupled from the
22
+ * queue's internal persistence and concurrency details.
23
+ */
24
+ export interface IOutboundQueue {
25
+ /**
26
+ * Add a message to the outbound delivery queue.
27
+ *
28
+ * @param message - Outbound message payload with recipient, content, and retry metadata
29
+ */
30
+ enqueue(message: IOutboundQueueItem): Promise<void>;
31
+ }
32
+ /**
33
+ * Interface for gateway components that support hot-reload of the canonical domain.
34
+ *
35
+ * Components implementing this interface can be registered with the
36
+ * `EmailGatewayService` so that when the canonical domain changes,
37
+ * all components are updated without requiring a restart.
38
+ *
39
+ * @see Requirement 8.5 — dynamic configuration reload
40
+ */
41
+ export interface IDomainAwareComponent {
42
+ /**
43
+ * Update the canonical domain used by this component.
44
+ *
45
+ * Implementations should apply the new domain immediately and clear
46
+ * any caches that depend on the old domain value.
47
+ *
48
+ * @param newDomain - The new canonical email domain
49
+ */
50
+ updateCanonicalDomain(newDomain: string): void;
51
+ }
52
+ /**
53
+ * A single item placed on the outbound delivery queue.
54
+ */
55
+ export interface IOutboundQueueItem {
56
+ /** RFC 5322 Message-ID */
57
+ messageId: string;
58
+ /** Sender email address */
59
+ from: string;
60
+ /** External recipient email addresses */
61
+ to: string[];
62
+ /** Email subject */
63
+ subject?: string;
64
+ /** Full email metadata for serialization */
65
+ metadata: IEmailMetadata;
66
+ /** Timestamp when the item was enqueued */
67
+ enqueuedAt: Date;
68
+ /** Current delivery status */
69
+ status: OutboundDeliveryStatus;
70
+ /** Number of delivery attempts so far */
71
+ retryCount: number;
72
+ /** Earliest time at which the next delivery attempt should be made */
73
+ nextAttemptAt?: Date;
74
+ }
75
+ /**
76
+ * Orchestrator service for the Email Gateway.
77
+ *
78
+ * Listens for gossip announcements that carry outbound email, extracts the
79
+ * message content from the Block Store, identifies external recipients by
80
+ * comparing their domain against the configured `canonicalDomain`, and
81
+ * enqueues qualifying messages in the OutboundQueue for SMTP delivery.
82
+ *
83
+ * Lifecycle:
84
+ * - `start()` registers the gossip announcement listener
85
+ * - `stop()` removes the listener and performs cleanup
86
+ *
87
+ * @see Requirements 1.1, 1.2, 1.4
88
+ */
89
+ export declare class EmailGatewayService {
90
+ private readonly config;
91
+ private readonly gossipService;
92
+ private readonly blockStore;
93
+ private readonly emailMessageService;
94
+ private outboundQueue?;
95
+ /** Bound reference kept so we can unsubscribe on stop(). */
96
+ private readonly boundAnnouncementHandler;
97
+ /** Whether the service is currently running. */
98
+ private running;
99
+ /**
100
+ * Registered domain-aware child components that receive canonical domain
101
+ * updates when `updateCanonicalDomain()` is called.
102
+ *
103
+ * @see Requirement 8.5 — hot-reload canonical domain without restart
104
+ */
105
+ private readonly domainAwareComponents;
106
+ /**
107
+ * @param config - Gateway configuration (canonical domain, limits, etc.)
108
+ * @param gossipService - Gossip protocol service for subscribing to announcements
109
+ * @param blockStore - Block store for retrieving message content blocks
110
+ * @param emailMessageService - Email message service for retrieving email metadata
111
+ * @param outboundQueue - Queue for outbound SMTP delivery (optional; set later via `setOutboundQueue`)
112
+ */
113
+ constructor(config: IEmailGatewayConfig, gossipService: IGossipService, blockStore: IBlockStore, emailMessageService: EmailMessageService, outboundQueue?: IOutboundQueue | undefined);
114
+ /**
115
+ * Start the gateway service.
116
+ *
117
+ * Registers a gossip announcement listener that intercepts outbound
118
+ * email announcements and delegates them to the outbound queue.
119
+ */
120
+ start(): void;
121
+ /**
122
+ * Stop the gateway service.
123
+ *
124
+ * Removes the gossip listener and marks the service as stopped.
125
+ */
126
+ stop(): void;
127
+ /**
128
+ * Whether the service is currently running.
129
+ */
130
+ isRunning(): boolean;
131
+ /**
132
+ * Wire the outbound queue after construction.
133
+ *
134
+ * Useful when the queue is created after the gateway service (e.g.
135
+ * during staged initialisation).
136
+ */
137
+ setOutboundQueue(queue: IOutboundQueue): void;
138
+ /**
139
+ * Register a child component that should be notified when the
140
+ * canonical domain changes.
141
+ *
142
+ * @param component - A component implementing `IDomainAwareComponent`
143
+ *
144
+ * @see Requirement 8.5 — hot-reload canonical domain without restart
145
+ */
146
+ registerDomainAwareComponent(component: IDomainAwareComponent): void;
147
+ /**
148
+ * Update the canonical domain across the gateway and all registered
149
+ * child components without requiring a restart.
150
+ *
151
+ * This method:
152
+ * 1. Updates the shared `IEmailGatewayConfig.canonicalDomain`
153
+ * 2. Propagates the new domain to all registered `IDomainAwareComponent`s
154
+ * (e.g. OutboundDeliveryWorker for DKIM signing, RecipientLookupService
155
+ * for inbound validation, BounceProcessor for VERP parsing)
156
+ *
157
+ * @param newDomain - The new canonical email domain
158
+ *
159
+ * @see Requirement 8.5 — when the canonical domain changes, update all
160
+ * gateway components for outbound signing and inbound recipient
161
+ * validation without requiring a restart
162
+ */
163
+ updateCanonicalDomain(newDomain: string): void;
164
+ /**
165
+ * Get the current canonical domain.
166
+ */
167
+ getCanonicalDomain(): string;
168
+ /**
169
+ * Determine whether an email address is external (not on the canonical domain).
170
+ *
171
+ * Extracts the domain portion of the address and compares it
172
+ * case-insensitively against `config.canonicalDomain`.
173
+ *
174
+ * @param emailAddress - A full email address (e.g. `alice@example.com`)
175
+ * @returns `true` when the address belongs to an external domain
176
+ *
177
+ * @see Requirement 1.1 — detect recipients whose domain ≠ canonical domain
178
+ */
179
+ isExternalRecipient(emailAddress: string): boolean;
180
+ /**
181
+ * Partition a list of email addresses into internal and external groups.
182
+ *
183
+ * @param addresses - Array of email addresses
184
+ * @returns Object with `internal` and `external` arrays
185
+ *
186
+ * @see Requirement 1.4 — mixed internal/external recipient handling
187
+ */
188
+ partitionRecipients(addresses: string[]): {
189
+ internal: string[];
190
+ external: string[];
191
+ };
192
+ /**
193
+ * Handle a gossip message-delivery announcement.
194
+ *
195
+ * When an announcement carries `messageDelivery` metadata the handler:
196
+ * 1. Retrieves the email metadata from the EmailMessageService
197
+ * 2. Identifies external recipients
198
+ * 3. Enqueues the message in the OutboundQueue for SMTP delivery
199
+ *
200
+ * Internal-only messages are ignored — they are already delivered via gossip.
201
+ *
202
+ * @param announcement - The gossip BlockAnnouncement with messageDelivery metadata
203
+ *
204
+ * @see Requirement 1.2 — extract message from Block Store and enqueue
205
+ * @see Requirement 1.4 — route external recipients to gateway
206
+ */
207
+ private handleAnnouncement;
208
+ }
209
+ //# sourceMappingURL=emailGatewayService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emailGatewayService.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/emailGatewayService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,cAAc,EACd,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAOhE;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;OAOG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAElB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,yCAAyC;IACzC,EAAE,EAAE,MAAM,EAAE,CAAC;IAEb,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,4CAA4C;IAC5C,QAAQ,EAAE,cAAc,CAAC;IAEzB,2CAA2C;IAC3C,UAAU,EAAE,IAAI,CAAC;IAEjB,8BAA8B;IAC9B,MAAM,EAAE,sBAAsB,CAAC;IAE/B,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IAEnB,sEAAsE;IACtE,aAAa,CAAC,EAAE,IAAI,CAAC;CACtB;AAID;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAmB;IAyB5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,aAAa,CAAC;IA5BxB,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAE/B;IAEV,gDAAgD;IAChD,OAAO,CAAC,OAAO,CAAS;IAExB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA+B;IAErE;;;;;;OAMG;gBAEgB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,EAAE,cAAc,EAC7B,UAAU,EAAE,WAAW,EACvB,mBAAmB,EAAE,mBAAmB,EACjD,aAAa,CAAC,EAAE,cAAc,YAAA;IAQxC;;;;;OAKG;IACH,KAAK,IAAI,IAAI;IAQb;;;;OAIG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;;OAKG;IACH,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAM7C;;;;;;;OAOG;IACH,4BAA4B,CAAC,SAAS,EAAE,qBAAqB,GAAG,IAAI;IAIpE;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAe9C;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAM5B;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAUlD;;;;;;;OAOG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG;QACxC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB;IAeD;;;;;;;;;;;;;;OAcG;YACW,kBAAkB;CAoDjC"}
@@ -0,0 +1,254 @@
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
+ * Registered domain-aware child components that receive canonical domain
45
+ * updates when `updateCanonicalDomain()` is called.
46
+ *
47
+ * @see Requirement 8.5 — hot-reload canonical domain without restart
48
+ */
49
+ domainAwareComponents = [];
50
+ /**
51
+ * @param config - Gateway configuration (canonical domain, limits, etc.)
52
+ * @param gossipService - Gossip protocol service for subscribing to announcements
53
+ * @param blockStore - Block store for retrieving message content blocks
54
+ * @param emailMessageService - Email message service for retrieving email metadata
55
+ * @param outboundQueue - Queue for outbound SMTP delivery (optional; set later via `setOutboundQueue`)
56
+ */
57
+ constructor(config, gossipService, blockStore, emailMessageService, outboundQueue) {
58
+ this.config = config;
59
+ this.gossipService = gossipService;
60
+ this.blockStore = blockStore;
61
+ this.emailMessageService = emailMessageService;
62
+ this.outboundQueue = outboundQueue;
63
+ // Bind once so the same reference is used for on/off.
64
+ this.boundAnnouncementHandler = this.handleAnnouncement.bind(this);
65
+ }
66
+ // ─── Lifecycle ──────────────────────────────────────────────────────
67
+ /**
68
+ * Start the gateway service.
69
+ *
70
+ * Registers a gossip announcement listener that intercepts outbound
71
+ * email announcements and delegates them to the outbound queue.
72
+ */
73
+ start() {
74
+ if (this.running) {
75
+ return;
76
+ }
77
+ this.gossipService.onMessageDelivery(this.boundAnnouncementHandler);
78
+ this.running = true;
79
+ }
80
+ /**
81
+ * Stop the gateway service.
82
+ *
83
+ * Removes the gossip listener and marks the service as stopped.
84
+ */
85
+ stop() {
86
+ if (!this.running) {
87
+ return;
88
+ }
89
+ this.gossipService.offMessageDelivery(this.boundAnnouncementHandler);
90
+ this.running = false;
91
+ }
92
+ /**
93
+ * Whether the service is currently running.
94
+ */
95
+ isRunning() {
96
+ return this.running;
97
+ }
98
+ /**
99
+ * Wire the outbound queue after construction.
100
+ *
101
+ * Useful when the queue is created after the gateway service (e.g.
102
+ * during staged initialisation).
103
+ */
104
+ setOutboundQueue(queue) {
105
+ this.outboundQueue = queue;
106
+ }
107
+ // ─── Hot-Reload: Canonical Domain ──────────────────────────────────
108
+ /**
109
+ * Register a child component that should be notified when the
110
+ * canonical domain changes.
111
+ *
112
+ * @param component - A component implementing `IDomainAwareComponent`
113
+ *
114
+ * @see Requirement 8.5 — hot-reload canonical domain without restart
115
+ */
116
+ registerDomainAwareComponent(component) {
117
+ this.domainAwareComponents.push(component);
118
+ }
119
+ /**
120
+ * Update the canonical domain across the gateway and all registered
121
+ * child components without requiring a restart.
122
+ *
123
+ * This method:
124
+ * 1. Updates the shared `IEmailGatewayConfig.canonicalDomain`
125
+ * 2. Propagates the new domain to all registered `IDomainAwareComponent`s
126
+ * (e.g. OutboundDeliveryWorker for DKIM signing, RecipientLookupService
127
+ * for inbound validation, BounceProcessor for VERP parsing)
128
+ *
129
+ * @param newDomain - The new canonical email domain
130
+ *
131
+ * @see Requirement 8.5 — when the canonical domain changes, update all
132
+ * gateway components for outbound signing and inbound recipient
133
+ * validation without requiring a restart
134
+ */
135
+ updateCanonicalDomain(newDomain) {
136
+ const trimmed = newDomain.trim();
137
+ if (trimmed.length === 0) {
138
+ return; // Ignore empty domain updates
139
+ }
140
+ // Update the shared config object (all components hold a reference to it).
141
+ this.config.canonicalDomain = trimmed;
142
+ // Propagate to all registered domain-aware components.
143
+ for (const component of this.domainAwareComponents) {
144
+ component.updateCanonicalDomain(trimmed);
145
+ }
146
+ }
147
+ /**
148
+ * Get the current canonical domain.
149
+ */
150
+ getCanonicalDomain() {
151
+ return this.config.canonicalDomain;
152
+ }
153
+ // ─── Domain Check ──────────────────────────────────────────────────
154
+ /**
155
+ * Determine whether an email address is external (not on the canonical domain).
156
+ *
157
+ * Extracts the domain portion of the address and compares it
158
+ * case-insensitively against `config.canonicalDomain`.
159
+ *
160
+ * @param emailAddress - A full email address (e.g. `alice@example.com`)
161
+ * @returns `true` when the address belongs to an external domain
162
+ *
163
+ * @see Requirement 1.1 — detect recipients whose domain ≠ canonical domain
164
+ */
165
+ isExternalRecipient(emailAddress) {
166
+ const atIndex = emailAddress.lastIndexOf('@');
167
+ if (atIndex === -1) {
168
+ // Malformed address — treat as external to be safe.
169
+ return true;
170
+ }
171
+ const domain = emailAddress.slice(atIndex + 1).toLowerCase();
172
+ return domain !== this.config.canonicalDomain.toLowerCase();
173
+ }
174
+ /**
175
+ * Partition a list of email addresses into internal and external groups.
176
+ *
177
+ * @param addresses - Array of email addresses
178
+ * @returns Object with `internal` and `external` arrays
179
+ *
180
+ * @see Requirement 1.4 — mixed internal/external recipient handling
181
+ */
182
+ partitionRecipients(addresses) {
183
+ const internal = [];
184
+ const external = [];
185
+ for (const addr of addresses) {
186
+ if (this.isExternalRecipient(addr)) {
187
+ external.push(addr);
188
+ }
189
+ else {
190
+ internal.push(addr);
191
+ }
192
+ }
193
+ return { internal, external };
194
+ }
195
+ // ─── Gossip Announcement Handler ───────────────────────────────────
196
+ /**
197
+ * Handle a gossip message-delivery announcement.
198
+ *
199
+ * When an announcement carries `messageDelivery` metadata the handler:
200
+ * 1. Retrieves the email metadata from the EmailMessageService
201
+ * 2. Identifies external recipients
202
+ * 3. Enqueues the message in the OutboundQueue for SMTP delivery
203
+ *
204
+ * Internal-only messages are ignored — they are already delivered via gossip.
205
+ *
206
+ * @param announcement - The gossip BlockAnnouncement with messageDelivery metadata
207
+ *
208
+ * @see Requirement 1.2 — extract message from Block Store and enqueue
209
+ * @see Requirement 1.4 — route external recipients to gateway
210
+ */
211
+ async handleAnnouncement(announcement) {
212
+ const delivery = announcement.messageDelivery;
213
+ if (!delivery) {
214
+ return;
215
+ }
216
+ // Retrieve the email metadata via the message ID.
217
+ const metadata = await this.emailMessageService.getEmail(delivery.messageId);
218
+ if (!metadata) {
219
+ // Message not found — nothing to route.
220
+ return;
221
+ }
222
+ // Collect all recipient addresses from the metadata.
223
+ const allRecipients = [
224
+ ...metadata.to.map((m) => m.address),
225
+ ...(metadata.cc ?? []).map((m) => m.address),
226
+ ...(metadata.bcc ?? []).map((m) => m.address),
227
+ ];
228
+ // Partition into internal / external.
229
+ const { external } = this.partitionRecipients(allRecipients);
230
+ if (external.length === 0) {
231
+ // Purely internal delivery — nothing for the gateway to do.
232
+ return;
233
+ }
234
+ if (!this.outboundQueue) {
235
+ // Queue not wired yet — cannot enqueue. This is a configuration issue.
236
+ // In production this would be logged/alerted; for now we silently skip.
237
+ return;
238
+ }
239
+ // Build the queue item and enqueue.
240
+ const queueItem = {
241
+ messageId: metadata.messageId,
242
+ from: metadata.from.address,
243
+ to: external,
244
+ subject: metadata.subject,
245
+ metadata,
246
+ enqueuedAt: new Date(),
247
+ status: brightchain_lib_1.OutboundDeliveryStatus.Queued,
248
+ retryCount: 0,
249
+ };
250
+ await this.outboundQueue.enqueue(queueItem);
251
+ }
252
+ }
253
+ exports.EmailGatewayService = EmailGatewayService;
254
+ //# 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"}