@push.rocks/smartmta 8.0.1 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/changelog.md +51 -0
  2. package/dist_rust/mailer-bin_linux_amd64 +0 -0
  3. package/dist_rust/mailer-bin_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/index.d.ts +6 -0
  6. package/dist_ts/index.js +7 -1
  7. package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +43 -3
  8. package/dist_ts/mail/delivery/classes.delivery.queue.js +310 -10
  9. package/dist_ts/mail/delivery/classes.delivery.system.d.ts +13 -2
  10. package/dist_ts/mail/delivery/classes.delivery.system.js +106 -36
  11. package/dist_ts/mail/interfaces.storage.d.ts +34 -0
  12. package/dist_ts/mail/interfaces.storage.js +89 -3
  13. package/dist_ts/mail/routing/classes.domain.registry.js +5 -1
  14. package/dist_ts/mail/routing/classes.email.action.executor.d.ts +15 -0
  15. package/dist_ts/mail/routing/classes.email.action.executor.js +38 -13
  16. package/dist_ts/mail/routing/classes.email.router.d.ts +2 -0
  17. package/dist_ts/mail/routing/classes.email.router.js +28 -21
  18. package/dist_ts/mail/routing/classes.unified.email.server.d.ts +156 -4
  19. package/dist_ts/mail/routing/classes.unified.email.server.js +1001 -61
  20. package/dist_ts/mail/routing/functions.routing.validation.d.ts +8 -0
  21. package/dist_ts/mail/routing/functions.routing.validation.js +18 -0
  22. package/dist_ts/mail/routing/interfaces.d.ts +11 -1
  23. package/dist_ts/plugins.d.ts +2 -1
  24. package/dist_ts/plugins.js +3 -2
  25. package/dist_ts/security/classes.rustsecuritybridge.d.ts +32 -1
  26. package/dist_ts/security/classes.rustsecuritybridge.js +13 -1
  27. package/dist_ts/security/index.d.ts +1 -1
  28. package/dist_ts/security/index.js +1 -1
  29. package/package.json +1 -1
  30. package/ts/00_commitinfo_data.ts +1 -1
  31. package/ts/index.ts +6 -0
  32. package/ts/mail/delivery/classes.delivery.queue.ts +429 -7
  33. package/ts/mail/delivery/classes.delivery.system.ts +137 -41
  34. package/ts/mail/interfaces.storage.ts +148 -2
  35. package/ts/mail/routing/classes.domain.registry.ts +4 -0
  36. package/ts/mail/routing/classes.email.action.executor.ts +97 -13
  37. package/ts/mail/routing/classes.email.router.ts +33 -20
  38. package/ts/mail/routing/classes.unified.email.server.ts +1367 -74
  39. package/ts/mail/routing/functions.routing.validation.ts +36 -0
  40. package/ts/mail/routing/interfaces.ts +13 -1
  41. package/ts/plugins.ts +2 -0
  42. package/ts/security/classes.rustsecuritybridge.ts +46 -1
  43. package/ts/security/index.ts +2 -0
package/changelog.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-07-21 - 8.1.1
4
+
5
+ ### Features
6
+
7
+ - add exact accepted-envelope dispatch for durable consumers
8
+ - Snapshot resolved per-recipient actions as immutable JSON-safe plans and replay them without consulting live routes.
9
+ - Scope parsed messages and SMTP sessions per envelope recipient while preserving the accepted raw RFC822 bytes unchanged.
10
+ - Queue forward, process, and deliver actions with durable deterministic idempotency keys and return their queue IDs.
11
+ - Persist bounded replay checkpoints through caller-managed storage; no filesystem persistence is introduced.
12
+ - Add backend-bounded prefix pagination and use it for convergent checkpoint and queue-tombstone cleanup.
13
+ - add exact accepted-envelope dispatch (accepted-envelope-dispatch)
14
+ - Snapshot resolved per-recipient actions as immutable JSON-safe plans for replay without consulting live routes.
15
+ - Queue forward, process, and deliver actions with deterministic durable idempotency keys and return queue IDs.
16
+ - Add accepted-envelope replay checkpoints with bounded cleanup backed by caller-managed storage.
17
+ - Introduce backend-bounded prefix pagination and use it for checkpoint and queue tombstone cleanup.
18
+
19
+ ## 2026-07-21 - 8.1.0
20
+
21
+ ### Features
22
+
23
+ - add fail-closed inbound storage policies and durable envelope acceptance
24
+ - Add per-domain store/reject fallbacks that run only after explicit recipient routes.
25
+ - Expose one awaited envelope hook with the exact raw message, complete SMTP envelope, resolved routes, typed security verdicts, and attachment count before the SMTP 250 response.
26
+ - Emit typed recipient-rejection observations with truthful local-mailbox and non-hosted-domain responses.
27
+ - expose complete SMTP delivery evidence
28
+ - Preserve lossless outbound attachments across the TypeScript/Rust boundary, including binary payloads, Unicode filenames, content IDs, and hardened MIME parameters.
29
+ - Record structured DATA transfer bytes, write-chunk counts, and duration on SMTP transaction entries.
30
+ - Persist materialized attachment counts on managed queue records with backward-compatible hydration.
31
+ - classify self-MX against the complete listener topology
32
+ - Normalize DNS names and IP literals, follow bounded CNAME chains, compare A/AAAA answers with explicit and dynamic listener identities, and fail closed on indeterminate DNS.
33
+ - Treat configured topology identity providers that return no proof, throw, or time out as indeterminate and perform no SMTP dial.
34
+ - Skip local MX candidates while continuing to eligible backup MX hosts, recording synthetic no-dial attempts for every skipped candidate.
35
+ - add inbound storage policies and durable delivery evidence (mail)
36
+ - Add per-domain inbound store/reject policies with route validation and awaited envelope acceptance context.
37
+ - Preserve outbound attachments across the TypeScript/Rust bridge with hardened MIME parameter handling.
38
+ - Record SMTP DATA transfer statistics and persist queue attachment counts for delivery diagnostics.
39
+ - Classify self-MX candidates against listener topology, skip local MX hosts, and continue to eligible backups.
40
+ - Add a durable delivery-failure outbox for terminal transport and local-topology failures.
41
+
42
+ ### Fixes
43
+
44
+ - preserve delivery semantics when retries are exhausted
45
+ - Terminalize unresolved recipients atomically with a separate durable delivery-failure operation.
46
+ - Drain delivery-failure operations in bounded startup and periodic batches with durable retry backoff and idempotent operation IDs.
47
+ - Keep local topology and transport exhaustion out of the SMTP-recipient suppression/bounce evidence path.
48
+ - Make explicit self-MX configuration failures terminal while allowing dynamic or DNS-derived topology to recover on retry.
49
+ - preserve rejection and transfer diagnostics under failure pressure
50
+ - Observe RCPT policy callback exceptions and timeouts exactly once as policy errors before returning SMTP 451.
51
+ - Reserve the structured DATA transfer summary when the bounded SMTP transcript reaches its entry cap.
52
+ - stop the rate-limiter cleanup timer when UnifiedEmailServer shuts down
53
+
3
54
  ## 2026-07-20 - 8.0.1
4
55
 
5
56
  ### Fixes
Binary file
Binary file
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartmta',
6
- version: '8.0.1',
6
+ version: '8.1.1',
7
7
  description: 'A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with Rust acceleration.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlIQUF5SDtDQUN2SSxDQUFBIn0=
@@ -7,4 +7,10 @@ export declare const smartMtaCapabilities: Readonly<{
7
7
  readonly callerManagedDkimKeys: true;
8
8
  readonly structuredSmtpTransactions: true;
9
9
  readonly typedDeliveryFailures: true;
10
+ readonly inboundStorePolicies: true;
11
+ readonly smtpTransferStats: true;
12
+ readonly outboundAttachments: true;
13
+ readonly topologyAwareSelfMx: true;
14
+ readonly durableDeliveryFailureOutbox: true;
15
+ readonly exactAcceptedEnvelopeDispatch: true;
10
16
  }>;
package/dist_ts/index.js CHANGED
@@ -7,5 +7,11 @@ export const smartMtaCapabilities = Object.freeze({
7
7
  callerManagedDkimKeys: true,
8
8
  structuredSmtpTransactions: true,
9
9
  typedDeliveryFailures: true,
10
+ inboundStorePolicies: true,
11
+ smtpTransferStats: true,
12
+ outboundAttachments: true,
13
+ topologyAwareSelfMx: true,
14
+ durableDeliveryFailureOutbox: true,
15
+ exactAcceptedEnvelopeDispatch: true,
10
16
  });
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2hELDBCQUEwQixFQUFFLElBQUk7SUFDaEMscUJBQXFCLEVBQUUsSUFBSTtJQUMzQiwwQkFBMEIsRUFBRSxJQUFJO0lBQ2hDLHFCQUFxQixFQUFFLElBQUk7Q0FDbkIsQ0FBQyxDQUFDIn0=
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2hELDBCQUEwQixFQUFFLElBQUk7SUFDaEMscUJBQXFCLEVBQUUsSUFBSTtJQUMzQiwwQkFBMEIsRUFBRSxJQUFJO0lBQ2hDLHFCQUFxQixFQUFFLElBQUk7SUFDM0Isb0JBQW9CLEVBQUUsSUFBSTtJQUMxQixpQkFBaUIsRUFBRSxJQUFJO0lBQ3ZCLG1CQUFtQixFQUFFLElBQUk7SUFDekIsbUJBQW1CLEVBQUUsSUFBSTtJQUN6Qiw0QkFBNEIsRUFBRSxJQUFJO0lBQ2xDLDZCQUE2QixFQUFFLElBQUk7Q0FDM0IsQ0FBQyxDQUFDIn0=
@@ -24,7 +24,8 @@ export interface IRecipientPermanentFailure {
24
24
  }
25
25
  export interface IBounceOperation {
26
26
  operationId: string;
27
- kind: 'smtpFailure';
27
+ kind: 'smtpFailure' | 'deliveryFailure';
28
+ failureClass?: 'localTopology' | 'transport';
28
29
  recipient: string;
29
30
  normalizedRecipient: string;
30
31
  smtpCode: number;
@@ -40,8 +41,14 @@ export interface IBounceOperation {
40
41
  */
41
42
  export interface IQueueItem {
42
43
  id: string;
44
+ /** Stable caller-supplied key used to make enqueue replay-safe. */
45
+ idempotencyKey?: string;
46
+ /** Fingerprint of the exact work associated with the idempotency key. */
47
+ idempotencyFingerprint?: string;
43
48
  processingMode: EmailProcessingMode;
44
49
  processingResult: Email;
50
+ /** Materialized attachment count for queue/detail consumers. */
51
+ attachmentCount?: number;
45
52
  route?: IEmailRoute;
46
53
  status: QueueItemStatus;
47
54
  attempts: number;
@@ -56,9 +63,15 @@ export interface IQueueItem {
56
63
  bounceOperations?: IBounceOperation[];
57
64
  smtpTransactions?: ISmtpTransactionAttempt[];
58
65
  }
66
+ export declare const ACCEPTED_ENVELOPE_IDEMPOTENCY_RETENTION_MS: number;
59
67
  export interface IQueueFailureOptions {
60
68
  /** Unknown failures default to retryable so temporary internal faults do not lose mail. */
61
69
  retryable?: boolean;
70
+ /** Durable work created atomically when unresolved recipients become terminal. */
71
+ terminalFailure?: {
72
+ failureClass: 'localTopology' | 'transport';
73
+ smtpCode?: number;
74
+ };
62
75
  }
63
76
  export interface IQueueFailureTransition {
64
77
  updated: boolean;
@@ -82,6 +95,14 @@ export interface IQueueOptions {
82
95
  baseRetryDelay?: number;
83
96
  maxRetryDelay?: number;
84
97
  }
98
+ export interface IQueueEnqueueOptions {
99
+ /** Stable key that resolves to one deterministic queue item id. */
100
+ idempotencyKey?: string;
101
+ /** Required with idempotencyKey to reject reuse for different work. */
102
+ idempotencyFingerprint?: string;
103
+ /** Fail closed unless the queue is backed by managed blob storage. */
104
+ requireDurable?: boolean;
105
+ }
85
106
  export interface IQueueStats {
86
107
  queueSize: number;
87
108
  status: {
@@ -115,12 +136,25 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
115
136
  private totalProcessed;
116
137
  private ownsManagedPrefix;
117
138
  private lifecycleState;
139
+ private readonly idempotentEnqueueFlights;
140
+ private idempotencyTombstoneCleanupCursor?;
118
141
  /**
119
142
  * Create a new unified delivery queue
120
143
  * @param options Queue options
121
144
  */
122
145
  constructor(options: IQueueOptions);
123
146
  private assertMutable;
147
+ /** Whether queue entries are committed through caller-managed blob storage. */
148
+ hasManagedStorage(): boolean;
149
+ /** Whether managed storage can list a backend-bounded page of keys. */
150
+ hasPaginatedManagedStorage(): boolean;
151
+ private idempotentQueueId;
152
+ private idempotencyTombstonePrefix;
153
+ private idempotencyTombstoneKey;
154
+ private readIdempotencyTombstone;
155
+ private parseIdempotencyTombstone;
156
+ private persistIdempotencyTombstone;
157
+ private cleanupExpiredIdempotencyTombstones;
124
158
  private createInitialRecipientStates;
125
159
  private createBounceOperationId;
126
160
  /**
@@ -149,7 +183,8 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
149
183
  * @param mode Processing mode
150
184
  * @param route Email route
151
185
  */
152
- enqueue(processingResult: Email, mode: EmailProcessingMode, route?: IEmailRoute): Promise<string>;
186
+ enqueue(processingResult: Email, mode: EmailProcessingMode, route?: IEmailRoute, enqueueOptions?: IQueueEnqueueOptions): Promise<string>;
187
+ private enqueueNew;
153
188
  /**
154
189
  * Get an item from the queue
155
190
  * @param id Item ID
@@ -189,7 +224,12 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
189
224
  permanentFailures: string[];
190
225
  };
191
226
  /** Includes terminal queue items because bounce work outlives delivery status. */
192
- listPendingBounceOperations(now?: Date): Array<{
227
+ listPendingBounceOperations(now?: Date, limitArg?: number): Array<{
228
+ itemId: string;
229
+ operation: IBounceOperation;
230
+ }>;
231
+ /** Durable terminal-delivery notices. These never enter SMTP recipient suppression. */
232
+ listPendingDeliveryFailureOperations(now?: Date, limitArg?: number): Array<{
193
233
  itemId: string;
194
234
  operation: IBounceOperation;
195
235
  }>;