@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.
- package/.smartconfig.json +50 -0
- package/changelog.md +10 -0
- package/cli.js +4 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.auth.d.ts +45 -0
- package/dist_ts/classes.auth.js +204 -0
- package/dist_ts/classes.config.d.ts +2 -0
- package/dist_ts/classes.config.js +72 -0
- package/dist_ts/classes.coremail.d.ts +41 -0
- package/dist_ts/classes.coremail.js +155 -0
- package/dist_ts/classes.desiredstate.d.ts +40 -0
- package/dist_ts/classes.desiredstate.js +382 -0
- package/dist_ts/classes.gateway.d.ts +62 -0
- package/dist_ts/classes.gateway.js +669 -0
- package/dist_ts/classes.inbound.d.ts +49 -0
- package/dist_ts/classes.inbound.js +702 -0
- package/dist_ts/classes.maintenance.d.ts +16 -0
- package/dist_ts/classes.maintenance.js +339 -0
- package/dist_ts/classes.models.d.ts +161 -0
- package/dist_ts/classes.models.js +595 -0
- package/dist_ts/classes.server.d.ts +40 -0
- package/dist_ts/classes.server.js +309 -0
- package/dist_ts/classes.storage.d.ts +32 -0
- package/dist_ts/classes.storage.js +317 -0
- package/dist_ts/classes.submissions.d.ts +33 -0
- package/dist_ts/classes.submissions.js +385 -0
- package/dist_ts/classes.transfer.d.ts +41 -0
- package/dist_ts/classes.transfer.js +289 -0
- package/dist_ts/coremail.cursor.d.ts +20 -0
- package/dist_ts/coremail.cursor.js +191 -0
- package/dist_ts/coremail.log.d.ts +3 -0
- package/dist_ts/coremail.log.js +11 -0
- package/dist_ts/coremail.mime.d.ts +8 -0
- package/dist_ts/coremail.mime.js +63 -0
- package/dist_ts/coremail.persistence.d.ts +148 -0
- package/dist_ts/coremail.persistence.js +695 -0
- package/dist_ts/coremail.quota.d.ts +29 -0
- package/dist_ts/coremail.quota.js +149 -0
- package/dist_ts/coremail.selectors.d.ts +3 -0
- package/dist_ts/coremail.selectors.js +21 -0
- package/dist_ts/coremail.validation.d.ts +9 -0
- package/dist_ts/coremail.validation.js +325 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +39 -0
- package/dist_ts/interfaces.d.ts +92 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +11 -0
- package/dist_ts/plugins.js +12 -0
- package/license.md +19 -0
- package/package.json +48 -0
- package/readme.md +199 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.auth.ts +321 -0
- package/ts/classes.config.ts +104 -0
- package/ts/classes.coremail.ts +249 -0
- package/ts/classes.desiredstate.ts +508 -0
- package/ts/classes.gateway.ts +811 -0
- package/ts/classes.inbound.ts +898 -0
- package/ts/classes.maintenance.ts +335 -0
- package/ts/classes.models.ts +530 -0
- package/ts/classes.server.ts +444 -0
- package/ts/classes.storage.ts +448 -0
- package/ts/classes.submissions.ts +554 -0
- package/ts/classes.transfer.ts +379 -0
- package/ts/coremail.cursor.ts +328 -0
- package/ts/coremail.log.ts +21 -0
- package/ts/coremail.mime.ts +94 -0
- package/ts/coremail.persistence.ts +1156 -0
- package/ts/coremail.quota.ts +214 -0
- package/ts/coremail.selectors.ts +35 -0
- package/ts/coremail.validation.ts +446 -0
- package/ts/index.ts +38 -0
- package/ts/interfaces.ts +109 -0
- package/ts/plugins.ts +11 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import {} from './classes.models.js';
|
|
3
|
+
import { CoreMailStorage, createSha256 } from './classes.storage.js';
|
|
4
|
+
import { CoreMailTransferService } from './classes.transfer.js';
|
|
5
|
+
import { createCoreMailSubmissionDigest, normalizeCoreMailOutboundMessage, } from './coremail.validation.js';
|
|
6
|
+
import { createCoreMailMime } from './coremail.mime.js';
|
|
7
|
+
import { createCoreMailOutboundQuotaDescriptors, ensureCoreMailQuotaCounter, incrementCoreMailQuotaCounter, withCoreMailTransaction, } from './coremail.quota.js';
|
|
8
|
+
import { requireCoreMailIdentifier, requireCoreMailUuid, } from './coremail.selectors.js';
|
|
9
|
+
const maximumPartBytes = plugins.serveZoneInterfaces.data.coreMailLimits.attachmentBytes;
|
|
10
|
+
const authorityFilter = (sessionArg, submissionIdArg) => ({
|
|
11
|
+
tenantId: requireCoreMailIdentifier(sessionArg.tenantId, 'session.tenantId'),
|
|
12
|
+
serviceId: requireCoreMailIdentifier(sessionArg.serviceId, 'session.serviceId'),
|
|
13
|
+
bindingId: requireCoreMailIdentifier(sessionArg.bindingId, 'session.bindingId'),
|
|
14
|
+
bindingRevision: sessionArg.bindingRevision,
|
|
15
|
+
...(submissionIdArg === undefined
|
|
16
|
+
? {}
|
|
17
|
+
: { submissionId: requireCoreMailUuid(submissionIdArg, 'submissionId') }),
|
|
18
|
+
});
|
|
19
|
+
const workloadAuthority = (sessionArg) => ({
|
|
20
|
+
kind: 'workload',
|
|
21
|
+
tenantId: sessionArg.tenantId,
|
|
22
|
+
serviceId: sessionArg.serviceId,
|
|
23
|
+
bindingId: sessionArg.bindingId,
|
|
24
|
+
});
|
|
25
|
+
const toPublicSubmission = (submissionArg) => plugins.serveZoneInterfaces.data.normalizeCoreMailSubmission({
|
|
26
|
+
submissionId: submissionArg.submissionId,
|
|
27
|
+
idempotencyKey: submissionArg.idempotencyKey,
|
|
28
|
+
submissionDigest: submissionArg.submissionDigest,
|
|
29
|
+
state: submissionArg.state,
|
|
30
|
+
parts: submissionArg.parts.map((partArg) => ({
|
|
31
|
+
partId: partArg.partId,
|
|
32
|
+
state: partArg.state,
|
|
33
|
+
sha256: partArg.sha256,
|
|
34
|
+
lengthBytes: partArg.lengthBytes,
|
|
35
|
+
})),
|
|
36
|
+
...(submissionArg.transportMessageId
|
|
37
|
+
? { transportMessageId: submissionArg.transportMessageId }
|
|
38
|
+
: {}),
|
|
39
|
+
attempts: submissionArg.attempts,
|
|
40
|
+
...(submissionArg.nextAttemptAt === undefined
|
|
41
|
+
|| submissionArg.state !== 'deferred'
|
|
42
|
+
? {}
|
|
43
|
+
: { nextAttemptAt: submissionArg.nextAttemptAt }),
|
|
44
|
+
...(submissionArg.error === undefined ? {} : { error: submissionArg.error }),
|
|
45
|
+
...(submissionArg.acceptedAt === undefined
|
|
46
|
+
? {}
|
|
47
|
+
: { acceptedAt: submissionArg.acceptedAt }),
|
|
48
|
+
...(submissionArg.deliveredAt === undefined
|
|
49
|
+
? {}
|
|
50
|
+
: { deliveredAt: submissionArg.deliveredAt }),
|
|
51
|
+
...(submissionArg.terminalAt === undefined
|
|
52
|
+
? {}
|
|
53
|
+
: { terminalAt: submissionArg.terminalAt }),
|
|
54
|
+
createdAt: submissionArg.createdAt,
|
|
55
|
+
updatedAt: submissionArg.updatedAt,
|
|
56
|
+
});
|
|
57
|
+
const isUniqueConflict = (errorArg) => errorArg instanceof plugins.smartdata.SmartdataExactPersistenceError
|
|
58
|
+
&& errorArg.code === 'unique_conflict';
|
|
59
|
+
export class CoreMailSubmissionService {
|
|
60
|
+
database;
|
|
61
|
+
models;
|
|
62
|
+
storage;
|
|
63
|
+
transfers;
|
|
64
|
+
now;
|
|
65
|
+
constructor(database, models, storage, transfers, now = Date.now) {
|
|
66
|
+
this.database = database;
|
|
67
|
+
this.models = models;
|
|
68
|
+
this.storage = storage;
|
|
69
|
+
this.transfers = transfers;
|
|
70
|
+
this.now = now;
|
|
71
|
+
}
|
|
72
|
+
async prepare(sessionArg, bindingArg, requestArg) {
|
|
73
|
+
const message = normalizeCoreMailOutboundMessage(requestArg.message, bindingArg);
|
|
74
|
+
const submissionDigest = createCoreMailSubmissionDigest(requestArg.idempotencyKey, message);
|
|
75
|
+
const replay = await this.models.Submission.exact.findStoredOne({
|
|
76
|
+
...authorityFilter(sessionArg, undefined),
|
|
77
|
+
idempotencyKey: requestArg.idempotencyKey,
|
|
78
|
+
});
|
|
79
|
+
if (replay) {
|
|
80
|
+
if (replay.submissionDigest !== submissionDigest) {
|
|
81
|
+
throw new Error('CoreMail idempotency key conflicts with persisted intent.');
|
|
82
|
+
}
|
|
83
|
+
return { submission: toPublicSubmission(replay), replayed: true };
|
|
84
|
+
}
|
|
85
|
+
const submissionId = plugins.nodeCrypto.randomUUID();
|
|
86
|
+
const createdAt = this.now();
|
|
87
|
+
const parts = message.parts.map((partArg) => ({
|
|
88
|
+
...partArg,
|
|
89
|
+
objectKey: `outbound-parts/${submissionId}/${plugins.nodeCrypto.randomUUID()}`,
|
|
90
|
+
state: 'missing',
|
|
91
|
+
}));
|
|
92
|
+
const submission = {
|
|
93
|
+
submissionId,
|
|
94
|
+
tenantId: sessionArg.tenantId,
|
|
95
|
+
serviceId: sessionArg.serviceId,
|
|
96
|
+
bindingId: sessionArg.bindingId,
|
|
97
|
+
bindingRevision: sessionArg.bindingRevision,
|
|
98
|
+
revision: 0,
|
|
99
|
+
idempotencyKey: requestArg.idempotencyKey,
|
|
100
|
+
submissionDigest,
|
|
101
|
+
state: 'preparing',
|
|
102
|
+
message,
|
|
103
|
+
parts,
|
|
104
|
+
attempts: 0,
|
|
105
|
+
createdAt,
|
|
106
|
+
updatedAt: createdAt,
|
|
107
|
+
};
|
|
108
|
+
const quotaNow = this.now();
|
|
109
|
+
const quota = createCoreMailOutboundQuotaDescriptors({
|
|
110
|
+
tenantId: sessionArg.tenantId,
|
|
111
|
+
serviceId: sessionArg.serviceId,
|
|
112
|
+
bindingId: sessionArg.bindingId,
|
|
113
|
+
bindingRevision: sessionArg.bindingRevision,
|
|
114
|
+
}, quotaNow);
|
|
115
|
+
await ensureCoreMailQuotaCounter(this.models, quota.minute);
|
|
116
|
+
await ensureCoreMailQuotaCounter(this.models, quota.day);
|
|
117
|
+
try {
|
|
118
|
+
const transactionResult = await withCoreMailTransaction(this.database, async (transactionArg) => {
|
|
119
|
+
const transactionReplay = await this.models.Submission.exact.findStoredOne({
|
|
120
|
+
...authorityFilter(sessionArg, undefined),
|
|
121
|
+
idempotencyKey: requestArg.idempotencyKey,
|
|
122
|
+
}, { session: transactionArg });
|
|
123
|
+
if (transactionReplay) {
|
|
124
|
+
if (transactionReplay.submissionDigest !== submissionDigest) {
|
|
125
|
+
throw new Error('CoreMail idempotency key conflicts with persisted intent.');
|
|
126
|
+
}
|
|
127
|
+
return { submissionId: transactionReplay.submissionId, replayed: true };
|
|
128
|
+
}
|
|
129
|
+
await incrementCoreMailQuotaCounter(this.models, quota.day, bindingArg.limits.messagesPerDay, quotaNow, transactionArg, quota.dayRetryAfterMs);
|
|
130
|
+
await incrementCoreMailQuotaCounter(this.models, quota.minute, bindingArg.limits.messagesPerMinute, quotaNow, transactionArg, quota.minuteRetryAfterMs);
|
|
131
|
+
const inserted = await this.models.Submission.exact.insert(submission, { session: transactionArg });
|
|
132
|
+
if (inserted.status === 'conflict') {
|
|
133
|
+
throw new Error('CoreMail submission identity conflicts with persisted intent.');
|
|
134
|
+
}
|
|
135
|
+
return { submissionId, replayed: inserted.status === 'already_committed' };
|
|
136
|
+
});
|
|
137
|
+
const committed = await this.models.Submission.exact.findStoredOne({
|
|
138
|
+
...authorityFilter(sessionArg, transactionResult.submissionId),
|
|
139
|
+
});
|
|
140
|
+
if (!committed || committed.submissionDigest !== submissionDigest) {
|
|
141
|
+
throw new Error('CoreMail committed submission is unavailable.');
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
submission: toPublicSubmission(committed),
|
|
145
|
+
replayed: transactionResult.replayed,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (!isUniqueConflict(error)) {
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
const concurrent = await this.models.Submission.exact.findStoredOne({
|
|
153
|
+
...authorityFilter(sessionArg, undefined),
|
|
154
|
+
idempotencyKey: requestArg.idempotencyKey,
|
|
155
|
+
});
|
|
156
|
+
if (!concurrent || concurrent.submissionDigest !== submissionDigest) {
|
|
157
|
+
throw new Error('CoreMail idempotency key conflicts with persisted intent.');
|
|
158
|
+
}
|
|
159
|
+
return { submission: toPublicSubmission(concurrent), replayed: true };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async preparePartUpload(sessionArg, requestArg) {
|
|
163
|
+
const submission = await this.requireSubmission(sessionArg, requestArg.submissionId);
|
|
164
|
+
if (submission.state !== 'preparing'
|
|
165
|
+
&& submission.state !== 'uploading'
|
|
166
|
+
&& submission.state !== 'ready') {
|
|
167
|
+
throw new Error('CoreMail submission no longer accepts part uploads.');
|
|
168
|
+
}
|
|
169
|
+
const partIndex = submission.parts.findIndex((partArg) => partArg.partId === requireCoreMailIdentifier(requestArg.partId, 'partId'));
|
|
170
|
+
if (partIndex < 0) {
|
|
171
|
+
throw new Error('CoreMail submission part is unavailable.');
|
|
172
|
+
}
|
|
173
|
+
const part = submission.parts[partIndex];
|
|
174
|
+
if (part.state === 'complete') {
|
|
175
|
+
throw new Error('CoreMail submission part is already complete.');
|
|
176
|
+
}
|
|
177
|
+
const grant = await this.transfers.issueGrant({
|
|
178
|
+
authority: workloadAuthority(sessionArg),
|
|
179
|
+
purpose: 'outbound-part-upload',
|
|
180
|
+
method: 'PUT',
|
|
181
|
+
expectedSha256: part.sha256,
|
|
182
|
+
lengthBytes: part.lengthBytes,
|
|
183
|
+
contentType: part.contentType,
|
|
184
|
+
objectKey: part.objectKey,
|
|
185
|
+
});
|
|
186
|
+
const parts = submission.parts.map((partArg, indexArg) => indexArg === partIndex
|
|
187
|
+
? { ...partArg, state: 'uploading', grantId: grant.grantId }
|
|
188
|
+
: partArg);
|
|
189
|
+
const updatedAt = this.now();
|
|
190
|
+
const update = await this.models.Submission.exact.transition({
|
|
191
|
+
current: submission,
|
|
192
|
+
change: (modelArg) => {
|
|
193
|
+
modelArg.parts = parts;
|
|
194
|
+
modelArg.state = 'uploading';
|
|
195
|
+
modelArg.updatedAt = updatedAt;
|
|
196
|
+
modelArg.revision += 1;
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
if (update.status !== 'transitioned') {
|
|
200
|
+
throw new Error('CoreMail submission part upload fence changed.');
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
grant: grant,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async completePartUpload(sessionArg, requestArg) {
|
|
207
|
+
const submission = await this.requireSubmission(sessionArg, requestArg.submissionId);
|
|
208
|
+
const partIndex = submission.parts.findIndex((partArg) => partArg.partId === requireCoreMailIdentifier(requestArg.partId, 'partId'));
|
|
209
|
+
if (partIndex < 0) {
|
|
210
|
+
throw new Error('CoreMail submission part is unavailable.');
|
|
211
|
+
}
|
|
212
|
+
const part = submission.parts[partIndex];
|
|
213
|
+
const sha256 = plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(requestArg.sha256);
|
|
214
|
+
if ((part.state !== 'uploading' && part.state !== 'complete')
|
|
215
|
+
|| part.sha256 !== sha256
|
|
216
|
+
|| part.lengthBytes !== requestArg.lengthBytes) {
|
|
217
|
+
throw new Error('CoreMail submission part completion is invalid.');
|
|
218
|
+
}
|
|
219
|
+
await this.transfers.assertConsumed({
|
|
220
|
+
grantId: requestArg.grantId,
|
|
221
|
+
authority: workloadAuthority(sessionArg),
|
|
222
|
+
purpose: 'outbound-part-upload',
|
|
223
|
+
expectedSha256: part.sha256,
|
|
224
|
+
lengthBytes: part.lengthBytes,
|
|
225
|
+
objectKey: part.objectKey,
|
|
226
|
+
});
|
|
227
|
+
if (part.state === 'complete') {
|
|
228
|
+
return { submission: toPublicSubmission(submission) };
|
|
229
|
+
}
|
|
230
|
+
const parts = submission.parts.map((partArg, indexArg) => indexArg === partIndex
|
|
231
|
+
? {
|
|
232
|
+
...partArg,
|
|
233
|
+
state: 'complete',
|
|
234
|
+
grantId: requestArg.grantId,
|
|
235
|
+
}
|
|
236
|
+
: partArg);
|
|
237
|
+
const allComplete = parts.every((partArg) => partArg.state === 'complete');
|
|
238
|
+
const updatedAt = this.now();
|
|
239
|
+
const update = await this.models.Submission.exact.transition({
|
|
240
|
+
current: submission,
|
|
241
|
+
change: (modelArg) => {
|
|
242
|
+
modelArg.parts = parts;
|
|
243
|
+
modelArg.state = allComplete ? 'ready' : 'uploading';
|
|
244
|
+
modelArg.updatedAt = updatedAt;
|
|
245
|
+
modelArg.revision += 1;
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
if (update.status !== 'transitioned') {
|
|
249
|
+
throw new Error('CoreMail submission part completion fence changed.');
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
submission: toPublicSubmission(update.document),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
async finalize(sessionArg, requestArg) {
|
|
256
|
+
const submission = await this.requireSubmission(sessionArg, requestArg.submissionId);
|
|
257
|
+
if (submission.state === 'accepted'
|
|
258
|
+
|| submission.state === 'queued'
|
|
259
|
+
|| submission.state === 'delivering'
|
|
260
|
+
|| submission.state === 'delivered'
|
|
261
|
+
|| submission.state === 'deferred'
|
|
262
|
+
|| submission.state === 'failed'
|
|
263
|
+
|| submission.state === 'deadLettered') {
|
|
264
|
+
return { submission: toPublicSubmission(submission) };
|
|
265
|
+
}
|
|
266
|
+
if (submission.state !== 'ready'
|
|
267
|
+
|| !submission.parts.every((partArg) => partArg.state === 'complete')) {
|
|
268
|
+
throw new Error('CoreMail submission is not ready for finalization.');
|
|
269
|
+
}
|
|
270
|
+
if (submission.mimeObjectKey
|
|
271
|
+
&& submission.mimeSha256
|
|
272
|
+
&& submission.mimeLengthBytes !== undefined
|
|
273
|
+
&& submission.mimePublishedAt !== undefined
|
|
274
|
+
&& (submission.workerRetryAt !== undefined
|
|
275
|
+
|| (submission.leaseOwnerTaskId !== undefined
|
|
276
|
+
&& submission.leaseOwnerTaskId !== 'submission-finalizer'
|
|
277
|
+
&& submission.leaseExpiresAt !== undefined
|
|
278
|
+
&& submission.leaseExpiresAt > this.now()))) {
|
|
279
|
+
return { submission: toPublicSubmission(submission) };
|
|
280
|
+
}
|
|
281
|
+
const content = await Promise.all(submission.parts.map(async (partArg) => ({
|
|
282
|
+
descriptor: partArg,
|
|
283
|
+
bytes: await this.storage.getVerifiedBytes(partArg.objectKey, partArg.lengthBytes, partArg.sha256, maximumPartBytes),
|
|
284
|
+
})));
|
|
285
|
+
const mimeBytes = createCoreMailMime(submission.submissionId, submission.submissionDigest, submission.createdAt, submission.message, content);
|
|
286
|
+
const mimeObjectKey = `outbound-mime/${submission.submissionId}/${submission.submissionDigest.slice(7)}`;
|
|
287
|
+
const mimeSha256 = createSha256(mimeBytes);
|
|
288
|
+
const mimeLengthBytes = mimeBytes.byteLength;
|
|
289
|
+
if (mimeLengthBytes > plugins.serveZoneInterfaces.data.coreMailLimits.serializedMimeBytes) {
|
|
290
|
+
throw new Error('CoreMail serialized MIME exceeds its byte budget.');
|
|
291
|
+
}
|
|
292
|
+
if (submission.mimeObjectKey !== undefined
|
|
293
|
+
&& (submission.mimeObjectKey !== mimeObjectKey
|
|
294
|
+
|| submission.mimeSha256 !== mimeSha256
|
|
295
|
+
|| submission.mimeLengthBytes !== mimeLengthBytes)) {
|
|
296
|
+
throw new Error('CoreMail submission MIME ownership conflicts.');
|
|
297
|
+
}
|
|
298
|
+
if (submission.mimeObjectKey === mimeObjectKey
|
|
299
|
+
&& submission.leaseExpiresAt !== undefined
|
|
300
|
+
&& submission.leaseExpiresAt > this.now()) {
|
|
301
|
+
if (submission.leaseOwnerTaskId !== 'submission-finalizer') {
|
|
302
|
+
return { submission: toPublicSubmission(submission) };
|
|
303
|
+
}
|
|
304
|
+
throw new Error('CoreMail submission finalization is already in progress.');
|
|
305
|
+
}
|
|
306
|
+
const leaseToken = plugins.nodeCrypto.randomUUID();
|
|
307
|
+
const claimAt = this.now();
|
|
308
|
+
const claim = await this.models.Submission.exact.transition({
|
|
309
|
+
current: submission,
|
|
310
|
+
change: (modelArg) => {
|
|
311
|
+
modelArg.mimeObjectKey = mimeObjectKey;
|
|
312
|
+
modelArg.mimeSha256 = mimeSha256;
|
|
313
|
+
modelArg.mimeLengthBytes = mimeLengthBytes;
|
|
314
|
+
modelArg.leaseOwnerTaskId = 'submission-finalizer';
|
|
315
|
+
modelArg.leaseToken = leaseToken;
|
|
316
|
+
modelArg.leaseExpiresAt = claimAt
|
|
317
|
+
+ plugins.serveZoneInterfaces.data.coreMailLimits.transferOverallTimeoutMs
|
|
318
|
+
+ 2 * 60_000;
|
|
319
|
+
modelArg.updatedAt = claimAt;
|
|
320
|
+
modelArg.revision += 1;
|
|
321
|
+
delete modelArg.mimePublishedAt;
|
|
322
|
+
delete modelArg.workerRetryAt;
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
if (claim.status !== 'transitioned') {
|
|
326
|
+
const replay = await this.requireSubmission(sessionArg, submission.submissionId);
|
|
327
|
+
if (replay.submissionDigest === submission.submissionDigest
|
|
328
|
+
&& replay.mimeObjectKey === mimeObjectKey
|
|
329
|
+
&& replay.mimeSha256 === mimeSha256
|
|
330
|
+
&& replay.mimeLengthBytes === mimeLengthBytes
|
|
331
|
+
&& (replay.workerRetryAt !== undefined
|
|
332
|
+
|| replay.leaseOwnerTaskId !== 'submission-finalizer')) {
|
|
333
|
+
return { submission: toPublicSubmission(replay) };
|
|
334
|
+
}
|
|
335
|
+
throw new Error('CoreMail submission finalization fence changed.');
|
|
336
|
+
}
|
|
337
|
+
const mime = await this.storage.putBytesExact(mimeObjectKey, mimeBytes, 'message/rfc822', plugins.serveZoneInterfaces.data.coreMailLimits.serializedMimeBytes, AbortSignal.timeout(plugins.serveZoneInterfaces.data.coreMailLimits.transferOverallTimeoutMs));
|
|
338
|
+
if (mime.sha256 !== mimeSha256 || mime.lengthBytes !== mimeLengthBytes) {
|
|
339
|
+
throw new Error('CoreMail published MIME integrity conflicts.');
|
|
340
|
+
}
|
|
341
|
+
const queuedAt = this.now();
|
|
342
|
+
const update = await this.models.Submission.exact.transition({
|
|
343
|
+
current: claim.document,
|
|
344
|
+
change: (modelArg) => {
|
|
345
|
+
modelArg.mimePublishedAt = queuedAt;
|
|
346
|
+
modelArg.workerRetryAt = queuedAt;
|
|
347
|
+
modelArg.updatedAt = queuedAt;
|
|
348
|
+
modelArg.revision += 1;
|
|
349
|
+
delete modelArg.leaseOwnerTaskId;
|
|
350
|
+
delete modelArg.leaseToken;
|
|
351
|
+
delete modelArg.leaseExpiresAt;
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
if (update.status !== 'transitioned') {
|
|
355
|
+
const replay = await this.requireSubmission(sessionArg, submission.submissionId).catch(() => undefined);
|
|
356
|
+
if (replay?.submissionDigest === submission.submissionDigest
|
|
357
|
+
&& replay.mimeObjectKey === mimeObjectKey
|
|
358
|
+
&& replay.mimeSha256 === mime.sha256
|
|
359
|
+
&& replay.mimeLengthBytes === mime.lengthBytes
|
|
360
|
+
&& (replay.workerRetryAt !== undefined
|
|
361
|
+
|| replay.leaseOwnerTaskId !== 'submission-finalizer')) {
|
|
362
|
+
return { submission: toPublicSubmission(replay) };
|
|
363
|
+
}
|
|
364
|
+
throw new Error('CoreMail submission finalization fence changed.');
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
submission: toPublicSubmission(update.document),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
async get(sessionArg, requestArg) {
|
|
371
|
+
return {
|
|
372
|
+
submission: toPublicSubmission(await this.requireSubmission(sessionArg, requestArg.submissionId)),
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
async requireSubmission(sessionArg, submissionIdArg) {
|
|
376
|
+
const submission = await this.models.Submission.exact.findStoredOne({
|
|
377
|
+
...authorityFilter(sessionArg, submissionIdArg),
|
|
378
|
+
});
|
|
379
|
+
if (!submission) {
|
|
380
|
+
throw new Error('CoreMail submission is unavailable.');
|
|
381
|
+
}
|
|
382
|
+
return submission;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdWJtaXNzaW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuc3VibWlzc2lvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUF3QixNQUFNLHFCQUFxQixDQUFDO0FBQzNELE9BQU8sRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEUsT0FBTyxFQUNMLDhCQUE4QixFQUM5QixnQ0FBZ0MsR0FDakMsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQ0wsc0NBQXNDLEVBQ3RDLDBCQUEwQixFQUMxQiw2QkFBNkIsRUFDN0IsdUJBQXVCLEdBQ3hCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixtQkFBbUIsR0FDcEIsTUFBTSx5QkFBeUIsQ0FBQztBQWFqQyxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQztBQUV6RixNQUFNLGVBQWUsR0FBRyxDQUN0QixVQUFvQyxFQUNwQyxlQUFtQyxFQUNuQyxFQUFFLENBQUMsQ0FBQztJQUNKLFFBQVEsRUFBRSx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLGtCQUFrQixDQUFDO0lBQzVFLFNBQVMsRUFBRSx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLG1CQUFtQixDQUFDO0lBQy9FLFNBQVMsRUFBRSx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLG1CQUFtQixDQUFDO0lBQy9FLGVBQWUsRUFBRSxVQUFVLENBQUMsZUFBZTtJQUMzQyxH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
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { type ICoreMailModels } from './classes.models.js';
|
|
3
|
+
import { CoreMailStorage } from './classes.storage.js';
|
|
4
|
+
import type { ITransferAuthority, TTransferGrantPurpose } from './interfaces.js';
|
|
5
|
+
import type { ICoreMailTransferGrantRecord } from './coremail.persistence.js';
|
|
6
|
+
type TCoreMailSha256 = plugins.serveZoneInterfaces.data.TCoreMailSha256;
|
|
7
|
+
type TStoredTransferGrant = plugins.smartdata.TStoredDocument<ICoreMailTransferGrantRecord>;
|
|
8
|
+
export declare class CoreMailTransferService {
|
|
9
|
+
private readonly models;
|
|
10
|
+
private readonly storage;
|
|
11
|
+
private readonly now;
|
|
12
|
+
private readonly completionTasks;
|
|
13
|
+
private readonly operationControllers;
|
|
14
|
+
private readonly stopController;
|
|
15
|
+
private stopping;
|
|
16
|
+
constructor(models: ICoreMailModels, storage: CoreMailStorage, now?: () => number);
|
|
17
|
+
stop(): Promise<void>;
|
|
18
|
+
private track;
|
|
19
|
+
issueGrant(optionsArg: {
|
|
20
|
+
authority: ITransferAuthority;
|
|
21
|
+
purpose: TTransferGrantPurpose;
|
|
22
|
+
method: 'PUT' | 'GET';
|
|
23
|
+
expectedSha256: TCoreMailSha256;
|
|
24
|
+
lengthBytes: number;
|
|
25
|
+
contentType: string;
|
|
26
|
+
objectKey: string;
|
|
27
|
+
}): Promise<plugins.serveZoneInterfaces.data.ICoreMailTransferGrant>;
|
|
28
|
+
assertConsumed(optionsArg: {
|
|
29
|
+
grantId: string;
|
|
30
|
+
authority: ITransferAuthority;
|
|
31
|
+
purpose: TTransferGrantPurpose;
|
|
32
|
+
expectedSha256: TCoreMailSha256;
|
|
33
|
+
lengthBytes: number;
|
|
34
|
+
objectKey?: string;
|
|
35
|
+
}): Promise<TStoredTransferGrant>;
|
|
36
|
+
handleHttp(contextArg: plugins.typedserver.IRequestContext): Promise<Response | null>;
|
|
37
|
+
private handleUpload;
|
|
38
|
+
private handleDownload;
|
|
39
|
+
private failGrant;
|
|
40
|
+
}
|
|
41
|
+
export {};
|