@serve.zone/coremail 1.0.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 (75) hide show
  1. package/.smartconfig.json +50 -0
  2. package/changelog.md +10 -0
  3. package/cli.js +4 -0
  4. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  5. package/dist_ts/00_commitinfo_data.js +9 -0
  6. package/dist_ts/classes.auth.d.ts +45 -0
  7. package/dist_ts/classes.auth.js +204 -0
  8. package/dist_ts/classes.config.d.ts +2 -0
  9. package/dist_ts/classes.config.js +72 -0
  10. package/dist_ts/classes.coremail.d.ts +41 -0
  11. package/dist_ts/classes.coremail.js +155 -0
  12. package/dist_ts/classes.desiredstate.d.ts +40 -0
  13. package/dist_ts/classes.desiredstate.js +382 -0
  14. package/dist_ts/classes.gateway.d.ts +62 -0
  15. package/dist_ts/classes.gateway.js +669 -0
  16. package/dist_ts/classes.inbound.d.ts +49 -0
  17. package/dist_ts/classes.inbound.js +702 -0
  18. package/dist_ts/classes.maintenance.d.ts +16 -0
  19. package/dist_ts/classes.maintenance.js +339 -0
  20. package/dist_ts/classes.models.d.ts +161 -0
  21. package/dist_ts/classes.models.js +595 -0
  22. package/dist_ts/classes.server.d.ts +40 -0
  23. package/dist_ts/classes.server.js +309 -0
  24. package/dist_ts/classes.storage.d.ts +32 -0
  25. package/dist_ts/classes.storage.js +317 -0
  26. package/dist_ts/classes.submissions.d.ts +33 -0
  27. package/dist_ts/classes.submissions.js +385 -0
  28. package/dist_ts/classes.transfer.d.ts +41 -0
  29. package/dist_ts/classes.transfer.js +289 -0
  30. package/dist_ts/coremail.cursor.d.ts +20 -0
  31. package/dist_ts/coremail.cursor.js +191 -0
  32. package/dist_ts/coremail.log.d.ts +3 -0
  33. package/dist_ts/coremail.log.js +11 -0
  34. package/dist_ts/coremail.mime.d.ts +8 -0
  35. package/dist_ts/coremail.mime.js +63 -0
  36. package/dist_ts/coremail.persistence.d.ts +148 -0
  37. package/dist_ts/coremail.persistence.js +695 -0
  38. package/dist_ts/coremail.quota.d.ts +29 -0
  39. package/dist_ts/coremail.quota.js +149 -0
  40. package/dist_ts/coremail.selectors.d.ts +3 -0
  41. package/dist_ts/coremail.selectors.js +21 -0
  42. package/dist_ts/coremail.validation.d.ts +9 -0
  43. package/dist_ts/coremail.validation.js +325 -0
  44. package/dist_ts/index.d.ts +4 -0
  45. package/dist_ts/index.js +39 -0
  46. package/dist_ts/interfaces.d.ts +92 -0
  47. package/dist_ts/interfaces.js +2 -0
  48. package/dist_ts/plugins.d.ts +11 -0
  49. package/dist_ts/plugins.js +12 -0
  50. package/license.md +19 -0
  51. package/package.json +48 -0
  52. package/readme.md +199 -0
  53. package/ts/00_commitinfo_data.ts +8 -0
  54. package/ts/classes.auth.ts +321 -0
  55. package/ts/classes.config.ts +104 -0
  56. package/ts/classes.coremail.ts +249 -0
  57. package/ts/classes.desiredstate.ts +508 -0
  58. package/ts/classes.gateway.ts +811 -0
  59. package/ts/classes.inbound.ts +898 -0
  60. package/ts/classes.maintenance.ts +335 -0
  61. package/ts/classes.models.ts +530 -0
  62. package/ts/classes.server.ts +444 -0
  63. package/ts/classes.storage.ts +448 -0
  64. package/ts/classes.submissions.ts +554 -0
  65. package/ts/classes.transfer.ts +379 -0
  66. package/ts/coremail.cursor.ts +328 -0
  67. package/ts/coremail.log.ts +21 -0
  68. package/ts/coremail.mime.ts +94 -0
  69. package/ts/coremail.persistence.ts +1156 -0
  70. package/ts/coremail.quota.ts +214 -0
  71. package/ts/coremail.selectors.ts +35 -0
  72. package/ts/coremail.validation.ts +446 -0
  73. package/ts/index.ts +38 -0
  74. package/ts/interfaces.ts +109 -0
  75. package/ts/plugins.ts +11 -0
@@ -0,0 +1,702 @@
1
+ import * as plugins from './plugins.js';
2
+ import {} from './classes.models.js';
3
+ import { createOpaqueToken, createSha256, } from './classes.storage.js';
4
+ import { CoreMailTransferService } from './classes.transfer.js';
5
+ import { normalizeCoreMailConnectionInfo, normalizeCoreMailEnvelope, normalizeCoreMailGatewayMessage, normalizeCoreMailMailboxAddress, } from './coremail.validation.js';
6
+ import { CoreMailInboundCursorCodec } from './coremail.cursor.js';
7
+ import { createCoreMailPendingQuotaDescriptor, decrementCoreMailQuotaCounter, ensureCoreMailQuotaCounter, incrementCoreMailQuotaCounter, withCoreMailTransaction, } from './coremail.quota.js';
8
+ import { requireCoreMailIdentifier, requireCoreMailUuid, } from './coremail.selectors.js';
9
+ const routingHandleTtlMs = plugins.serveZoneInterfaces.data.coreMailLimits.routingHandleTtlMs;
10
+ const listLimitMaximum = plugins.serveZoneInterfaces.data.coreMailLimits.inboundPageSize;
11
+ const gatewayAuthority = (serviceIdArg) => ({
12
+ kind: 'gateway',
13
+ tenantId: '-',
14
+ serviceId: serviceIdArg,
15
+ bindingId: '-',
16
+ });
17
+ const workloadAuthority = (sessionArg) => ({
18
+ kind: 'workload',
19
+ tenantId: sessionArg.tenantId,
20
+ serviceId: sessionArg.serviceId,
21
+ bindingId: sessionArg.bindingId,
22
+ });
23
+ const workloadFilter = (sessionArg, deliveryIdArg) => ({
24
+ tenantId: requireCoreMailIdentifier(sessionArg.tenantId, 'session.tenantId'),
25
+ serviceId: requireCoreMailIdentifier(sessionArg.serviceId, 'session.serviceId'),
26
+ bindingId: requireCoreMailIdentifier(sessionArg.bindingId, 'session.bindingId'),
27
+ bindingRevision: sessionArg.bindingRevision,
28
+ ...(deliveryIdArg === undefined
29
+ ? {}
30
+ : { deliveryId: requireCoreMailUuid(deliveryIdArg, 'deliveryId') }),
31
+ });
32
+ const toPublicDelivery = (deliveryArg) => ({
33
+ deliveryId: deliveryArg.deliveryId,
34
+ transportDeliveryId: deliveryArg.transportDeliveryId,
35
+ state: deliveryArg.state,
36
+ envelope: deliveryArg.envelope,
37
+ rawMime: {
38
+ sha256: deliveryArg.rawMimeSha256,
39
+ lengthBytes: deliveryArg.rawMimeLengthBytes,
40
+ contentType: 'message/rfc822',
41
+ },
42
+ ...(deliveryArg.messageId ? { messageId: deliveryArg.messageId } : {}),
43
+ ...(deliveryArg.subject ? { subject: deliveryArg.subject } : {}),
44
+ receivedAt: deliveryArg.receivedAt,
45
+ updatedAt: deliveryArg.updatedAt,
46
+ ...(deliveryArg.state === 'acknowledged'
47
+ ? {
48
+ acknowledgedAt: deliveryArg.updatedAt,
49
+ acknowledgedOutcome: deliveryArg.acknowledgedOutcome,
50
+ }
51
+ : {}),
52
+ });
53
+ const createEnvelopeDigest = (envelopeArg, sourceArg) => createSha256(JSON.stringify({
54
+ envelope: envelopeArg,
55
+ source: sourceArg,
56
+ }));
57
+ const canonicalJson = (valueArg) => {
58
+ const visit = (value) => {
59
+ if (Array.isArray(value))
60
+ return value.map(visit);
61
+ if (value && typeof value === 'object') {
62
+ return Object.fromEntries(Object.keys(value)
63
+ .sort()
64
+ .map((keyArg) => [
65
+ keyArg,
66
+ visit(value[keyArg]),
67
+ ]));
68
+ }
69
+ return value;
70
+ };
71
+ return JSON.stringify(visit(valueArg));
72
+ };
73
+ const isUniqueConflict = (errorArg) => errorArg instanceof plugins.smartdata.SmartdataExactPersistenceError
74
+ && errorArg.code === 'unique_conflict';
75
+ export class CoreMailInboundService {
76
+ database;
77
+ models;
78
+ transfers;
79
+ serviceId;
80
+ getDesiredState;
81
+ now;
82
+ cursorCodec;
83
+ constructor(database, models, transfers, serviceId, getDesiredState, resolveRuntimeSecretArg, now = Date.now) {
84
+ this.database = database;
85
+ this.models = models;
86
+ this.transfers = transfers;
87
+ this.serviceId = serviceId;
88
+ this.getDesiredState = getDesiredState;
89
+ this.now = now;
90
+ this.cursorCodec = new CoreMailInboundCursorCodec(resolveRuntimeSecretArg);
91
+ }
92
+ async resolveRecipients(requestArg) {
93
+ const desiredState = await this.getDesiredState();
94
+ if (!desiredState) {
95
+ throw new Error('CoreMail desired state is unavailable.');
96
+ }
97
+ if (!Array.isArray(requestArg.recipients)
98
+ || requestArg.recipients.length === 0
99
+ || requestArg.recipients.length > 100) {
100
+ throw new Error('CoreMail gateway recipients are invalid.');
101
+ }
102
+ const envelope = normalizeCoreMailEnvelope(requestArg.envelope);
103
+ const source = normalizeCoreMailConnectionInfo(requestArg.source);
104
+ const envelopeDigest = createEnvelopeDigest(envelope, source);
105
+ const recipients = requestArg.recipients.map(normalizeCoreMailMailboxAddress);
106
+ if (new Set(recipients).size !== recipients.length) {
107
+ throw new Error('CoreMail gateway recipients contain duplicates.');
108
+ }
109
+ const resolutions = [];
110
+ const pendingCounts = new Map();
111
+ for (const recipient of recipients) {
112
+ const binding = desiredState.bindings.find((bindingArg) => bindingArg.state === 'active'
113
+ && bindingArg.capabilities.includes('inbound')
114
+ && bindingArg.inboundRecipients.includes(recipient));
115
+ if (!binding) {
116
+ resolutions.push({
117
+ recipient,
118
+ action: 'reject',
119
+ smtpCode: 550,
120
+ message: 'Recipient unavailable',
121
+ });
122
+ continue;
123
+ }
124
+ let pendingCount = pendingCounts.get(binding.bindingId);
125
+ if (pendingCount === undefined) {
126
+ pendingCount = await this.models.InboundDelivery.exact.count({
127
+ tenantId: binding.tenantId,
128
+ serviceId: binding.serviceId,
129
+ bindingId: binding.bindingId,
130
+ bindingRevision: binding.revision,
131
+ state: {
132
+ $in: [...plugins.serveZoneInterfaces.data.coreMailQuotaPolicy
133
+ .pendingInboundStates],
134
+ },
135
+ });
136
+ pendingCounts.set(binding.bindingId, pendingCount);
137
+ }
138
+ if (pendingCount >= binding.limits.maxPendingInbound) {
139
+ resolutions.push({
140
+ recipient,
141
+ action: 'defer',
142
+ smtpCode: 452,
143
+ message: 'Recipient temporarily unavailable',
144
+ });
145
+ continue;
146
+ }
147
+ const routingHandle = createOpaqueToken();
148
+ const createdAt = this.now();
149
+ const inserted = await this.models.RecipientHandle.exact.insert({
150
+ routingHandle: createSha256(routingHandle),
151
+ tenantId: binding.tenantId,
152
+ serviceId: binding.serviceId,
153
+ bindingId: binding.bindingId,
154
+ bindingRevision: binding.revision,
155
+ maxPendingInbound: binding.limits.maxPendingInbound,
156
+ recipient,
157
+ envelopeDigest,
158
+ state: 'issued',
159
+ expiresAt: createdAt + routingHandleTtlMs,
160
+ createdAt,
161
+ });
162
+ if (inserted.status === 'conflict') {
163
+ throw new Error('CoreMail routing handle identity conflict.');
164
+ }
165
+ resolutions.push({
166
+ recipient,
167
+ action: 'accept',
168
+ routingHandle,
169
+ });
170
+ }
171
+ return { resolutions };
172
+ }
173
+ async prepareInboundHandoff(requestArg) {
174
+ if (!Array.isArray(requestArg.routingHandles)
175
+ || requestArg.routingHandles.length === 0
176
+ || requestArg.routingHandles.length > 100) {
177
+ throw new Error('CoreMail inbound handoff identity is invalid.');
178
+ }
179
+ const transportDeliveryId = requireCoreMailIdentifier(requestArg.transportDeliveryId, 'transportDeliveryId');
180
+ const routingHandles = requestArg.routingHandles.map((handleArg) => {
181
+ if (typeof handleArg !== 'string' || handleArg.length < 32 || handleArg.length > 512) {
182
+ throw new Error('CoreMail routing handle is invalid.');
183
+ }
184
+ return createSha256(handleArg);
185
+ });
186
+ if (new Set(routingHandles).size !== routingHandles.length) {
187
+ throw new Error('CoreMail inbound handoff contains duplicate routing handles.');
188
+ }
189
+ const message = normalizeCoreMailGatewayMessage(requestArg.message);
190
+ const source = normalizeCoreMailConnectionInfo(requestArg.source);
191
+ const envelopeDigest = createEnvelopeDigest(message.envelope, source);
192
+ const existing = await this.models.InboundHandoff.exact.findStoredOne({
193
+ transportDeliveryId,
194
+ });
195
+ if (existing) {
196
+ if (canonicalJson(existing.routingHandles) !== canonicalJson(routingHandles)
197
+ || canonicalJson(existing.message) !== canonicalJson(message)
198
+ || canonicalJson(existing.source) !== canonicalJson(source)
199
+ || existing.state === 'failed') {
200
+ throw new Error('CoreMail inbound handoff replay conflicts with persisted intent.');
201
+ }
202
+ if (existing.state === 'completed') {
203
+ return {
204
+ handoffId: existing.handoffId,
205
+ replayed: true,
206
+ };
207
+ }
208
+ const grant = await this.issueInboundGrant(existing);
209
+ return {
210
+ handoffId: existing.handoffId,
211
+ grant,
212
+ replayed: true,
213
+ };
214
+ }
215
+ const now = this.now();
216
+ for (const routingHandle of routingHandles) {
217
+ const handle = await this.models.RecipientHandle.exact.findStoredOne({
218
+ routingHandle,
219
+ state: 'issued',
220
+ expiresAt: { $gte: now },
221
+ });
222
+ if (!handle) {
223
+ throw new Error('CoreMail routing authority is unavailable.');
224
+ }
225
+ if (handle.envelopeDigest !== envelopeDigest) {
226
+ throw new Error('CoreMail routing authority is bound to another envelope.');
227
+ }
228
+ }
229
+ const handoffId = plugins.nodeCrypto.randomUUID();
230
+ const handoff = {
231
+ handoffId,
232
+ revision: 0,
233
+ transportDeliveryId,
234
+ routingHandles,
235
+ message,
236
+ source,
237
+ state: 'prepared',
238
+ objectKey: `inbound-mime/${handoffId}/${message.rawMime.sha256.slice(7)}`,
239
+ deliveryIds: [],
240
+ createdAt: now,
241
+ updatedAt: now,
242
+ };
243
+ let storedHandoff;
244
+ try {
245
+ const inserted = await this.models.InboundHandoff.exact.insert(handoff);
246
+ if (inserted.status === 'conflict') {
247
+ throw new Error('CoreMail inbound handoff identity conflict.');
248
+ }
249
+ storedHandoff = inserted.document;
250
+ }
251
+ catch (error) {
252
+ if (!isUniqueConflict(error)) {
253
+ throw error;
254
+ }
255
+ const concurrent = await this.models.InboundHandoff.exact.findStoredOne({
256
+ transportDeliveryId,
257
+ });
258
+ if (!concurrent
259
+ || canonicalJson(concurrent.routingHandles)
260
+ !== canonicalJson(routingHandles)
261
+ || canonicalJson(concurrent.message) !== canonicalJson(message)
262
+ || canonicalJson(concurrent.source) !== canonicalJson(source)
263
+ || concurrent.state === 'failed') {
264
+ throw new Error('CoreMail inbound handoff conflicts with persisted intent.');
265
+ }
266
+ if (concurrent.state === 'completed') {
267
+ return {
268
+ handoffId: concurrent.handoffId,
269
+ replayed: true,
270
+ };
271
+ }
272
+ const concurrentGrant = await this.issueInboundGrant(concurrent);
273
+ return {
274
+ handoffId: concurrent.handoffId,
275
+ grant: concurrentGrant,
276
+ replayed: true,
277
+ };
278
+ }
279
+ const grant = await this.issueInboundGrant(storedHandoff);
280
+ return { handoffId, grant, replayed: false };
281
+ }
282
+ async issueInboundGrant(handoffArg) {
283
+ if (handoffArg.state !== 'prepared' && handoffArg.state !== 'uploaded') {
284
+ throw new Error('CoreMail inbound handoff cannot issue an upload grant.');
285
+ }
286
+ const grant = await this.transfers.issueGrant({
287
+ authority: gatewayAuthority(this.serviceId),
288
+ purpose: 'inbound-mime-upload',
289
+ method: 'PUT',
290
+ expectedSha256: handoffArg.message.rawMime.sha256,
291
+ lengthBytes: handoffArg.message.rawMime.lengthBytes,
292
+ contentType: 'message/rfc822',
293
+ objectKey: handoffArg.objectKey,
294
+ });
295
+ const update = await this.models.InboundHandoff.exact.transition({
296
+ current: handoffArg,
297
+ change: (modelArg) => {
298
+ modelArg.grantId = grant.grantId;
299
+ modelArg.state = 'uploaded';
300
+ modelArg.updatedAt = this.now();
301
+ modelArg.revision += 1;
302
+ },
303
+ });
304
+ if (update.status !== 'transitioned') {
305
+ throw new Error('CoreMail inbound handoff upload fence changed.');
306
+ }
307
+ return grant;
308
+ }
309
+ async completeInboundHandoff(requestArg) {
310
+ const handoff = await this.models.InboundHandoff.exact.findStoredOne({
311
+ handoffId: requireCoreMailUuid(requestArg.handoffId, 'handoffId'),
312
+ });
313
+ if (!handoff || handoff.state === 'failed') {
314
+ throw new Error('CoreMail inbound handoff is unavailable.');
315
+ }
316
+ const sha256 = plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(requestArg.sha256);
317
+ if ((handoff.state !== 'uploaded' && handoff.state !== 'completed')
318
+ || handoff.message.rawMime.sha256 !== sha256
319
+ || handoff.message.rawMime.lengthBytes !== requestArg.lengthBytes) {
320
+ throw new Error('CoreMail inbound handoff completion is invalid.');
321
+ }
322
+ await this.transfers.assertConsumed({
323
+ grantId: requestArg.grantId,
324
+ authority: gatewayAuthority(this.serviceId),
325
+ purpose: 'inbound-mime-upload',
326
+ expectedSha256: handoff.message.rawMime.sha256,
327
+ lengthBytes: handoff.message.rawMime.lengthBytes,
328
+ objectKey: handoff.objectKey,
329
+ });
330
+ if (handoff.state === 'completed') {
331
+ return {
332
+ accepted: true,
333
+ deliveryIds: [...handoff.deliveryIds],
334
+ replayed: true,
335
+ };
336
+ }
337
+ const handles = [];
338
+ for (const routingHandle of handoff.routingHandles) {
339
+ const handle = await this.models.RecipientHandle.exact.findStoredOne({
340
+ routingHandle,
341
+ });
342
+ if (!handle
343
+ || (handle.state === 'consumed'
344
+ && handle.handoffId !== handoff.handoffId)
345
+ || (handle.state === 'issued'
346
+ && handle.expiresAt < this.now())
347
+ || handle.envelopeDigest !== createEnvelopeDigest(handoff.message.envelope, handoff.source)) {
348
+ throw new Error('CoreMail routing handle fence changed.');
349
+ }
350
+ handles.push(handle);
351
+ }
352
+ const grouped = new Map();
353
+ for (const handle of handles) {
354
+ const key = JSON.stringify([
355
+ handle.tenantId,
356
+ handle.serviceId,
357
+ handle.bindingId,
358
+ handle.bindingRevision,
359
+ ]);
360
+ const group = grouped.get(key) ?? [];
361
+ group.push(handle);
362
+ grouped.set(key, group);
363
+ }
364
+ const groups = [...grouped.values()];
365
+ const candidates = [];
366
+ for (const group of groups) {
367
+ const authority = group[0];
368
+ if (group.some((handleArg) => handleArg.maxPendingInbound !== authority.maxPendingInbound)) {
369
+ throw new Error('CoreMail routing handles disagree on pending quota.');
370
+ }
371
+ const quota = createCoreMailPendingQuotaDescriptor(authority);
372
+ await ensureCoreMailQuotaCounter(this.models, quota);
373
+ const receivedAt = this.now();
374
+ candidates.push({
375
+ deliveryId: plugins.nodeCrypto.randomUUID(),
376
+ tenantId: authority.tenantId,
377
+ serviceId: authority.serviceId,
378
+ bindingId: authority.bindingId,
379
+ bindingRevision: authority.bindingRevision,
380
+ revision: 0,
381
+ transportDeliveryId: handoff.transportDeliveryId,
382
+ state: 'pending',
383
+ envelope: {
384
+ mailFrom: handoff.message.envelope.mailFrom,
385
+ rcptTo: group.map((handleArg) => handleArg.recipient),
386
+ },
387
+ rawMimeSha256: handoff.message.rawMime.sha256,
388
+ rawMimeLengthBytes: handoff.message.rawMime.lengthBytes,
389
+ rawMimeObjectKey: handoff.objectKey,
390
+ receivedAt,
391
+ updatedAt: receivedAt,
392
+ });
393
+ }
394
+ try {
395
+ const deliveryIds = await withCoreMailTransaction(this.database, async (transactionArg) => {
396
+ const transactionHandoff = await this.models.InboundHandoff.exact.findStoredOne({
397
+ handoffId: handoff.handoffId,
398
+ state: 'uploaded',
399
+ revision: handoff.revision,
400
+ }, { session: transactionArg });
401
+ if (!transactionHandoff) {
402
+ throw new Error('CoreMail inbound handoff completion fence changed.');
403
+ }
404
+ const committedIds = [];
405
+ for (const [index, group] of groups.entries()) {
406
+ const authority = group[0];
407
+ const candidate = candidates[index];
408
+ const quota = createCoreMailPendingQuotaDescriptor(authority);
409
+ const existing = await this.models.InboundDelivery.exact.findStoredOne({
410
+ transportDeliveryId: handoff.transportDeliveryId,
411
+ bindingId: authority.bindingId,
412
+ bindingRevision: authority.bindingRevision,
413
+ }, { session: transactionArg });
414
+ if (!existing) {
415
+ await incrementCoreMailQuotaCounter(this.models, quota, authority.maxPendingInbound, candidate.receivedAt, transactionArg);
416
+ const inserted = await this.models.InboundDelivery.exact.insert(candidate, { session: transactionArg });
417
+ if (inserted.status === 'conflict') {
418
+ throw new Error('CoreMail inbound delivery identity conflict.');
419
+ }
420
+ }
421
+ for (const originalHandle of group) {
422
+ const handle = await this.models.RecipientHandle.exact.findStoredOne({ routingHandle: originalHandle.routingHandle }, { session: transactionArg });
423
+ if (!handle
424
+ || handle.tenantId !== authority.tenantId
425
+ || handle.serviceId !== authority.serviceId
426
+ || handle.bindingId !== authority.bindingId
427
+ || handle.bindingRevision !== authority.bindingRevision
428
+ || handle.maxPendingInbound !== authority.maxPendingInbound
429
+ || (handle.state === 'consumed'
430
+ && handle.handoffId !== handoff.handoffId)
431
+ || (handle.state === 'issued'
432
+ && handle.expiresAt < candidate.receivedAt)) {
433
+ throw new Error('CoreMail routing handle fence changed.');
434
+ }
435
+ if (handle.state === 'issued') {
436
+ const claim = await this.models.RecipientHandle.exact.transition({
437
+ current: handle,
438
+ change: (modelArg) => {
439
+ modelArg.state = 'consumed';
440
+ modelArg.handoffId = handoff.handoffId;
441
+ },
442
+ }, { session: transactionArg });
443
+ if (claim.status !== 'transitioned') {
444
+ throw new Error('CoreMail routing handle claim fence changed.');
445
+ }
446
+ }
447
+ }
448
+ committedIds.push(existing?.deliveryId ?? candidate.deliveryId);
449
+ }
450
+ committedIds.sort();
451
+ const completion = await this.models.InboundHandoff.exact.transition({
452
+ current: transactionHandoff,
453
+ change: (modelArg) => {
454
+ modelArg.state = 'completed';
455
+ modelArg.grantId = requestArg.grantId;
456
+ modelArg.deliveryIds = committedIds;
457
+ modelArg.completedAt = this.now();
458
+ modelArg.updatedAt = modelArg.completedAt;
459
+ modelArg.revision += 1;
460
+ },
461
+ }, { session: transactionArg });
462
+ if (completion.status !== 'transitioned') {
463
+ throw new Error('CoreMail inbound handoff completion fence changed.');
464
+ }
465
+ return committedIds;
466
+ });
467
+ return { accepted: true, deliveryIds, replayed: false };
468
+ }
469
+ catch (error) {
470
+ const replay = await this.models.InboundHandoff.exact.findStoredOne({
471
+ handoffId: handoff.handoffId,
472
+ state: 'completed',
473
+ });
474
+ if (replay) {
475
+ return {
476
+ accepted: true,
477
+ deliveryIds: [...replay.deliveryIds],
478
+ replayed: true,
479
+ };
480
+ }
481
+ throw error;
482
+ }
483
+ }
484
+ async listDeliveries(sessionArg, requestArg) {
485
+ if (!Number.isSafeInteger(requestArg.limit)
486
+ || requestArg.limit < 1
487
+ || requestArg.limit > listLimitMaximum
488
+ || (requestArg.cursor !== undefined
489
+ && (typeof requestArg.cursor !== 'string'
490
+ || requestArg.cursor.length >
491
+ plugins.serveZoneInterfaces.data.coreMailLimits.cursorBytes))) {
492
+ throw new Error('CoreMail inbound list window is invalid.');
493
+ }
494
+ const authority = {
495
+ tenantId: sessionArg.tenantId,
496
+ serviceId: sessionArg.serviceId,
497
+ bindingId: sessionArg.bindingId,
498
+ bindingRevision: sessionArg.bindingRevision,
499
+ };
500
+ const now = this.now();
501
+ const desiredState = await this.getDesiredState();
502
+ if (!desiredState) {
503
+ throw new Error('CoreMail desired state is unavailable.');
504
+ }
505
+ const position = requestArg.cursor
506
+ ? this.cursorCodec.decode(requestArg.cursor, authority, now, desiredState.cursorKeys)
507
+ : null;
508
+ const snapshotAt = position?.snapshotAt ?? now;
509
+ const deliveries = await this.models.InboundDelivery.exact.findStored({
510
+ filter: {
511
+ ...workloadFilter(sessionArg, undefined),
512
+ receivedAt: { $lt: snapshotAt },
513
+ ...(position
514
+ ? {
515
+ $or: [{
516
+ receivedAt: { $gt: position.receivedAt },
517
+ }, {
518
+ receivedAt: position.receivedAt,
519
+ deliveryId: { $gt: position.deliveryId },
520
+ }],
521
+ }
522
+ : {}),
523
+ },
524
+ sort: { receivedAt: 1, deliveryId: 1 },
525
+ limit: requestArg.limit + 1,
526
+ });
527
+ const page = [];
528
+ for (const delivery of deliveries.slice(0, requestArg.limit)) {
529
+ const publicDelivery = toPublicDelivery(delivery);
530
+ const cursor = this.cursorCodec.encode(authority, {
531
+ snapshotAt,
532
+ receivedAt: delivery.receivedAt,
533
+ deliveryId: delivery.deliveryId,
534
+ }, desiredState.cursorKeys);
535
+ const candidate = {
536
+ deliveries: [...page, publicDelivery],
537
+ nextCursor: cursor,
538
+ };
539
+ if (Buffer.byteLength(JSON.stringify(candidate), 'utf8')
540
+ > plugins.serveZoneInterfaces.data.coreMailLimits.inboundPageBytes) {
541
+ break;
542
+ }
543
+ page.push(publicDelivery);
544
+ }
545
+ if (page.length === 0 && deliveries.length > 0) {
546
+ throw new Error('CoreMail inbound delivery exceeds the page byte budget.');
547
+ }
548
+ const hasMore = page.length < deliveries.length;
549
+ const last = page.at(-1);
550
+ const response = {
551
+ deliveries: page,
552
+ ...(hasMore && last
553
+ ? {
554
+ nextCursor: this.cursorCodec.encode(authority, {
555
+ snapshotAt,
556
+ receivedAt: last.receivedAt,
557
+ deliveryId: last.deliveryId,
558
+ }, desiredState.cursorKeys),
559
+ }
560
+ : {}),
561
+ };
562
+ return plugins.serveZoneInterfaces.data
563
+ .normalizeCoreMailInboundDeliveryPage(response);
564
+ }
565
+ async prepareFetch(sessionArg, requestArg) {
566
+ const delivery = await this.requireDelivery(sessionArg, requestArg.deliveryId);
567
+ if (delivery.state === 'acknowledged') {
568
+ throw new Error('CoreMail inbound delivery is already acknowledged.');
569
+ }
570
+ const grant = await this.transfers.issueGrant({
571
+ authority: workloadAuthority(sessionArg),
572
+ purpose: 'inbound-mime-download',
573
+ method: 'GET',
574
+ expectedSha256: delivery.rawMimeSha256,
575
+ lengthBytes: delivery.rawMimeLengthBytes,
576
+ contentType: 'message/rfc822',
577
+ objectKey: delivery.rawMimeObjectKey,
578
+ });
579
+ const update = await this.models.InboundDelivery.exact.transition({
580
+ current: delivery,
581
+ change: (modelArg) => {
582
+ modelArg.state = 'fetching';
583
+ modelArg.fetchGrantId = grant.grantId;
584
+ modelArg.updatedAt = this.now();
585
+ modelArg.revision += 1;
586
+ },
587
+ });
588
+ if (update.status !== 'transitioned') {
589
+ throw new Error('CoreMail inbound fetch preparation fence changed.');
590
+ }
591
+ return {
592
+ grant: grant,
593
+ };
594
+ }
595
+ async completeFetch(sessionArg, requestArg) {
596
+ const delivery = await this.requireDelivery(sessionArg, requestArg.deliveryId);
597
+ const sha256 = plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(requestArg.sha256);
598
+ if ((delivery.state !== 'fetching' && delivery.state !== 'fetched')
599
+ || delivery.rawMimeSha256 !== sha256
600
+ || delivery.rawMimeLengthBytes !== requestArg.lengthBytes) {
601
+ throw new Error('CoreMail inbound fetch completion is invalid.');
602
+ }
603
+ await this.transfers.assertConsumed({
604
+ grantId: requestArg.grantId,
605
+ authority: workloadAuthority(sessionArg),
606
+ purpose: 'inbound-mime-download',
607
+ expectedSha256: delivery.rawMimeSha256,
608
+ lengthBytes: delivery.rawMimeLengthBytes,
609
+ objectKey: delivery.rawMimeObjectKey,
610
+ });
611
+ if (delivery.state === 'fetched') {
612
+ return { delivery: toPublicDelivery(delivery) };
613
+ }
614
+ const updatedAt = this.now();
615
+ const update = await this.models.InboundDelivery.exact.transition({
616
+ current: delivery,
617
+ change: (modelArg) => {
618
+ modelArg.state = 'fetched';
619
+ modelArg.fetchGrantId = requestArg.grantId;
620
+ modelArg.updatedAt = updatedAt;
621
+ modelArg.revision += 1;
622
+ },
623
+ });
624
+ if (update.status !== 'transitioned') {
625
+ throw new Error('CoreMail inbound fetch completion fence changed.');
626
+ }
627
+ return {
628
+ delivery: toPublicDelivery(update.document),
629
+ };
630
+ }
631
+ async acknowledge(sessionArg, requestArg) {
632
+ if (requestArg.outcome !== 'processed' && requestArg.outcome !== 'discarded') {
633
+ throw new Error('CoreMail inbound acknowledgement outcome is invalid.');
634
+ }
635
+ const delivery = await this.requireDelivery(sessionArg, requestArg.deliveryId);
636
+ if (delivery.state === 'acknowledged') {
637
+ if (delivery.acknowledgedOutcome !== requestArg.outcome) {
638
+ throw new Error('CoreMail inbound acknowledgement conflicts with persisted intent.');
639
+ }
640
+ return { delivery: toPublicDelivery(delivery), replayed: true };
641
+ }
642
+ if (delivery.state !== 'fetched') {
643
+ throw new Error('CoreMail inbound delivery must be fetched before acknowledgement.');
644
+ }
645
+ const updatedAt = this.now();
646
+ const quota = createCoreMailPendingQuotaDescriptor({
647
+ tenantId: sessionArg.tenantId,
648
+ serviceId: sessionArg.serviceId,
649
+ bindingId: sessionArg.bindingId,
650
+ bindingRevision: sessionArg.bindingRevision,
651
+ });
652
+ await ensureCoreMailQuotaCounter(this.models, quota);
653
+ const transactionResult = await withCoreMailTransaction(this.database, async (transactionArg) => {
654
+ const current = await this.models.InboundDelivery.exact.findStoredOne(workloadFilter(sessionArg, requestArg.deliveryId), { session: transactionArg });
655
+ if (!current) {
656
+ throw new Error('CoreMail inbound delivery is unavailable.');
657
+ }
658
+ if (current.state === 'acknowledged') {
659
+ if (current.acknowledgedOutcome !== requestArg.outcome) {
660
+ throw new Error('CoreMail inbound acknowledgement conflicts with persisted intent.');
661
+ }
662
+ return { replayed: true };
663
+ }
664
+ if (current.state !== 'fetched') {
665
+ throw new Error('CoreMail inbound delivery must be fetched before acknowledgement.');
666
+ }
667
+ await decrementCoreMailQuotaCounter(this.models, quota, updatedAt, transactionArg);
668
+ const update = await this.models.InboundDelivery.exact.transition({
669
+ current,
670
+ change: (modelArg) => {
671
+ modelArg.state = 'acknowledged';
672
+ modelArg.acknowledgedOutcome = requestArg.outcome;
673
+ modelArg.updatedAt = updatedAt;
674
+ modelArg.revision += 1;
675
+ },
676
+ }, { session: transactionArg });
677
+ if (update.status !== 'transitioned') {
678
+ throw new Error('CoreMail inbound acknowledgement fence changed.');
679
+ }
680
+ return { replayed: false };
681
+ });
682
+ const committed = await this.requireDelivery(sessionArg, requestArg.deliveryId);
683
+ if (committed.state !== 'acknowledged'
684
+ || committed.acknowledgedOutcome !== requestArg.outcome) {
685
+ throw new Error('CoreMail committed inbound acknowledgement is unavailable.');
686
+ }
687
+ return {
688
+ delivery: toPublicDelivery(committed),
689
+ replayed: transactionResult.replayed,
690
+ };
691
+ }
692
+ async requireDelivery(sessionArg, deliveryIdArg) {
693
+ const delivery = await this.models.InboundDelivery.exact.findStoredOne({
694
+ ...workloadFilter(sessionArg, deliveryIdArg),
695
+ });
696
+ if (!delivery) {
697
+ throw new Error('CoreMail inbound delivery is unavailable.');
698
+ }
699
+ return delivery;
700
+ }
701
+ }
702
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5pbmJvdW5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5pbmJvdW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBd0IsTUFBTSxxQkFBcUIsQ0FBQztBQUMzRCxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFlBQVksR0FDYixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2hFLE9BQU8sRUFDTCwrQkFBK0IsRUFDL0IseUJBQXlCLEVBQ3pCLCtCQUErQixFQUMvQiwrQkFBK0IsR0FDaEMsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRSxPQUFPLEVBQ0wsb0NBQW9DLEVBQ3BDLDZCQUE2QixFQUM3QiwwQkFBMEIsRUFDMUIsNkJBQTZCLEVBQzdCLHVCQUF1QixHQUN4QixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsbUJBQW1CLEdBQ3BCLE1BQU0seUJBQXlCLENBQUM7QUFvQmpDLE1BQU0sa0JBQWtCLEdBQ3RCLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGtCQUFrQixDQUFDO0FBQ3JFLE1BQU0sZ0JBQWdCLEdBQ3BCLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQztBQUVsRSxNQUFNLGdCQUFnQixHQUFHLENBQUMsWUFBb0IsRUFBc0IsRUFBRSxDQUFDLENBQUM7SUFDdEUsSUFBSSxFQUFFLFNBQVM7SUFDZixRQUFRLEVBQUUsR0FBRztJQUNiLFNBQVMsRUFBRSxZQUFZO0lBQ3ZCLFNBQVMsRUFBRSxHQUFHO0NBQ2YsQ0FBQyxDQUFDO0FBRUgsTUFBTSxpQkFBaUIs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