@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,50 @@
1
+ {
2
+ "@git.zone/cli": {
3
+ "schemaVersion": 2,
4
+ "projectType": "service",
5
+ "module": {
6
+ "githost": "code.foss.global",
7
+ "gitscope": "serve.zone",
8
+ "gitrepo": "coremail",
9
+ "description": "Authenticated mail persistence and delivery orchestration for serve.zone workloads.",
10
+ "npmPackagename": "@serve.zone/coremail",
11
+ "license": "MIT"
12
+ },
13
+ "release": {
14
+ "targets": {
15
+ "git": {
16
+ "enabled": true,
17
+ "remote": "origin",
18
+ "pushBranch": true,
19
+ "pushTags": true
20
+ },
21
+ "npm": {
22
+ "enabled": true,
23
+ "registries": [
24
+ "https://verdaccio.lossless.digital",
25
+ "https://registry.npmjs.org"
26
+ ],
27
+ "accessLevel": "public",
28
+ "alreadyPublished": "success"
29
+ },
30
+ "docker": {
31
+ "enabled": true,
32
+ "engine": "tsdocker",
33
+ "patterns": []
34
+ }
35
+ }
36
+ }
37
+ },
38
+ "@git.zone/tsdocker": {
39
+ "registries": [
40
+ "code.foss.global"
41
+ ],
42
+ "registryRepoMap": {
43
+ "code.foss.global": "serve.zone/coremail"
44
+ },
45
+ "platforms": [
46
+ "linux/amd64",
47
+ "linux/arm64"
48
+ ]
49
+ }
50
+ }
package/changelog.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 2026-07-30 - 1.0.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - Add the standalone CoreMail service with authenticated workload/control and
8
+ dcrouter gateway sessions, SmartData-only state transitions, exact
9
+ SmartBucket transfers, deterministic MIME, bounded inbound delivery cursors,
10
+ monotonic desired-state activation, and lifecycle-owned outbound delivery.
package/cli.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ process.env.CLI_CALL = 'true';
3
+ const cliTool = await import('./dist_ts/index.js');
4
+ await cliTool.runCli();
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export declare const commitinfo: {
5
+ name: string;
6
+ version: string;
7
+ description: string;
8
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@serve.zone/coremail',
6
+ version: '1.0.0',
7
+ description: 'Authenticated mail persistence and delivery orchestration for serve.zone workloads.'
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFGQUFxRjtDQUNuRyxDQUFBIn0=
@@ -0,0 +1,45 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { ICoreMailAuthLimiterSnapshot, ICoreMailControlSession, ICoreMailPeer, ICoreMailWorkloadSession } from './interfaces.js';
3
+ type TCoreMailDesiredState = plugins.serveZoneInterfaces.data.ICoreMailDesiredState;
4
+ type TCoreMailBinding = plugins.serveZoneInterfaces.data.ICoreMailBindingDesiredState;
5
+ export declare const coreMailSessionKey = "coremail.authenticated-session";
6
+ export declare const coreMailPreAuthDeadlineKey = "coremail.pre-auth-deadline";
7
+ export declare class CoreMailAuthenticationError extends Error {
8
+ constructor();
9
+ }
10
+ export declare class CoreMailAuthorizationError extends Error {
11
+ constructor();
12
+ }
13
+ export declare class CoreMailCapabilityDeniedError extends Error {
14
+ constructor();
15
+ }
16
+ export declare class CoreMailAuthLimiter {
17
+ private readonly maximumInFlight;
18
+ private readonly capacity;
19
+ private readonly refillPerSecond;
20
+ private readonly now;
21
+ private inFlight;
22
+ private tokens;
23
+ private lastRefillAt;
24
+ constructor(maximumInFlight?: number, capacity?: number, refillPerSecond?: number, now?: () => number);
25
+ private refill;
26
+ snapshot(): ICoreMailAuthLimiterSnapshot;
27
+ run<T>(workArg: () => Promise<T>): Promise<T>;
28
+ }
29
+ export declare class CoreMailAuth {
30
+ private readonly controlBootstrap;
31
+ private readonly getActiveDesiredState;
32
+ private readonly now;
33
+ readonly limiter: CoreMailAuthLimiter;
34
+ constructor(controlBootstrap: plugins.serveZoneInterfaces.data.ICoreMailControlBootstrap, getActiveDesiredState: () => Promise<TCoreMailDesiredState | null>, now?: () => number);
35
+ private requireFreshPeer;
36
+ private verify;
37
+ authenticateControl(peerArg: ICoreMailPeer, requestArg: plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailAuthenticateControl['request']): Promise<ICoreMailControlSession>;
38
+ authenticateWorkload(peerArg: ICoreMailPeer, requestArg: plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailAuthenticateWorkload['request']): Promise<ICoreMailWorkloadSession>;
39
+ requireControlSession(peerArg: ICoreMailPeer): ICoreMailControlSession;
40
+ requireWorkloadSession(peerArg: ICoreMailPeer, operationArg: plugins.serveZoneInterfaces.data.TCoreMailWorkloadOperation): Promise<{
41
+ session: ICoreMailWorkloadSession;
42
+ binding: TCoreMailBinding;
43
+ }>;
44
+ }
45
+ export {};
@@ -0,0 +1,204 @@
1
+ import * as plugins from './plugins.js';
2
+ import { requireCoreMailIdentifier, requireCoreMailSafeInteger, } from './coremail.selectors.js';
3
+ export const coreMailSessionKey = 'coremail.authenticated-session';
4
+ export const coreMailPreAuthDeadlineKey = 'coremail.pre-auth-deadline';
5
+ export class CoreMailAuthenticationError extends Error {
6
+ constructor() {
7
+ super('CoreMail authentication failed.');
8
+ this.name = 'CoreMailAuthenticationError';
9
+ }
10
+ }
11
+ export class CoreMailAuthorizationError extends Error {
12
+ constructor() {
13
+ super('CoreMail authority is unavailable.');
14
+ this.name = 'CoreMailAuthorizationError';
15
+ }
16
+ }
17
+ export class CoreMailCapabilityDeniedError extends Error {
18
+ constructor() {
19
+ super('CoreMail operation is not permitted by this authority.');
20
+ this.name = 'CoreMailCapabilityDeniedError';
21
+ }
22
+ }
23
+ export class CoreMailAuthLimiter {
24
+ maximumInFlight;
25
+ capacity;
26
+ refillPerSecond;
27
+ now;
28
+ inFlight = 0;
29
+ tokens;
30
+ lastRefillAt;
31
+ constructor(maximumInFlight = 4, capacity = 8, refillPerSecond = 2, now = Date.now) {
32
+ this.maximumInFlight = maximumInFlight;
33
+ this.capacity = capacity;
34
+ this.refillPerSecond = refillPerSecond;
35
+ this.now = now;
36
+ this.tokens = capacity;
37
+ this.lastRefillAt = now();
38
+ }
39
+ refill() {
40
+ const now = this.now();
41
+ const elapsedMs = Math.max(0, now - this.lastRefillAt);
42
+ if (elapsedMs < 1_000) {
43
+ return;
44
+ }
45
+ const intervals = Math.floor(elapsedMs / 1_000);
46
+ this.tokens = Math.min(this.capacity, this.tokens + (intervals * this.refillPerSecond));
47
+ this.lastRefillAt += intervals * 1_000;
48
+ }
49
+ snapshot() {
50
+ this.refill();
51
+ return { inFlight: this.inFlight, tokens: this.tokens };
52
+ }
53
+ async run(workArg) {
54
+ this.refill();
55
+ if (this.inFlight >= this.maximumInFlight || this.tokens < 1) {
56
+ throw new CoreMailAuthenticationError();
57
+ }
58
+ this.tokens--;
59
+ this.inFlight++;
60
+ try {
61
+ return await workArg();
62
+ }
63
+ finally {
64
+ this.inFlight--;
65
+ }
66
+ }
67
+ }
68
+ const findAcceptedVerifier = (credentialsArg, credentialIdArg, credentialVersionArg, nowArg) => credentialsArg.find((credentialArg) => credentialArg.credentialId === credentialIdArg
69
+ && credentialArg.version === credentialVersionArg
70
+ && (credentialArg.state === 'current'
71
+ || (credentialArg.state === 'retiring'
72
+ && credentialArg.acceptUntil !== undefined
73
+ && credentialArg.acceptUntil >= nowArg)));
74
+ export class CoreMailAuth {
75
+ controlBootstrap;
76
+ getActiveDesiredState;
77
+ now;
78
+ limiter = new CoreMailAuthLimiter();
79
+ constructor(controlBootstrap, getActiveDesiredState, now = Date.now) {
80
+ this.controlBootstrap = controlBootstrap;
81
+ this.getActiveDesiredState = getActiveDesiredState;
82
+ this.now = now;
83
+ }
84
+ requireFreshPeer(peerArg) {
85
+ const deadline = peerArg.context.state[coreMailPreAuthDeadlineKey];
86
+ if (peerArg.data.has(coreMailSessionKey)
87
+ || !Number.isSafeInteger(deadline)
88
+ || Number(deadline) < this.now()) {
89
+ peerArg.close(4401, 'authentication required');
90
+ throw new CoreMailAuthenticationError();
91
+ }
92
+ }
93
+ async verify(verifierArg, secretArg) {
94
+ if (!verifierArg
95
+ || typeof secretArg !== 'string'
96
+ || secretArg.length < 32
97
+ || secretArg.length > 512) {
98
+ throw new CoreMailAuthenticationError();
99
+ }
100
+ const verified = await this.limiter.run(async () => plugins.argon2.verify(verifierArg.verificationHash, secretArg));
101
+ if (!verified) {
102
+ throw new CoreMailAuthenticationError();
103
+ }
104
+ }
105
+ async authenticateControl(peerArg, requestArg) {
106
+ this.requireFreshPeer(peerArg);
107
+ try {
108
+ const credentialId = requireCoreMailIdentifier(requestArg.credentialId, 'credentialId');
109
+ const credentialVersion = requireCoreMailSafeInteger(requestArg.credentialVersion, 'credentialVersion', 1);
110
+ const verifier = findAcceptedVerifier(this.controlBootstrap.credentials, credentialId, credentialVersion, this.now());
111
+ await this.verify(verifier, requestArg.credentialSecret);
112
+ const session = Object.freeze({
113
+ kind: 'control',
114
+ peerId: peerArg.id,
115
+ credentialId,
116
+ credentialVersion,
117
+ authenticatedAt: this.now(),
118
+ });
119
+ peerArg.data.set(coreMailSessionKey, session);
120
+ return session;
121
+ }
122
+ catch {
123
+ peerArg.close(4401, 'authentication failed');
124
+ throw new CoreMailAuthenticationError();
125
+ }
126
+ }
127
+ async authenticateWorkload(peerArg, requestArg) {
128
+ this.requireFreshPeer(peerArg);
129
+ try {
130
+ const desiredState = await this.getActiveDesiredState();
131
+ const bindingId = requireCoreMailIdentifier(requestArg.bindingId, 'bindingId');
132
+ const credentialId = requireCoreMailIdentifier(requestArg.credentialId, 'credentialId');
133
+ const credentialVersion = requireCoreMailSafeInteger(requestArg.credentialVersion, 'credentialVersion', 1);
134
+ const binding = desiredState?.bindings.find((bindingArg) => bindingArg.bindingId === bindingId
135
+ && bindingArg.state !== 'disabled');
136
+ const verifier = binding && findAcceptedVerifier(binding.credentials, credentialId, credentialVersion, this.now());
137
+ await this.verify(verifier, requestArg.credentialSecret);
138
+ const allowedOperations = plugins.serveZoneInterfaces.data.resolveCoreMailWorkloadOperations(binding.state, binding.capabilities);
139
+ const session = Object.freeze({
140
+ kind: 'workload',
141
+ peerId: peerArg.id,
142
+ tenantId: binding.tenantId,
143
+ serviceId: binding.serviceId,
144
+ bindingId: binding.bindingId,
145
+ bindingRevision: binding.revision,
146
+ configEpoch: desiredState.configEpoch,
147
+ credentialId,
148
+ credentialVersion,
149
+ bindingState: binding.state,
150
+ capabilities: Object.freeze([...binding.capabilities]),
151
+ allowedOperations: Object.freeze([...allowedOperations]),
152
+ coreMailTransferOrigin: desiredState.gateway.coreMailTransferOrigin,
153
+ authenticatedAt: this.now(),
154
+ });
155
+ peerArg.data.set(coreMailSessionKey, session);
156
+ return session;
157
+ }
158
+ catch {
159
+ peerArg.close(4401, 'authentication failed');
160
+ throw new CoreMailAuthenticationError();
161
+ }
162
+ }
163
+ requireControlSession(peerArg) {
164
+ const session = peerArg.data.get(coreMailSessionKey);
165
+ if (!session || session.kind !== 'control' || session.peerId !== peerArg.id) {
166
+ peerArg.close(4403, 'authority unavailable');
167
+ throw new CoreMailAuthorizationError();
168
+ }
169
+ const verifier = findAcceptedVerifier(this.controlBootstrap.credentials, session.credentialId, session.credentialVersion, this.now());
170
+ if (!verifier) {
171
+ peerArg.close(4403, 'authority expired');
172
+ throw new CoreMailAuthorizationError();
173
+ }
174
+ return session;
175
+ }
176
+ async requireWorkloadSession(peerArg, operationArg) {
177
+ const session = peerArg.data.get(coreMailSessionKey);
178
+ if (!session || session.kind !== 'workload' || session.peerId !== peerArg.id) {
179
+ peerArg.close(4403, 'authority unavailable');
180
+ throw new CoreMailAuthorizationError();
181
+ }
182
+ const desiredState = await this.getActiveDesiredState();
183
+ const binding = desiredState?.bindings.find((bindingArg) => bindingArg.bindingId === session.bindingId
184
+ && bindingArg.serviceId === session.serviceId
185
+ && bindingArg.tenantId === session.tenantId
186
+ && bindingArg.revision === session.bindingRevision
187
+ && bindingArg.state === session.bindingState);
188
+ const verifier = binding && findAcceptedVerifier(binding.credentials, session.credentialId, session.credentialVersion, this.now());
189
+ if (!desiredState
190
+ || desiredState.configEpoch !== session.configEpoch
191
+ || !binding
192
+ || !verifier) {
193
+ peerArg.close(4403, 'authority expired');
194
+ throw new CoreMailAuthorizationError();
195
+ }
196
+ const allowedOperations = plugins.serveZoneInterfaces.data.resolveCoreMailWorkloadOperations(binding.state, binding.capabilities);
197
+ if (!session.allowedOperations.includes(operationArg)
198
+ || !allowedOperations.includes(operationArg)) {
199
+ throw new CoreMailCapabilityDeniedError();
200
+ }
201
+ return { session, binding };
202
+ }
203
+ }
204
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5hdXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBUXhDLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsMEJBQTBCLEdBQzNCLE1BQU0seUJBQXlCLENBQUM7QUFPakMsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsZ0NBQWdDLENBQUM7QUFDbkUsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsNEJBQTRCLENBQUM7QUFFdkUsTUFBTSxPQUFPLDJCQUE0QixTQUFRLEtBQUs7SUFDcEQ7UUFDRSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztRQUN6QyxJQUFJLENBQUMsSUFBSSxHQUFHLDZCQUE2QixDQUFDO0lBQzVDLENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTywwQkFBMkIsU0FBUSxLQUFLO0lBQ25EO1FBQ0UsS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLElBQUksR0FBRyw0QkFBNEIsQ0FBQztJQUMzQyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLE9BQU8sNkJBQThCLFNBQVEsS0FBSztJQUN0RDtRQUNFLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxJQUFJLEdBQUcsK0JBQStCLENBQUM7SUFDOUMsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLG1CQUFtQjtJQU1YO0lBQ0E7SUFDQTtJQUNBO0lBUlgsUUFBUSxHQUFHLENBQUMsQ0FBQztJQUNiLE1BQU0sQ0FBUztJQUNmLFlBQVksQ0FBUztJQUU3QixZQUNtQixrQkFBa0IsQ0FBQyxFQUNuQixXQUFXLENBQUMsRUFDWixrQkFBa0IsQ0FBQyxFQUNuQixNQUFvQixJQUFJLENBQUMsR0FBRztRQUg1QixvQkFBZSxHQUFmLGVBQWUsQ0FBSTtRQUNuQixhQUFRLEdBQVIsUUFBUSxDQUFJO1FBQ1osb0JBQWUsR0FBZixlQUFlLENBQUk7UUFDbkIsUUFBRyxHQUFILEdBQUcsQ0FBeUI7UUFFN0MsSUFBSSxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUM7UUFDdkIsSUFBSSxDQUFDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRU8sTUFBTTtRQUNaLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN2QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZELElBQUksU0FBUyxHQUFHLEtBQUssRUFBRSxDQUFDO1lBQ3RCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUNwQixJQUFJLENBQUMsUUFBUSxFQUNiLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUNqRCxDQUFDO1FBQ0YsSUFBSSxDQUFDLFlBQVksSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ3pDLENBQUM7SUFFTSxRQUFRO1FBQ2IsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDMUQsQ0FBQztJQUVNLEtBQUssQ0FBQyxHQUFHLENBQUksT0FBeUI7UUFDM0MsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxlQUFlLElBQUksSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3RCxNQUFNLElBQUksMkJBQTJCLEVBQUUsQ0FBQztRQUMxQyxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2hCLElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxPQUFPLEVBQUUsQ0FBQztRQUN6QixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUM7Q0FDRjtBQUVELE1BQU0sb0JBQW9CLEdBQUcsQ0FDM0IsY0FBbUMsRUFDbkMsZUFBdUIsRUFDdkIsb0JBQTRCLEVBQzVCLE1BQWMsRUFDaUIsRUFBRSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUN4RSxhQUFhLENBQUMsWUFBWSxLQUFLLGVBQWU7T0FDM0MsYUFBYSxDQUFDLE9BQU8sS0FBSyxvQkFBb0I7T0FDOUMsQ0FDRCxhQUFhLENBQUMsS0FBSyxLQUFLLFNBQVM7V0FDOUIsQ0FDRCxhQUFhLENBQUMsS0FBSyxLQUFLLFVBQVU7ZUFDL0IsYUFBYSxDQUFDLFdBQVcsS0FBSyxTQUFTO2VBQ3ZDLGFBQWEsQ0FBQyxXQUFXLElBQUksTUFBTSxDQUN2QyxDQUNGLENBQ0YsQ0FBQztBQUVGLE1BQU0sT0FBTyxZQUFZO0lBSUo7SUFFQTtJQUVBO0lBUEgsT0FBTyxHQUFHLElBQUksbUJBQW1CLEVBQUUsQ0FBQztJQUVwRCxZQUNtQixnQkFDMkMsRUFDM0MscUJBQ3NCLEVBQ3RCLE1BQW9CLElBQUksQ0FBQyxHQUFHO1FBSjVCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FDMkI7UUFDM0MsMEJBQXFCLEdBQXJCLHFCQUFxQixDQUNDO1FBQ3RCLFFBQUcsR0FBSCxHQUFHLENBQXlCO0lBQzVDLENBQUM7SUFFSSxnQkFBZ0IsQ0FBQyxPQUFzQjtRQUM3QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ25FLElBQ0UsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUM7ZUFDakMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQztlQUMvQixNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUNoQyxDQUFDO1lBQ0QsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUseUJBQXlCLENBQUMsQ0FBQztZQUMvQyxNQUFNLElBQUksMkJBQTJCLEVBQUUsQ0FBQztRQUMxQyxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxNQUFNLENBQ2xCLFdBQTBDLEVBQzFDLFNBQWlCO1FBRWpCLElBQ0UsQ0FBQyxXQUFXO2VBQ1QsT0FBTyxTQUFTLEtBQUssUUFBUTtlQUM3QixTQUFTLENBQUMsTUFBTSxHQUFHLEVBQUU7ZUFDckIsU0FBUyxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQ3pCLENBQUM7WUFDRCxNQUFNLElBQUksMkJBQTJCLEVBQUUsQ0FBQztRQUMxQyxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUNqRCxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLENBQy9ELENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDZCxNQUFNLElBQUksMkJBQTJCLEVBQUUsQ0FBQztRQUMxQyxDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxtQkFBbUIsQ0FDOUIsT0FBc0IsRUFDdEIsVUFDMkY7UUFFM0YsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQztZQUNILE1BQU0sWUFBWSxHQUFHLHlCQUF5QixDQUM1QyxVQUFVLENBQUMsWUFBWSxFQUN2QixjQUFjLENBQ2YsQ0FBQztZQUNGLE1BQU0saUJBQWlCLEdBQUcsMEJBQTBCLENBQ2xELFVBQVUsQ0FBQyxpQkFBaUIsRUFDNUIsbUJBQW1CLEVBQ25CLENBQUMsQ0FDRixDQUFDO1lBQ0YsTUFBTSxRQUFRLEdBQUcsb0JBQW9CLENBQ25DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQ2pDLFlBQVksRUFDWixpQkFBaUIsRUFDakIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUNYLENBQUM7WUFDRixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ3pELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQTBCO2dCQUNyRCxJQUFJLEVBQUUsU0FBUztnQkFDZixNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUU7Z0JBQ2xCLFlBQVk7Z0JBQ1osaUJBQWlCO2dCQUNqQixlQUFlLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTthQUM1QixDQUFDLENBQUM7WUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM5QyxPQUFPLE9BQU8sQ0FBQztRQUNqQixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztZQUM3QyxNQUFNLElBQUksMkJBQTJCLEVBQUUsQ0FBQztRQUMxQyxDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxvQkFBb0IsQ0FDL0IsT0FBc0IsRUFDdEIsVUFDNEY7UUFFNUYsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQztZQUNILE1BQU0sWUFBWSxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDeEQsTUFBTSxTQUFTLEdBQUcseUJBQXlCLENBQ3pDLFVBQVUsQ0FBQyxTQUFTLEVBQ3BCLFdBQVcsQ0FDWixDQUFDO1lBQ0YsTUFBTSxZQUFZLEdBQUcseUJBQXlCLENBQzVDLFVBQVUsQ0FBQyxZQUFZLEVBQ3ZCLGNBQWMsQ0FDZixDQUFDO1lBQ0YsTUFBTSxpQkFBaUIsR0FBRywwQkFBMEIsQ0FDbEQsVUFBVSxDQUFDLGlCQUFpQixFQUM1QixtQkFBbUIsRUFDbkIsQ0FBQyxDQUNGLENBQUM7WUFDRixNQUFNLE9BQU8sR0FBRyxZQUFZLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQ3pELFVBQVUsQ0FBQyxTQUFTLEtBQUssU0FBUzttQkFDL0IsVUFBVSxDQUFDLEtBQUssS0FBSyxVQUFVLENBQ25DLENBQUM7WUFDRixNQUFNLFFBQVEsR0FBRyxPQUFPLElBQUksb0JBQW9CLENBQzlDLE9BQU8sQ0FBQyxXQUFXLEVBQ25CLFlBQVksRUFDWixpQkFBaUIsRUFDakIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUNYLENBQUM7WUFDRixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ3pELE1BQU0saUJBQWlCLEdBQ3JCLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsaUNBQWlDLENBQ2hFLE9BQVEsQ0FBQyxLQUFLLEVBQ2QsT0FBUSxDQUFDLFlBQVksQ0FDdEIsQ0FBQztZQUNKLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQTJCO2dCQUN0RCxJQUFJLEVBQUUsVUFBVTtnQkFDaEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxFQUFFO2dCQUNsQixRQUFRLEVBQUUsT0FBUSxDQUFDLFFBQVE7Z0JBQzNCLFNBQVMsRUFBRSxPQUFRLENBQUMsU0FBUztnQkFDN0IsU0FBUyxFQUFFLE9BQVEsQ0FBQyxTQUFTO2dCQUM3QixlQUFlLEVBQUUsT0FBUSxDQUFDLFFBQVE7Z0JBQ2xDLFdBQVcsRUFBRSxZQUFhLENBQUMsV0FBVztnQkFDdEMsWUFBWTtnQkFDWixpQkFBaUI7Z0JBQ2pCLFlBQVksRUFBRSxPQUFRLENBQUMsS0FBOEI7Z0JBQ3JELFlBQVksRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxPQUFRLENBQUMsWUFBWSxDQUFDLENBQ0U7Z0JBQ3hELGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLENBQ1E7Z0JBQy9ELHNCQUFzQixFQUFFLFlBQWEsQ0FBQyxPQUFPLENBQUMsc0JBQXNCO2dCQUNwRSxlQUFlLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTthQUM1QixDQUFDLENBQUM7WUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM5QyxPQUFPLE9BQU8sQ0FBQztRQUNqQixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztZQUM3QyxNQUFNLElBQUksMkJBQTJCLEVBQUUsQ0FBQztRQUMxQyxDQUFDO0lBQ0gsQ0FBQztJQUVNLHFCQUFxQixDQUFDLE9BQXNCO1FBQ2pELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFpQyxDQUFDO1FBQ3JGLElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDNUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztZQUM3QyxNQUFNLElBQUksMEJBQTBCLEVBQUUsQ0FBQztRQUN6QyxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsb0JBQW9CLENBQ25DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQ2pDLE9BQU8sQ0FBQyxZQUFZLEVBQ3BCLE9BQU8sQ0FBQyxpQkFBaUIsRUFDekIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUNYLENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sSUFBSSwwQkFBMEIsRUFBRSxDQUFDO1FBQ3pDLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRU0sS0FBSyxDQUFDLHNCQUFzQixDQUNqQyxPQUFzQixFQUN0QixZQUF5RTtRQUt6RSxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBaUMsQ0FBQztRQUNyRixJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssVUFBVSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzdFLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLHVCQUF1QixDQUFDLENBQUM7WUFDN0MsTUFBTSxJQUFJLDBCQUEwQixFQUFFLENBQUM7UUFDekMsQ0FBQztRQUNELE1BQU0sWUFBWSxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDeEQsTUFBTSxPQUFPLEdBQUcsWUFBWSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUN6RCxVQUFVLENBQUMsU0FBUyxLQUFLLE9BQU8sQ0FBQyxTQUFTO2VBQ3ZDLFVBQVUsQ0FBQyxTQUFTLEtBQUssT0FBTyxDQUFDLFNBQVM7ZUFDMUMsVUFBVSxDQUFDLFFBQVEsS0FBSyxPQUFPLENBQUMsUUFBUTtlQUN4QyxVQUFVLENBQUMsUUFBUSxLQUFLLE9BQU8sQ0FBQyxlQUFlO2VBQy9DLFVBQVUsQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLFlBQVksQ0FDN0MsQ0FBQztRQUNGLE1BQU0sUUFBUSxHQUFHLE9BQU8sSUFBSSxvQkFBb0IsQ0FDOUMsT0FBTyxDQUFDLFdBQVcsRUFDbkIsT0FBTyxDQUFDLFlBQVksRUFDcEIsT0FBTyxDQUFDLGlCQUFpQixFQUN6QixJQUFJLENBQUMsR0FBRyxFQUFFLENBQ1gsQ0FBQztRQUNGLElBQ0UsQ0FBQyxZQUFZO2VBQ1YsWUFBWSxDQUFDLFdBQVcsS0FBSyxPQUFPLENBQUMsV0FBVztlQUNoRCxDQUFDLE9BQU87ZUFDUixDQUFDLFFBQVEsRUFDWixDQUFDO1lBQ0QsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztZQUN6QyxNQUFNLElBQUksMEJBQTBCLEVBQUUsQ0FBQztRQUN6QyxDQUFDO1FBQ0QsTUFBTSxpQkFBaUIsR0FDckIsT0FBTyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxpQ0FBaUMsQ0FDaEUsT0FBTyxDQUFDLEtBQUssRUFDYixPQUFPLENBQUMsWUFBWSxDQUNyQixDQUFDO1FBQ0osSUFDRSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDO2VBQzlDLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUM1QyxDQUFDO1lBQ0QsTUFBTSxJQUFJLDZCQUE2QixFQUFFLENBQUM7UUFDNUMsQ0FBQztRQUNELE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDOUIsQ0FBQztDQUNGIn0=
@@ -0,0 +1,2 @@
1
+ import type { ICoreMailConfig } from './interfaces.js';
2
+ export declare const readCoreMailConfig: () => ICoreMailConfig;
@@ -0,0 +1,72 @@
1
+ import * as plugins from './plugins.js';
2
+ const requireEnv = (keyArg) => {
3
+ const value = process.env[keyArg];
4
+ if (!value || value.trim() !== value) {
5
+ throw new Error(`CoreMail requires a non-empty canonical ${keyArg}.`);
6
+ }
7
+ return value;
8
+ };
9
+ const parsePositiveInteger = (valueArg, keyArg, maximumArg) => {
10
+ if (!/^[1-9][0-9]*$/.test(valueArg)) {
11
+ throw new Error(`${keyArg} must be a positive integer.`);
12
+ }
13
+ const value = Number(valueArg);
14
+ if (!Number.isSafeInteger(value) || value > maximumArg) {
15
+ throw new Error(`${keyArg} is outside the supported range.`);
16
+ }
17
+ return value;
18
+ };
19
+ const parsePlainJson = (valueArg, keyArg) => {
20
+ const parsed = JSON.parse(valueArg);
21
+ if (!parsed
22
+ || typeof parsed !== 'object'
23
+ || Array.isArray(parsed)
24
+ || Object.getPrototypeOf(parsed) !== Object.prototype) {
25
+ throw new Error(`${keyArg} must contain one plain JSON object.`);
26
+ }
27
+ return parsed;
28
+ };
29
+ const parseHostnames = (valueArg) => {
30
+ const hostnames = valueArg.split(',');
31
+ if (hostnames.length === 0
32
+ || hostnames.length > 16
33
+ || hostnames.some((entryArg) => entryArg.trim() !== entryArg
34
+ || !/^[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?$/.test(entryArg)
35
+ || entryArg.includes('..'))
36
+ || new Set(hostnames).size !== hostnames.length) {
37
+ throw new Error('COREMAIL_HOSTNAMES must be a unique canonical hostname list.');
38
+ }
39
+ return hostnames;
40
+ };
41
+ export const readCoreMailConfig = () => {
42
+ const controlBootstrap = plugins.serveZoneInterfaces.data.normalizeCoreMailControlBootstrap(parsePlainJson(requireEnv(plugins.serveZoneInterfaces.data.coreMailRuntimeKeys.controlBootstrap), plugins.serveZoneInterfaces.data.coreMailRuntimeKeys.controlBootstrap));
43
+ const serviceId = requireEnv('COREMAIL_SERVICE_ID');
44
+ if (controlBootstrap.coreMailServiceId !== serviceId) {
45
+ throw new Error('CoreMail control bootstrap is bound to another service.');
46
+ }
47
+ const storageDescriptor = parsePlainJson(requireEnv('COREMAIL_STORAGE_DESCRIPTOR'), 'COREMAIL_STORAGE_DESCRIPTOR');
48
+ return Object.freeze({
49
+ port: parsePositiveInteger(process.env.COREMAIL_PORT ?? '3000', 'COREMAIL_PORT', 65_535),
50
+ hostnames: Object.freeze(parseHostnames(process.env.COREMAIL_HOSTNAMES ?? 'coremail.serve.zone')),
51
+ mongoDescriptor: Object.freeze({
52
+ mongoDbUrl: requireEnv('COREMAIL_MONGODB_URL'),
53
+ mongoDbName: requireEnv('COREMAIL_MONGODB_NAME'),
54
+ maxPoolSize: parsePositiveInteger(process.env.COREMAIL_MONGODB_MAX_POOL_SIZE ?? '50', 'COREMAIL_MONGODB_MAX_POOL_SIZE', 500),
55
+ maxIdleTimeMS: 300_000,
56
+ serverSelectionTimeoutMS: 10_000,
57
+ socketTimeoutMS: 30_000,
58
+ }),
59
+ storageDescriptor: Object.freeze(storageDescriptor),
60
+ bucketName: requireEnv('COREMAIL_BUCKET_NAME'),
61
+ controlBootstrap,
62
+ resolveRuntimeSecret: requireEnv,
63
+ replica: Object.freeze({
64
+ taskId: requireEnv('COREMAIL_TASK_ID'),
65
+ serviceId,
66
+ rolloutId: requireEnv('COREMAIL_ROLLOUT_ID'),
67
+ rolloutGeneration: parsePositiveInteger(requireEnv('COREMAIL_ROLLOUT_GENERATION'), 'COREMAIL_ROLLOUT_GENERATION', Number.MAX_SAFE_INTEGER),
68
+ imageDigest: plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(requireEnv('COREMAIL_IMAGE_DIGEST')),
69
+ }),
70
+ });
71
+ };
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUd4QyxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQWMsRUFBVSxFQUFFO0lBQzVDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDLENBQUM7QUFFRixNQUFNLG9CQUFvQixHQUFHLENBQUMsUUFBZ0IsRUFBRSxNQUFjLEVBQUUsVUFBa0IsRUFBVSxFQUFFO0lBQzVGLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLE1BQU0sOEJBQThCLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9CLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssR0FBRyxVQUFVLEVBQUUsQ0FBQztRQUN2RCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsTUFBTSxrQ0FBa0MsQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMsQ0FBQztBQUVGLE1BQU0sY0FBYyxHQUFHLENBQUMsUUFBZ0IsRUFBRSxNQUFjLEVBQTJCLEVBQUU7SUFDbkYsTUFBTSxNQUFNLEdBQVksSUFBSSxDQUFD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
@@ -0,0 +1,41 @@
1
+ import * as plugins from './plugins.js';
2
+ import { CoreMailAuth } from './classes.auth.js';
3
+ import { CoreMailDesiredStateService } from './classes.desiredstate.js';
4
+ import { CoreMailGateway, CoreMailOutboundWorker } from './classes.gateway.js';
5
+ import { CoreMailInboundService } from './classes.inbound.js';
6
+ import { CoreMailMaintenanceService } from './classes.maintenance.js';
7
+ import { type ICoreMailModels } from './classes.models.js';
8
+ import { CoreMailServer } from './classes.server.js';
9
+ import { CoreMailStorage } from './classes.storage.js';
10
+ import { CoreMailSubmissionService } from './classes.submissions.js';
11
+ import { CoreMailTransferService } from './classes.transfer.js';
12
+ import type { ICoreMailConfig } from './interfaces.js';
13
+ export declare class CoreMail {
14
+ readonly config: ICoreMailConfig;
15
+ readonly database: plugins.smartdata.SmartdataDb;
16
+ readonly models: ICoreMailModels;
17
+ readonly storage: CoreMailStorage;
18
+ readonly transfers: CoreMailTransferService;
19
+ readonly desiredState: CoreMailDesiredStateService;
20
+ readonly auth: CoreMailAuth;
21
+ readonly submissions: CoreMailSubmissionService;
22
+ readonly inbound: CoreMailInboundService;
23
+ readonly maintenance: CoreMailMaintenanceService;
24
+ readonly gateway: CoreMailGateway;
25
+ readonly server: CoreMailServer;
26
+ readonly outboundWorker: CoreMailOutboundWorker;
27
+ private lifecycleState;
28
+ private startPromise;
29
+ private stopPromise;
30
+ private databaseStarted;
31
+ private storageStarted;
32
+ private gatewayStarted;
33
+ private serverStarted;
34
+ private workerStarted;
35
+ private maintenanceStarted;
36
+ constructor(configArg?: ICoreMailConfig);
37
+ start(): Promise<void>;
38
+ private startInternal;
39
+ stop(): Promise<void>;
40
+ private stopStartedResources;
41
+ }
@@ -0,0 +1,155 @@
1
+ import * as plugins from './plugins.js';
2
+ import { CoreMailAuth } from './classes.auth.js';
3
+ import { readCoreMailConfig } from './classes.config.js';
4
+ import { CoreMailDesiredStateService } from './classes.desiredstate.js';
5
+ import { CoreMailGateway, CoreMailOutboundWorker, } from './classes.gateway.js';
6
+ import { CoreMailInboundService } from './classes.inbound.js';
7
+ import { CoreMailMaintenanceService } from './classes.maintenance.js';
8
+ import { createCoreMailModels, prepareCoreMailModelsForTransactions, } from './classes.models.js';
9
+ import { CoreMailServer } from './classes.server.js';
10
+ import { CoreMailStorage } from './classes.storage.js';
11
+ import { CoreMailSubmissionService } from './classes.submissions.js';
12
+ import { CoreMailTransferService } from './classes.transfer.js';
13
+ export class CoreMail {
14
+ config;
15
+ database;
16
+ models;
17
+ storage;
18
+ transfers;
19
+ desiredState;
20
+ auth;
21
+ submissions;
22
+ inbound;
23
+ maintenance;
24
+ gateway;
25
+ server;
26
+ outboundWorker;
27
+ lifecycleState = 'new';
28
+ startPromise = null;
29
+ stopPromise = null;
30
+ databaseStarted = false;
31
+ storageStarted = false;
32
+ gatewayStarted = false;
33
+ serverStarted = false;
34
+ workerStarted = false;
35
+ maintenanceStarted = false;
36
+ constructor(configArg = readCoreMailConfig()) {
37
+ this.config = configArg;
38
+ this.database = new plugins.smartdata.SmartdataDb(configArg.mongoDescriptor);
39
+ this.models = createCoreMailModels(this.database);
40
+ this.storage = new CoreMailStorage(configArg.storageDescriptor, configArg.bucketName);
41
+ this.transfers = new CoreMailTransferService(this.models, this.storage);
42
+ let server;
43
+ this.desiredState = new CoreMailDesiredStateService(this.database, this.models, this.storage, this.transfers, configArg.replica, (bindingArg, configEpochArg) => server?.activeSessionCounts(bindingArg, configEpochArg) ?? []);
44
+ this.auth = new CoreMailAuth(configArg.controlBootstrap, this.desiredState.getActiveDesiredState);
45
+ this.submissions = new CoreMailSubmissionService(this.database, this.models, this.storage, this.transfers);
46
+ this.inbound = new CoreMailInboundService(this.database, this.models, this.transfers, configArg.replica.serviceId, this.desiredState.getActiveDesiredState, configArg.resolveRuntimeSecret);
47
+ this.gateway = new CoreMailGateway(configArg, this.models, this.transfers, this.inbound, this.desiredState.getActiveDesiredState);
48
+ this.maintenance = new CoreMailMaintenanceService(this.models, this.storage);
49
+ this.server = server = new CoreMailServer(configArg, this.database, this.storage, this.transfers, this.desiredState, this.auth, this.submissions, this.inbound, this.gateway);
50
+ this.outboundWorker = new CoreMailOutboundWorker(this.models, this.transfers, this.gateway, configArg.replica.taskId, configArg.replica.serviceId);
51
+ }
52
+ async start() {
53
+ if (this.lifecycleState === 'running')
54
+ return;
55
+ if (this.lifecycleState === 'starting') {
56
+ await this.startPromise;
57
+ return;
58
+ }
59
+ if (this.lifecycleState !== 'new') {
60
+ throw new Error(`CoreMail cannot start from lifecycle state "${this.lifecycleState}".`);
61
+ }
62
+ this.lifecycleState = 'starting';
63
+ const startPromise = this.startInternal();
64
+ this.startPromise = startPromise;
65
+ try {
66
+ await startPromise;
67
+ this.lifecycleState = 'running';
68
+ }
69
+ catch (error) {
70
+ try {
71
+ await this.stopStartedResources();
72
+ this.lifecycleState = 'stopped';
73
+ }
74
+ catch (cleanupError) {
75
+ this.lifecycleState = 'failed';
76
+ throw new AggregateError([error, cleanupError], 'CoreMail startup and cleanup both failed.');
77
+ }
78
+ throw error;
79
+ }
80
+ finally {
81
+ if (this.startPromise === startPromise) {
82
+ this.startPromise = null;
83
+ }
84
+ }
85
+ }
86
+ async startInternal() {
87
+ await this.database.init();
88
+ this.databaseStarted = true;
89
+ await Promise.all(Object.values(this.models).map((modelArg) => modelArg.init()));
90
+ await prepareCoreMailModelsForTransactions(this.models);
91
+ await this.storage.start();
92
+ this.storageStarted = true;
93
+ await this.desiredState.start();
94
+ this.gateway.start();
95
+ this.gatewayStarted = true;
96
+ await this.server.start();
97
+ this.serverStarted = true;
98
+ this.maintenance.start();
99
+ this.maintenanceStarted = true;
100
+ this.outboundWorker.start();
101
+ this.workerStarted = true;
102
+ }
103
+ async stop() {
104
+ if (this.lifecycleState === 'stopped')
105
+ return;
106
+ if (this.lifecycleState === 'stopping') {
107
+ await this.stopPromise;
108
+ return;
109
+ }
110
+ if (this.lifecycleState === 'starting') {
111
+ await this.startPromise?.catch(() => undefined);
112
+ }
113
+ this.lifecycleState = 'stopping';
114
+ const stopPromise = this.stopStartedResources();
115
+ this.stopPromise = stopPromise;
116
+ try {
117
+ await stopPromise;
118
+ this.lifecycleState = 'stopped';
119
+ }
120
+ catch (error) {
121
+ this.lifecycleState = 'failed';
122
+ throw error;
123
+ }
124
+ finally {
125
+ if (this.stopPromise === stopPromise) {
126
+ this.stopPromise = null;
127
+ }
128
+ }
129
+ }
130
+ async stopStartedResources() {
131
+ const errors = [];
132
+ const stopOne = async (startedArg, stopArg, markStoppedArg) => {
133
+ if (!startedArg)
134
+ return;
135
+ try {
136
+ await stopArg();
137
+ markStoppedArg();
138
+ }
139
+ catch (error) {
140
+ errors.push(error);
141
+ }
142
+ };
143
+ await stopOne(this.workerStarted, () => this.outboundWorker.stop(), () => { this.workerStarted = false; });
144
+ await stopOne(this.serverStarted, () => this.server.stop(), () => { this.serverStarted = false; });
145
+ await stopOne(this.maintenanceStarted, () => this.maintenance.stop(), () => { this.maintenanceStarted = false; });
146
+ await stopOne(this.gatewayStarted, () => this.gateway.stop(), () => { this.gatewayStarted = false; });
147
+ await this.transfers.stop().catch((error) => errors.push(error));
148
+ await stopOne(this.storageStarted, () => this.storage.stop(), () => { this.storageStarted = false; });
149
+ await stopOne(this.databaseStarted, () => this.database.close(), () => { this.databaseStarted = false; });
150
+ if (errors.length > 0) {
151
+ throw new AggregateError(errors, 'CoreMail lifecycle shutdown failed.');
152
+ }
153
+ }
154
+ }
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb3JlbWFpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuY29yZW1haWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3hFLE9BQU8sRUFDTCxlQUFlLEVBQ2Ysc0JBQXNCLEdBQ3ZCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDOUQsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdEUsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixvQ0FBb0MsR0FFckMsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBV2hFLE1BQU0sT0FBTyxRQUFRO0lBQ0gsTUFBTSxDQUFrQjtJQUN4QixRQUFRLENBQWdDO0lBQ3hDLE1BQU0sQ0FBa0I7SUFDeEIsT0FBTyxDQUFrQjtJQUN6QixTQUFTLENBQTBCO0lBQ25DLFlBQVksQ0FBOEI7SUFDMUMsSUFBSSxDQUFlO0lBQ25CLFdBQVcsQ0FBNEI7SUFDdkMsT0FBTyxDQUF5QjtJQUNoQyxXQUFXLENBQTZCO0lBQ3hDLE9BQU8sQ0FBa0I7SUFDekIsTUFBTSxDQUFpQjtJQUN2Qixj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