@serve.zone/interfaces 30.12.0 → 30.13.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.
@@ -26,6 +26,11 @@ export type TCoreMailSubmissionState =
26
26
  | 'deferred'
27
27
  | 'failed'
28
28
  | 'deadLettered';
29
+ /**
30
+ * Entry point that produced an outbound submission. `api` is the authenticated
31
+ * workload TypedRequest surface, `smtp` is the CoreMail submission listener.
32
+ */
33
+ export type TCoreMailSubmissionSource = 'api' | 'smtp';
29
34
  export type TCoreMailInboundDeliveryState = 'pending' | 'fetching' | 'fetched' | 'acknowledged';
30
35
  export type TCoreMailInboundAckOutcome = 'processed' | 'discarded';
31
36
  export type TCoreMailRecipientAction = 'accept' | 'reject' | 'defer' | 'unhandled';
@@ -149,6 +154,8 @@ export interface ICoreMailSubmission {
149
154
  idempotencyKey: string;
150
155
  submissionDigest: TCoreMailSha256;
151
156
  state: TCoreMailSubmissionState;
157
+ /** Entry point that produced this submission. Omitted means an API submission. */
158
+ source?: TCoreMailSubmissionSource;
152
159
  parts: ICoreMailPartStatus[];
153
160
  transportMessageId?: string;
154
161
  attempts: number;
@@ -255,11 +262,38 @@ export interface ICoreMailRuntimeKeyReference {
255
262
  acceptUntil?: number;
256
263
  }
257
264
 
265
+ export interface ICoreMailSmtpTlsDesiredState {
266
+ /** Keys in CoreMail's resolved runtime secret material holding PEM text, never plaintext values. */
267
+ certificatePemSecretKey: string;
268
+ privateKeyPemSecretKey: string;
269
+ }
270
+
271
+ /**
272
+ * Desired state for CoreMail's own SMTP submission listener (MSA).
273
+ *
274
+ * SMTP AUTH uses the binding identity directly: the username is the
275
+ * `bindingId` and the password is any current or retiring credential secret of
276
+ * that binding, so credential rotation windows behave exactly as they do for
277
+ * the workload TypedRequest surface. The listener stays unavailable until the
278
+ * referenced PEM material resolves; an enabled listener without resolvable
279
+ * certificate and private key material never accepts submissions.
280
+ */
281
+ export interface ICoreMailSmtpDesiredState {
282
+ enabled: boolean;
283
+ /** Listener port inside the CoreMail workload. */
284
+ port: number;
285
+ /** Advertised EHLO hostname. */
286
+ hostname: string;
287
+ tls: ICoreMailSmtpTlsDesiredState;
288
+ }
289
+
258
290
  export interface ICoreMailDesiredState {
259
291
  schemaVersion: 2;
260
292
  configEpoch: number;
261
293
  bindings: ICoreMailBindingDesiredState[];
262
294
  gateway: ICoreMailGatewayDesiredState;
295
+ /** Optional SMTP submission listener. An omitted listener keeps the API-only surface. */
296
+ smtp?: ICoreMailSmtpDesiredState;
263
297
  cursorKeys: ICoreMailRuntimeKeyReference[];
264
298
  }
265
299
 
@@ -293,6 +327,36 @@ export interface ICoreMailReconciliationStatus {
293
327
  errorCode?: TCoreMailErrorCode;
294
328
  }
295
329
 
330
+ export interface ICoreMailOutboundMailCounters {
331
+ submittedApi: number;
332
+ submittedSmtp: number;
333
+ delivered: number;
334
+ deferred: number;
335
+ failed: number;
336
+ deadLettered: number;
337
+ }
338
+
339
+ export interface ICoreMailInboundMailCounters {
340
+ received: number;
341
+ acknowledgedProcessed: number;
342
+ acknowledgedDiscarded: number;
343
+ }
344
+
345
+ /**
346
+ * Per-service mail counters for one UTC calendar day, reported over the
347
+ * authenticated CoreMail control session.
348
+ */
349
+ export interface ICoreMailServiceMailStatistics {
350
+ tenantId: string;
351
+ serviceId: string;
352
+ bindingId: string;
353
+ /** UTC calendar day, `YYYY-MM-DD`. */
354
+ dayUtc: string;
355
+ outbound: ICoreMailOutboundMailCounters;
356
+ inbound: ICoreMailInboundMailCounters;
357
+ updatedAt: number;
358
+ }
359
+
296
360
  export interface ICoreMailRecipientResolution {
297
361
  recipient: string;
298
362
  action: TCoreMailRecipientAction;
@@ -311,6 +375,14 @@ export interface ICoreMailGatewayMessageDescriptor {
311
375
  };
312
376
  }
313
377
 
378
+ /**
379
+ * dcrouter-reported delivery status for one accepted transport message.
380
+ *
381
+ * `updatedAt` must be monotonic per `transportMessageId`. A
382
+ * `transportMessageId` the gateway can never recognize again must be reported
383
+ * as a terminal `failed` status instead of an error, because CoreMail retries
384
+ * errors indefinitely.
385
+ */
314
386
  export interface ICoreMailGatewayOutboundStatus {
315
387
  transportMessageId: string;
316
388
  state: Extract<
package/ts/data/mail.ts CHANGED
@@ -2,7 +2,13 @@ export type TMailGatewayClientType = 'onebox' | 'cloudly' | 'custom' | (string &
2
2
 
3
3
  export type TMailAddressPatternType = 'exactAddress' | 'domainWildcard' | 'localPartPattern';
4
4
 
5
- export type TMailInboundTargetType = 'webhook' | 'smtpForward' | 'typedEndpoint' | 'discard' | 'reject';
5
+ export type TMailInboundTargetType =
6
+ | 'webhook'
7
+ | 'smtpForward'
8
+ | 'typedEndpoint'
9
+ | 'coreMail'
10
+ | 'discard'
11
+ | 'reject';
6
12
 
7
13
  export type TMailRecipientPolicyMode = 'acceptAll' | 'staticList' | 'cachedResolver' | 'appResolver';
8
14
 
@@ -50,9 +56,26 @@ export type TMailDeliveryJournalEventType =
50
56
  | 'bounced'
51
57
  | 'complaint';
52
58
 
59
+ /**
60
+ * Error codes a mail submission may return. The CoreMail-fronted path maps the
61
+ * matching `TCoreMailErrorCode` values through unchanged so applications can
62
+ * branch on them regardless of which transport carried the submission.
63
+ */
53
64
  export type TMailSubmissionErrorCode =
54
65
  | 'INVALID_REPLY_TO'
55
- | 'REPLY_TO_FIELD_HEADER_CONFLICT';
66
+ | 'REPLY_TO_FIELD_HEADER_CONFLICT'
67
+ | 'AUTHENTICATION_FAILED'
68
+ | 'CAPABILITY_DENIED'
69
+ | 'INVALID_REQUEST'
70
+ | 'INVALID_MAILBOX'
71
+ | 'INVALID_SENDER'
72
+ | 'INVALID_RECIPIENT'
73
+ | 'INVALID_HEADER'
74
+ | 'PAYLOAD_LIMIT_EXCEEDED'
75
+ | 'QUOTA_EXCEEDED'
76
+ | 'IDEMPOTENCY_CONFLICT'
77
+ | 'STATE_CONFLICT'
78
+ | 'NOT_FOUND';
56
79
 
57
80
  /**
58
81
  * Runtime owner of a mail resource. `appInstanceId` is the deployed WorkApp or service
@@ -94,11 +117,17 @@ export interface IMailTypedEndpointTarget {
94
117
  timeoutMs?: number;
95
118
  }
96
119
 
120
+ export interface IMailCoreMailTarget {
121
+ /** CoreMail service identity that owns the inbound mailbox. */
122
+ coreMailServiceId: string;
123
+ }
124
+
97
125
  export interface IMailInboundTarget {
98
126
  type: TMailInboundTargetType;
99
127
  webhook?: IMailWebhookTarget;
100
128
  smtpForward?: IMailSmtpForwardTarget;
101
129
  typedEndpoint?: IMailTypedEndpointTarget;
130
+ coreMail?: IMailCoreMailTarget;
102
131
  reject?: {
103
132
  smtpCode: number;
104
133
  message: string;
@@ -231,8 +260,11 @@ export type TServiceMailSubmissionTlsMode = 'plain' | 'starttls' | 'implicitTls'
231
260
 
232
261
  export interface IServiceMailInboundConfig {
233
262
  enabled?: boolean;
234
- /** Platformclient apps use typedEndpoint; third-party apps with their own SMTP server use smtpForward. */
235
- targetType?: 'typedEndpoint' | 'smtpForward';
263
+ /**
264
+ * Platformclient apps use typedEndpoint; third-party apps with their own SMTP
265
+ * server use smtpForward; services bound to a CoreMail workload use coreMail.
266
+ */
267
+ targetType?: 'typedEndpoint' | 'smtpForward' | 'coreMail';
236
268
  /** TypedRequest method exposed by platformclient over TypedSocket for inbound delivery. */
237
269
  typedMethod?: string;
238
270
  /** Published Docker/Swarm port that dcrouter may SMTP-forward inbound mail to. */
@@ -10,6 +10,7 @@ import type {
10
10
  ICoreMailRecipientResolution,
11
11
  ICoreMailReconciliationStatus,
12
12
  ICoreMailReplicaIdentity,
13
+ ICoreMailServiceMailStatistics,
13
14
  ICoreMailSubmission,
14
15
  ICoreMailUploadGrant,
15
16
  TCoreMailInboundAckOutcome,
@@ -237,6 +238,33 @@ export interface IReq_CoreMailGetReconciliationStatus extends plugins.typedreque
237
238
  };
238
239
  }
239
240
 
241
+ /**
242
+ * Control-session read of per-service mail counters. Authority comes from the
243
+ * authenticated control session; the request carries no tenant or binding
244
+ * authority of its own.
245
+ */
246
+ export interface IReq_CoreMailGetServiceMailStatistics extends plugins.typedrequestInterfaces.implementsTR<
247
+ plugins.typedrequestInterfaces.ITypedRequest,
248
+ IReq_CoreMailGetServiceMailStatistics
249
+ > {
250
+ method: 'coreMailGetServiceMailStatistics';
251
+ request: {
252
+ /** Inclusive first UTC calendar day, `YYYY-MM-DD`. */
253
+ fromDayUtc: string;
254
+ /** Inclusive last UTC calendar day, `YYYY-MM-DD`. */
255
+ toDayUtc: string;
256
+ /** Optional service filter. Omitted means every service known to this CoreMail. */
257
+ serviceIds?: string[];
258
+ /** Opaque CoreMail-owned composite cursor. */
259
+ cursor?: string;
260
+ limit: number;
261
+ };
262
+ response: {
263
+ statistics: ICoreMailServiceMailStatistics[];
264
+ nextCursor?: string;
265
+ };
266
+ }
267
+
240
268
  export interface IReq_CoreMailGatewayAuthenticate extends plugins.typedrequestInterfaces.implementsTR<
241
269
  plugins.typedrequestInterfaces.ITypedRequest,
242
270
  IReq_CoreMailGatewayAuthenticate
@@ -256,6 +284,13 @@ export interface IReq_CoreMailGatewayAuthenticate extends plugins.typedrequestIn
256
284
  };
257
285
  }
258
286
 
287
+ /**
288
+ * CoreMail binds every issued routing handle to a digest of the exact
289
+ * normalized `envelope` and `source` sent here. The following
290
+ * `coreMailGatewayPrepareInboundHandoff` call must therefore resend
291
+ * byte-identical values: the full `rcptTo` set in the same order, the same
292
+ * `mailFrom`, and the same connection source fields.
293
+ */
259
294
  export interface IReq_CoreMailGatewayResolveRecipients extends plugins.typedrequestInterfaces.implementsTR<
260
295
  plugins.typedrequestInterfaces.ITypedRequest,
261
296
  IReq_CoreMailGatewayResolveRecipients
@@ -271,6 +306,13 @@ export interface IReq_CoreMailGatewayResolveRecipients extends plugins.typedrequ
271
306
  };
272
307
  }
273
308
 
309
+ /**
310
+ * The handoff is validated against the routing handles issued by
311
+ * `coreMailGatewayResolveRecipients`. `message.envelope` and `source` must be
312
+ * byte-identical to the resolve-time values, including the full `rcptTo` set in
313
+ * the same order, because CoreMail recomputes the envelope digest the handles
314
+ * are bound to.
315
+ */
274
316
  export interface IReq_CoreMailGatewayPrepareInboundHandoff extends plugins.typedrequestInterfaces.implementsTR<
275
317
  plugins.typedrequestInterfaces.ITypedRequest,
276
318
  IReq_CoreMailGatewayPrepareInboundHandoff
@@ -343,6 +385,12 @@ export interface IReq_CoreMailGatewayCompleteOutboundHandoff extends plugins.typ
343
385
  };
344
386
  }
345
387
 
388
+ /**
389
+ * Status polling for one accepted transport message. `status.updatedAt` must be
390
+ * monotonic per `transportMessageId`. A `transportMessageId` that is
391
+ * permanently unknown to the gateway must be answered with a terminal `failed`
392
+ * status rather than an error, because CoreMail retries errors indefinitely.
393
+ */
346
394
  export interface IReq_CoreMailGatewayGetOutboundStatus extends plugins.typedrequestInterfaces.implementsTR<
347
395
  plugins.typedrequestInterfaces.ITypedRequest,
348
396
  IReq_CoreMailGatewayGetOutboundStatus
@@ -1,4 +1,5 @@
1
1
  import * as plugins from '../plugins.js';
2
+ import type { ICoreMailGatewayPeerDesiredState } from '../data/coremail.js';
2
3
  import type { IIdentity } from '../data/user.js';
3
4
  import type {
4
5
  IMailAddressBinding,
@@ -144,6 +145,67 @@ export interface IReq_DeleteMailAddressBinding extends plugins.typedrequestInter
144
145
  };
145
146
  }
146
147
 
148
+ /**
149
+ * dcrouter-owned CoreMail gateway peer state.
150
+ *
151
+ * `peer.transferOrigin` must equal the `gateway.coreMailTransferOrigin` carried
152
+ * in that CoreMail service's own desired state. The producer (Cloudly or
153
+ * Onebox) is the single owner of that string: dcrouter never infers it from a
154
+ * socket, Host header, TypedSocket tag, or peer input.
155
+ */
156
+ export interface IReq_ListCoreMailGatewayPeers extends plugins.typedrequestInterfaces.implementsTR<
157
+ plugins.typedrequestInterfaces.ITypedRequest,
158
+ IReq_ListCoreMailGatewayPeers
159
+ > {
160
+ method: 'listCoreMailGatewayPeers';
161
+ request: {
162
+ auth: IMailControlRequestAuth;
163
+ owner: IMailResourceOwner;
164
+ };
165
+ response: {
166
+ peers: ICoreMailGatewayPeerDesiredState[];
167
+ };
168
+ }
169
+
170
+ /**
171
+ * Creates or replaces one CoreMail gateway peer. On success the accepted peer is
172
+ * returned in its stored form so the producer can compare the exact applied
173
+ * state. `owner` is required (not partial) because a peer is producer-owned
174
+ * provisioning state, never a filtered listing.
175
+ */
176
+ export interface IReq_SyncCoreMailGatewayPeer extends plugins.typedrequestInterfaces.implementsTR<
177
+ plugins.typedrequestInterfaces.ITypedRequest,
178
+ IReq_SyncCoreMailGatewayPeer
179
+ > {
180
+ method: 'syncCoreMailGatewayPeer';
181
+ request: {
182
+ auth: IMailControlRequestAuth;
183
+ owner: IMailResourceOwner;
184
+ peer: ICoreMailGatewayPeerDesiredState;
185
+ };
186
+ response: {
187
+ success: boolean;
188
+ peer?: ICoreMailGatewayPeerDesiredState;
189
+ message?: string;
190
+ };
191
+ }
192
+
193
+ export interface IReq_DeleteCoreMailGatewayPeer extends plugins.typedrequestInterfaces.implementsTR<
194
+ plugins.typedrequestInterfaces.ITypedRequest,
195
+ IReq_DeleteCoreMailGatewayPeer
196
+ > {
197
+ method: 'deleteCoreMailGatewayPeer';
198
+ request: {
199
+ auth: IMailControlRequestAuth;
200
+ owner: IMailResourceOwner;
201
+ coreMailServiceId: string;
202
+ };
203
+ response: {
204
+ success: boolean;
205
+ message?: string;
206
+ };
207
+ }
208
+
147
209
  export interface IReq_ListWorkAppMailBindings extends plugins.typedrequestInterfaces.implementsTR<
148
210
  plugins.typedrequestInterfaces.ITypedRequest,
149
211
  IReq_ListWorkAppMailBindings