@openora/core 0.4.1-canary.129 → 0.4.1-canary.130

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 (182) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/admin-console/__tests__/backoffice.service.int.test.js +1 -0
  3. package/dist/admin-console/__tests__/backoffice.service.int.test.js.map +1 -1
  4. package/dist/admin-console/plugin.d.ts +2 -2
  5. package/dist/admin-console/service/backoffice.service.d.ts +3 -0
  6. package/dist/admin-console/service/backoffice.service.d.ts.map +1 -1
  7. package/dist/analytics/plugin.d.ts +2 -2
  8. package/dist/audit/plugin.d.ts +2 -2
  9. package/dist/casino/gaming/plugin.d.ts +2 -2
  10. package/dist/casino/lobby/plugin.d.ts +2 -2
  11. package/dist/cms/plugin.d.ts +2 -2
  12. package/dist/compliance/__tests__/rg.router.int.test.js +4 -2
  13. package/dist/compliance/__tests__/rg.router.int.test.js.map +1 -1
  14. package/dist/compliance/__tests__/rg.service.int.test.js +42 -17
  15. package/dist/compliance/__tests__/rg.service.int.test.js.map +1 -1
  16. package/dist/compliance/plugin.d.ts +2 -2
  17. package/dist/compliance/plugin.d.ts.map +1 -1
  18. package/dist/compliance/plugin.js +3 -5
  19. package/dist/compliance/plugin.js.map +1 -1
  20. package/dist/compliance/service/rg-self-service.service.d.ts.map +1 -1
  21. package/dist/compliance/service/rg-self-service.service.js +2 -2
  22. package/dist/compliance/service/rg-self-service.service.js.map +1 -1
  23. package/dist/compliance/service/rg.service.d.ts +6 -8
  24. package/dist/compliance/service/rg.service.d.ts.map +1 -1
  25. package/dist/compliance/service/rg.service.js +43 -29
  26. package/dist/compliance/service/rg.service.js.map +1 -1
  27. package/dist/contracts/adapters/admin-user-directory.d.ts +1 -0
  28. package/dist/contracts/adapters/admin-user-directory.d.ts.map +1 -1
  29. package/dist/contracts/adapters/admin-user-directory.js.map +1 -1
  30. package/dist/contracts/adapters/audit.d.ts +1 -1
  31. package/dist/contracts/adapters/audit.d.ts.map +1 -1
  32. package/dist/contracts/adapters/audit.js.map +1 -1
  33. package/dist/contracts/adapters/email-template.d.ts +6 -48
  34. package/dist/contracts/adapters/email-template.d.ts.map +1 -1
  35. package/dist/contracts/adapters/email-template.js +0 -58
  36. package/dist/contracts/adapters/email-template.js.map +1 -1
  37. package/dist/contracts/adapters/index.d.ts +4 -6
  38. package/dist/contracts/adapters/index.d.ts.map +1 -1
  39. package/dist/contracts/adapters/index.js +2 -3
  40. package/dist/contracts/adapters/index.js.map +1 -1
  41. package/dist/contracts/adapters/mail.d.ts +30 -0
  42. package/dist/contracts/adapters/mail.d.ts.map +1 -0
  43. package/dist/contracts/adapters/mail.js +4 -0
  44. package/dist/contracts/adapters/mail.js.map +1 -0
  45. package/dist/contracts/schemas/common.d.ts +1 -0
  46. package/dist/contracts/schemas/common.d.ts.map +1 -1
  47. package/dist/contracts/schemas/common.js +11 -0
  48. package/dist/contracts/schemas/common.js.map +1 -1
  49. package/dist/contracts/schemas/index.d.ts +1 -0
  50. package/dist/contracts/schemas/index.d.ts.map +1 -1
  51. package/dist/contracts/schemas/index.js +1 -0
  52. package/dist/contracts/schemas/index.js.map +1 -1
  53. package/dist/contracts/schemas/mail.d.ts +166 -0
  54. package/dist/contracts/schemas/mail.d.ts.map +1 -0
  55. package/dist/contracts/schemas/mail.js +74 -0
  56. package/dist/contracts/schemas/mail.js.map +1 -0
  57. package/dist/engagement/chat/__tests__/chat.service.int.test.js +4 -0
  58. package/dist/engagement/chat/__tests__/chat.service.int.test.js.map +1 -1
  59. package/dist/engagement/chat/plugin.d.ts +2 -2
  60. package/dist/engagement/chat-commands/plugin.d.ts +2 -2
  61. package/dist/engagement/notifications/__tests__/chat-room-notifications.int.test.js +8 -11
  62. package/dist/engagement/notifications/__tests__/chat-room-notifications.int.test.js.map +1 -1
  63. package/dist/engagement/notifications/__tests__/notification-event-map.test.js +76 -39
  64. package/dist/engagement/notifications/__tests__/notification-event-map.test.js.map +1 -1
  65. package/dist/engagement/notifications/plugin.d.ts +8 -7
  66. package/dist/engagement/notifications/plugin.d.ts.map +1 -1
  67. package/dist/engagement/notifications/plugin.js +102 -86
  68. package/dist/engagement/notifications/plugin.js.map +1 -1
  69. package/dist/engagement/social/plugin.d.ts +2 -2
  70. package/dist/fx/exchange-rate/plugin.d.ts +2 -2
  71. package/dist/iam/__tests__/iam.service.int.test.js +53 -46
  72. package/dist/iam/__tests__/iam.service.int.test.js.map +1 -1
  73. package/dist/iam/plugin.d.ts +3 -2
  74. package/dist/iam/plugin.d.ts.map +1 -1
  75. package/dist/iam/plugin.js +3 -2
  76. package/dist/iam/plugin.js.map +1 -1
  77. package/dist/iam/service/iam.service.d.ts +3 -3
  78. package/dist/iam/service/iam.service.d.ts.map +1 -1
  79. package/dist/iam/service/iam.service.js +11 -7
  80. package/dist/iam/service/iam.service.js.map +1 -1
  81. package/dist/mail/__tests__/default-email-template-renderer.test.d.ts.map +1 -0
  82. package/dist/mail/__tests__/default-email-template-renderer.test.js +119 -0
  83. package/dist/mail/__tests__/default-email-template-renderer.test.js.map +1 -0
  84. package/dist/mail/__tests__/mail.service.test.d.ts +2 -0
  85. package/dist/mail/__tests__/mail.service.test.d.ts.map +1 -0
  86. package/dist/mail/__tests__/mail.service.test.js +215 -0
  87. package/dist/mail/__tests__/mail.service.test.js.map +1 -0
  88. package/dist/mail/adapters/default-email-template-renderer.d.ts +5 -0
  89. package/dist/mail/adapters/default-email-template-renderer.d.ts.map +1 -0
  90. package/dist/mail/adapters/default-email-template-renderer.js +107 -0
  91. package/dist/mail/adapters/default-email-template-renderer.js.map +1 -0
  92. package/dist/mail/adapters/stdout-email-sender.d.ts +5 -0
  93. package/dist/mail/adapters/stdout-email-sender.d.ts.map +1 -0
  94. package/dist/mail/adapters/stdout-email-sender.js +8 -0
  95. package/dist/mail/adapters/stdout-email-sender.js.map +1 -0
  96. package/dist/mail/contract/index.d.ts +120 -0
  97. package/dist/mail/contract/index.d.ts.map +1 -0
  98. package/dist/mail/contract/index.js +17 -0
  99. package/dist/mail/contract/index.js.map +1 -0
  100. package/dist/mail/index.d.ts +5 -0
  101. package/dist/mail/index.d.ts.map +1 -0
  102. package/dist/mail/index.js +5 -0
  103. package/dist/mail/index.js.map +1 -0
  104. package/dist/mail/plugin.d.ts +181 -0
  105. package/dist/mail/plugin.d.ts.map +1 -0
  106. package/dist/mail/plugin.js +66 -0
  107. package/dist/mail/plugin.js.map +1 -0
  108. package/dist/mail/service/mail-payload.service.d.ts +8 -0
  109. package/dist/mail/service/mail-payload.service.d.ts.map +1 -0
  110. package/dist/mail/service/mail-payload.service.js +43 -0
  111. package/dist/mail/service/mail-payload.service.js.map +1 -0
  112. package/dist/mail/service/mail.service.d.ts +30 -0
  113. package/dist/mail/service/mail.service.d.ts.map +1 -0
  114. package/dist/mail/service/mail.service.js +152 -0
  115. package/dist/mail/service/mail.service.js.map +1 -0
  116. package/dist/pam/identity/__tests__/identity.rate-limit.int.test.js +0 -4
  117. package/dist/pam/identity/__tests__/identity.rate-limit.int.test.js.map +1 -1
  118. package/dist/pam/identity/__tests__/identity.registration-gates.int.test.js +0 -4
  119. package/dist/pam/identity/__tests__/identity.registration-gates.int.test.js.map +1 -1
  120. package/dist/pam/identity/__tests__/identity.service.int.test.js +13 -4
  121. package/dist/pam/identity/__tests__/identity.service.int.test.js.map +1 -1
  122. package/dist/pam/identity/admin-user-directory.d.ts +4 -0
  123. package/dist/pam/identity/admin-user-directory.d.ts.map +1 -1
  124. package/dist/pam/identity/admin-user-directory.js +1 -0
  125. package/dist/pam/identity/admin-user-directory.js.map +1 -1
  126. package/dist/pam/identity/plugin.d.ts +3 -2
  127. package/dist/pam/identity/plugin.d.ts.map +1 -1
  128. package/dist/pam/identity/plugin.js +3 -9
  129. package/dist/pam/identity/plugin.js.map +1 -1
  130. package/dist/pam/identity/service/identity.service.d.ts +5 -7
  131. package/dist/pam/identity/service/identity.service.d.ts.map +1 -1
  132. package/dist/pam/identity/service/identity.service.js +40 -23
  133. package/dist/pam/identity/service/identity.service.js.map +1 -1
  134. package/dist/pam/player-management/plugin.d.ts +2 -2
  135. package/dist/pam/player-note/plugin.d.ts +2 -2
  136. package/dist/pam/profile/plugin.d.ts +2 -2
  137. package/dist/pam/shared/__tests__/shared-mappers.test.js +6 -0
  138. package/dist/pam/shared/__tests__/shared-mappers.test.js.map +1 -1
  139. package/dist/pam/shared/language.d.ts.map +1 -1
  140. package/dist/pam/shared/language.js +6 -0
  141. package/dist/pam/shared/language.js.map +1 -1
  142. package/dist/pam/tag/plugin.d.ts +2 -2
  143. package/dist/server/auth/__tests__/auth.test.js +45 -50
  144. package/dist/server/auth/__tests__/auth.test.js.map +1 -1
  145. package/dist/server/auth/auth.d.ts +7 -8
  146. package/dist/server/auth/auth.d.ts.map +1 -1
  147. package/dist/server/auth/auth.js +10 -20
  148. package/dist/server/auth/auth.js.map +1 -1
  149. package/dist/server/auth/index.d.ts +1 -1
  150. package/dist/server/auth/index.d.ts.map +1 -1
  151. package/dist/server/plugin-host/core-plugins.d.ts.map +1 -1
  152. package/dist/server/plugin-host/core-plugins.js +1 -0
  153. package/dist/server/plugin-host/core-plugins.js.map +1 -1
  154. package/dist/server/runtime/core-token-catalog.d.ts +2 -2
  155. package/dist/server/runtime/core-token-catalog.js +3 -3
  156. package/dist/server/runtime/core-token-catalog.js.map +1 -1
  157. package/dist/server/runtime/create-app.d.ts.map +1 -1
  158. package/dist/server/runtime/create-app.js +7 -7
  159. package/dist/server/runtime/create-app.js.map +1 -1
  160. package/dist/wallet/plugin.d.ts +2 -2
  161. package/generators/src/config.ts +1 -2
  162. package/package.json +21 -1
  163. package/dist/contracts/adapters/email.d.ts +0 -17
  164. package/dist/contracts/adapters/email.d.ts.map +0 -1
  165. package/dist/contracts/adapters/email.js +0 -10
  166. package/dist/contracts/adapters/email.js.map +0 -1
  167. package/dist/contracts/adapters/notification.d.ts +0 -13
  168. package/dist/contracts/adapters/notification.d.ts.map +0 -1
  169. package/dist/contracts/adapters/notification.js +0 -10
  170. package/dist/contracts/adapters/notification.js.map +0 -1
  171. package/dist/engagement/notifications/adapters/mock/mock-notification-adapter.d.ts +0 -5
  172. package/dist/engagement/notifications/adapters/mock/mock-notification-adapter.d.ts.map +0 -1
  173. package/dist/engagement/notifications/adapters/mock/mock-notification-adapter.js +0 -6
  174. package/dist/engagement/notifications/adapters/mock/mock-notification-adapter.js.map +0 -1
  175. package/dist/pam/identity/adapters/__tests__/default-email-template-renderer.test.d.ts.map +0 -1
  176. package/dist/pam/identity/adapters/__tests__/default-email-template-renderer.test.js +0 -33
  177. package/dist/pam/identity/adapters/__tests__/default-email-template-renderer.test.js.map +0 -1
  178. package/dist/pam/identity/adapters/default-email-template-renderer.d.ts +0 -8
  179. package/dist/pam/identity/adapters/default-email-template-renderer.d.ts.map +0 -1
  180. package/dist/pam/identity/adapters/default-email-template-renderer.js +0 -7
  181. package/dist/pam/identity/adapters/default-email-template-renderer.js.map +0 -1
  182. /package/dist/{pam/identity/adapters → mail}/__tests__/default-email-template-renderer.test.d.ts +0 -0
@@ -0,0 +1,107 @@
1
+ import { formatMoneyAmount, } from '@openora/core/contracts';
2
+ const DEFAULT_LOCALE = 'en';
3
+ const escapeHtml = (value) => value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
4
+ const textToHtml = (text) => text
5
+ .split(/\n{2,}/)
6
+ .map((block) => `<p>${escapeHtml(block).replace(/\n/g, '<br>')}</p>`)
7
+ .join('\n');
8
+ const DATE_FORMAT_OPTS = { dateStyle: 'long', timeStyle: 'short', timeZone: 'UTC' };
9
+ const dateFormatter = (locale) => {
10
+ try {
11
+ return new Intl.DateTimeFormat(locale, DATE_FORMAT_OPTS);
12
+ }
13
+ catch {
14
+ return new Intl.DateTimeFormat(DEFAULT_LOCALE, DATE_FORMAT_OPTS);
15
+ }
16
+ };
17
+ const formatEmailDate = (iso, locale) => iso === null ? 'further notice' : `${dateFormatter(locale).format(new Date(iso))} UTC`;
18
+ const formatMoney = (amount, currency) => `${formatMoneyAmount(amount)} ${currency}`;
19
+ const PLAIN_EMAIL_TEMPLATES = {
20
+ verifyEmail: (data) => ({
21
+ subject: 'Verify your email',
22
+ text: `Your email verification code is: ${data.otp}`,
23
+ }),
24
+ resetPasswordOtp: (data) => ({
25
+ subject: 'Reset your password',
26
+ text: `Your password reset code is: ${data.otp}`,
27
+ }),
28
+ adminResetPasswordOtp: (data) => ({
29
+ subject: 'Password reset requested by an administrator',
30
+ text: `An administrator requested a password reset for your account. Your reset code is: ${data.otp}`,
31
+ }),
32
+ existingAccountSignUp: (data) => ({
33
+ subject: 'You already have an account',
34
+ text: `Someone tried to create an account with this email address. ` +
35
+ `You already have one, so no new account was created. ` +
36
+ `If it was you, sign in as usual - or use this code to reset your password: ${data.otp}`,
37
+ }),
38
+ rgLimitUpdated: (data) => {
39
+ const value = data.amount !== null
40
+ ? formatMoney(data.amount, data.currency ?? '')
41
+ : `${data.minutes} minutes`;
42
+ return {
43
+ subject: 'Your gambling limit was updated',
44
+ text: `A ${data.period} ${data.type} limit of ${value.trim()} is now active on your account.`,
45
+ };
46
+ },
47
+ rgCoolingOffActivated: (data, locale) => ({
48
+ subject: 'Your cooling-off period has started',
49
+ text: `A cooling-off period is active on your account until ${formatEmailDate(data.expiresAt, locale)}.\n\nYou will not be able to log in or place bets until then.`,
50
+ }),
51
+ rgCoolingOffLifted: () => ({
52
+ subject: 'Your cooling-off period has ended',
53
+ text: 'Your cooling-off period has been ended and you can log in again.',
54
+ }),
55
+ rgSelfExclusionActivated: (data, locale) => ({
56
+ subject: 'Your self-exclusion has started',
57
+ text: data.isPermanent
58
+ ? 'Your account has been permanently self-excluded and you will not be able to log in.'
59
+ : `Your account is self-excluded until ${formatEmailDate(data.expiresAt, locale)}.\n\nYou will not be able to log in until then.`,
60
+ }),
61
+ rgSelfExclusionLifted: () => ({
62
+ subject: 'Your self-exclusion has been lifted',
63
+ text: 'Your self-exclusion has been lifted and you can log in again.',
64
+ }),
65
+ withdrawalApproved: (data, locale) => ({
66
+ subject: 'Your withdrawal was approved',
67
+ text: `Your withdrawal of ${formatMoney(data.amount, data.currency)} has been approved and is being processed.\n\n` +
68
+ `Transaction: ${data.transactionId}\nDate: ${formatEmailDate(data.occurredAt, locale)}`,
69
+ }),
70
+ withdrawalRejected: (data, locale) => ({
71
+ subject: 'Your withdrawal was rejected',
72
+ text: `Your withdrawal of ${formatMoney(data.amount, data.currency)} was rejected and the funds were returned to your balance.\n\n` +
73
+ `Transaction: ${data.transactionId}\nDate: ${formatEmailDate(data.occurredAt, locale)}` +
74
+ (data.reason ? `\nReason: ${data.reason}` : ''),
75
+ }),
76
+ kycResubmissionRequested: (data) => ({
77
+ subject: 'Document resubmission required',
78
+ text: `An admin has requested you resubmit your verification documents.` +
79
+ (data.reason ? ` Reason: ${data.reason}.` : ''),
80
+ }),
81
+ adminInvitation: (data, locale) => ({
82
+ subject: 'You have been invited as an administrator',
83
+ text: `Your admin invitation token: ${data.token}. It expires at ${formatEmailDate(data.expiresAt, locale)}.`,
84
+ }),
85
+ securityLoginAlert: (data, locale) => ({
86
+ subject: 'New sign-in to your account',
87
+ text: `A new sign-in to your account was detected on ${formatEmailDate(data.occurredAt, locale)}.\n\n` +
88
+ `If this was not you, secure your account immediately.`,
89
+ }),
90
+ securityWithdrawalRequested: (data, locale) => ({
91
+ subject: 'Withdrawal requested on your account',
92
+ text: `A withdrawal of ${formatMoney(data.amount, data.currency)} was requested on your account and is pending review.\n\n` +
93
+ `Transaction: ${data.transactionId}\nDate: ${formatEmailDate(data.occurredAt, locale)}\n\n` +
94
+ `If this was not you, secure your account immediately.`,
95
+ }),
96
+ };
97
+ const renderDefaultEmail = (template, locale) => {
98
+ const plain = PLAIN_EMAIL_TEMPLATES[template.key];
99
+ const { subject, text } = plain(template.data, locale);
100
+ return { subject, text, html: textToHtml(text) };
101
+ };
102
+ export class DefaultEmailTemplateRenderer {
103
+ render(template, locale) {
104
+ return renderDefaultEmail(template, locale);
105
+ }
106
+ }
107
+ //# sourceMappingURL=default-email-template-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-email-template-renderer.js","sourceRoot":"","sources":["../../../src/mail/adapters/default-email-template-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { EmailMessage, EmailSenderPort } from '@openora/core/contracts';
2
+ export declare class StdoutEmailSender implements EmailSenderPort {
3
+ send(message: EmailMessage): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=stdout-email-sender.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdout-email-sender.d.ts","sourceRoot":"","sources":["../../../src/mail/adapters/stdout-email-sender.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI7E,qBAAa,iBAAkB,YAAW,eAAe;IACjD,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAMjD"}
@@ -0,0 +1,8 @@
1
+ import { createLogger } from '@openora/core/server';
2
+ const logger = createLogger('mail');
3
+ export class StdoutEmailSender {
4
+ async send(message) {
5
+ logger.info({ to: message.to, subject: message.subject, bytes: message.html.length }, 'mock email delivery (no EMAIL_SENDER overlay bound)');
6
+ }
7
+ }
8
+ //# sourceMappingURL=stdout-email-sender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdout-email-sender.js","sourceRoot":"","sources":["../../../src/mail/adapters/stdout-email-sender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAEpC,MAAM,OAAO,iBAAiB;IAC5B,KAAK,CAAC,IAAI,CAAC,OAAqB;QAC9B,MAAM,CAAC,IAAI,CACT,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EACxE,qDAAqD,CACtD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,120 @@
1
+ import * as z from 'zod';
2
+ export declare const MAIL_SEND_QUEUE: import("@openora/core/contracts").QueueName;
3
+ export declare const MailRecipientSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4
+ kind: z.ZodLiteral<"user">;
5
+ userId: z.ZodUUID;
6
+ }, z.core.$strip>, z.ZodObject<{
7
+ kind: z.ZodLiteral<"address">;
8
+ email: z.ZodEmail;
9
+ locale: z.ZodOptional<z.ZodString>;
10
+ }, z.core.$strip>], "kind">;
11
+ export type MailRecipient = z.infer<typeof MailRecipientSchema>;
12
+ export declare const MailSendJobSchema: z.ZodObject<{
13
+ recipient: z.ZodDiscriminatedUnion<[z.ZodObject<{
14
+ kind: z.ZodLiteral<"user">;
15
+ userId: z.ZodUUID;
16
+ }, z.core.$strip>, z.ZodObject<{
17
+ kind: z.ZodLiteral<"address">;
18
+ email: z.ZodEmail;
19
+ locale: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>], "kind">;
21
+ template: z.ZodDiscriminatedUnion<[z.ZodObject<{
22
+ key: z.ZodLiteral<"verifyEmail">;
23
+ data: z.ZodObject<{
24
+ otp: z.ZodString;
25
+ }, z.core.$strip>;
26
+ }, z.core.$strip>, z.ZodObject<{
27
+ key: z.ZodLiteral<"resetPasswordOtp">;
28
+ data: z.ZodObject<{
29
+ otp: z.ZodString;
30
+ email: z.ZodEmail;
31
+ }, z.core.$strip>;
32
+ }, z.core.$strip>, z.ZodObject<{
33
+ key: z.ZodLiteral<"adminResetPasswordOtp">;
34
+ data: z.ZodObject<{
35
+ otp: z.ZodString;
36
+ email: z.ZodEmail;
37
+ }, z.core.$strip>;
38
+ }, z.core.$strip>, z.ZodObject<{
39
+ key: z.ZodLiteral<"existingAccountSignUp">;
40
+ data: z.ZodObject<{
41
+ otp: z.ZodString;
42
+ email: z.ZodEmail;
43
+ }, z.core.$strip>;
44
+ }, z.core.$strip>, z.ZodObject<{
45
+ key: z.ZodLiteral<"rgLimitUpdated">;
46
+ data: z.ZodObject<{
47
+ period: z.ZodString;
48
+ type: z.ZodString;
49
+ amount: z.ZodNullable<z.ZodString>;
50
+ currency: z.ZodNullable<z.ZodString>;
51
+ minutes: z.ZodNullable<z.ZodNumber>;
52
+ }, z.core.$strip>;
53
+ }, z.core.$strip>, z.ZodObject<{
54
+ key: z.ZodLiteral<"rgCoolingOffActivated">;
55
+ data: z.ZodObject<{
56
+ expiresAt: z.ZodISODateTime;
57
+ }, z.core.$strip>;
58
+ }, z.core.$strip>, z.ZodObject<{
59
+ key: z.ZodLiteral<"rgCoolingOffLifted">;
60
+ data: z.ZodObject<{}, z.core.$strip>;
61
+ }, z.core.$strip>, z.ZodObject<{
62
+ key: z.ZodLiteral<"rgSelfExclusionActivated">;
63
+ data: z.ZodObject<{
64
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
65
+ isPermanent: z.ZodBoolean;
66
+ }, z.core.$strip>;
67
+ }, z.core.$strip>, z.ZodObject<{
68
+ key: z.ZodLiteral<"rgSelfExclusionLifted">;
69
+ data: z.ZodObject<{}, z.core.$strip>;
70
+ }, z.core.$strip>, z.ZodObject<{
71
+ key: z.ZodLiteral<"withdrawalApproved">;
72
+ data: z.ZodObject<{
73
+ amount: z.ZodString;
74
+ currency: z.ZodString;
75
+ transactionId: z.ZodUUID;
76
+ occurredAt: z.ZodISODateTime;
77
+ }, z.core.$strip>;
78
+ }, z.core.$strip>, z.ZodObject<{
79
+ key: z.ZodLiteral<"withdrawalRejected">;
80
+ data: z.ZodObject<{
81
+ reason: z.ZodNullable<z.ZodString>;
82
+ amount: z.ZodString;
83
+ currency: z.ZodString;
84
+ transactionId: z.ZodUUID;
85
+ occurredAt: z.ZodISODateTime;
86
+ }, z.core.$strip>;
87
+ }, z.core.$strip>, z.ZodObject<{
88
+ key: z.ZodLiteral<"kycResubmissionRequested">;
89
+ data: z.ZodObject<{
90
+ reason: z.ZodNullable<z.ZodString>;
91
+ }, z.core.$strip>;
92
+ }, z.core.$strip>, z.ZodObject<{
93
+ key: z.ZodLiteral<"adminInvitation">;
94
+ data: z.ZodObject<{
95
+ token: z.ZodString;
96
+ expiresAt: z.ZodISODateTime;
97
+ }, z.core.$strip>;
98
+ }, z.core.$strip>, z.ZodObject<{
99
+ key: z.ZodLiteral<"securityLoginAlert">;
100
+ data: z.ZodObject<{
101
+ occurredAt: z.ZodISODateTime;
102
+ }, z.core.$strip>;
103
+ }, z.core.$strip>, z.ZodObject<{
104
+ key: z.ZodLiteral<"securityWithdrawalRequested">;
105
+ data: z.ZodObject<{
106
+ amount: z.ZodString;
107
+ currency: z.ZodString;
108
+ transactionId: z.ZodUUID;
109
+ occurredAt: z.ZodISODateTime;
110
+ }, z.core.$strip>;
111
+ }, z.core.$strip>], "key">;
112
+ }, z.core.$strip>;
113
+ export type MailSendJob = z.infer<typeof MailSendJobSchema>;
114
+ export declare const EncryptedMailSendJobSchema: z.ZodObject<{
115
+ ciphertext: z.ZodString;
116
+ iv: z.ZodString;
117
+ tag: z.ZodString;
118
+ }, z.core.$strip>;
119
+ export type EncryptedMailSendJob = z.infer<typeof EncryptedMailSendJobSchema>;
120
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mail/contract/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAGzB,eAAO,MAAM,eAAe,6CAAqB,CAAC;AAElD,eAAO,MAAM,mBAAmB;;;;;;;2BAG9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,0BAA0B;;;;iBAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import * as z from 'zod';
2
+ import { MailTemplateSchema, UuidSchema, queue } from '@openora/core/contracts';
3
+ export const MAIL_SEND_QUEUE = queue('mail-send');
4
+ export const MailRecipientSchema = z.discriminatedUnion('kind', [
5
+ z.object({ kind: z.literal('user'), userId: UuidSchema }),
6
+ z.object({ kind: z.literal('address'), email: z.email(), locale: z.string().optional() }),
7
+ ]);
8
+ export const MailSendJobSchema = z.object({
9
+ recipient: MailRecipientSchema,
10
+ template: MailTemplateSchema,
11
+ });
12
+ export const EncryptedMailSendJobSchema = z.object({
13
+ ciphertext: z.string().min(1),
14
+ iv: z.string().min(1),
15
+ tag: z.string().min(1),
16
+ });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mail/contract/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEhF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC9D,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACzD,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;CAC1F,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,SAAS,EAAE,mBAAmB;IAC9B,QAAQ,EAAE,kBAAkB;CAC7B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACvB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { MailService, type MailServiceDeps } from './service/mail.service.js';
2
+ export { DefaultEmailTemplateRenderer } from './adapters/default-email-template-renderer.js';
3
+ export { StdoutEmailSender } from './adapters/stdout-email-sender.js';
4
+ export { MAIL_SEND_QUEUE, EncryptedMailSendJobSchema, MailSendJobSchema, MailRecipientSchema, type EncryptedMailSendJob, type MailSendJob, type MailRecipient, } from './contract/index.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { MailService } from './service/mail.service.js';
2
+ export { DefaultEmailTemplateRenderer } from './adapters/default-email-template-renderer.js';
3
+ export { StdoutEmailSender } from './adapters/stdout-email-sender.js';
4
+ export { MAIL_SEND_QUEUE, EncryptedMailSendJobSchema, MailSendJobSchema, MailRecipientSchema, } from './contract/index.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwB,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,181 @@
1
+ declare const _default: {
2
+ readonly id: "mail";
3
+ readonly register: (ctx: import("@openora/core/server").PluginContext<{
4
+ ADMIN_GAME_REPORTING: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminGameReporting>;
5
+ ADMIN_GUARD: import("@openora/core/contracts").Token<import("@openora/core/server").AdminGuard>;
6
+ ADMIN_PERMISSION_RESOLVER: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminPermissionResolver>;
7
+ ADMIN_PLAYER_ACTIVITY: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminPlayerActivity>;
8
+ ADMIN_ROLE_ASSIGNMENT_DIRECTORY: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminRoleAssignmentDirectory>;
9
+ ADMIN_SECURITY_POLICY: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminSecurityPolicy>;
10
+ ADMIN_USER_DIRECTORY: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminUserDirectory>;
11
+ ADMIN_WALLET_REPORTING: import("@openora/core/contracts").Token<import("@openora/core/contracts").AdminWalletReporting>;
12
+ AUDIT_WRITER: import("@openora/core/contracts").SealedToken<import("@openora/core/contracts").AuditWritePort>;
13
+ AUTH_SESSION: import("@openora/core/contracts").Token<import("@openora/core/server").SessionResolver>;
14
+ CACHE: import("@openora/core/contracts").Token<import("@openora/core/contracts").CacheAdapter>;
15
+ CHAT_BLOCK_WRITER: import("@openora/core/contracts").Token<import("@openora/core/contracts").ChatBlockWriter>;
16
+ CHAT_MODERATION: import("@openora/core/contracts").Token<import("@openora/core/contracts").ChatModeration, string>;
17
+ CHAT_REALTIME_CLIENT_AUTHORIZER: import("@openora/core/contracts").Token<import("@openora/core/contracts").RealtimeClientAuthorizer>;
18
+ CHAT_REALTIME_TRANSPORT: import("@openora/core/contracts").Token<import("@openora/core/contracts").RealtimeTransport>;
19
+ CHAT_ROOM_ACCESS: import("@openora/core/contracts").Token<import("@openora/core/contracts").ChatRoomAccess>;
20
+ CHAT_SYSTEM_WRITER: import("@openora/core/contracts").Token<import("@openora/core/contracts").ChatSystemWriter, string>;
21
+ DRIZZLE: import("@openora/core/contracts").Token<import("@openora/core/server").DrizzleService>;
22
+ EMAIL_SENDER: import("@openora/core/contracts").Token<import("@openora/core/contracts").EmailSenderPort>;
23
+ EMAIL_TEMPLATE_RENDERER: import("@openora/core/contracts").Token<import("@openora/core/contracts").EmailTemplateRenderer>;
24
+ ERROR_TRACKING: import("@openora/core/contracts").Token<import("@openora/core/contracts").ErrorTrackingAdapter>;
25
+ EVENT_BUS: import("@openora/core/contracts").Token<import("@openora/core/server").EventBus>;
26
+ EXCHANGE_RATE_READER: import("@openora/core/contracts").Token<import("@openora/core/contracts").ExchangeRateReader>;
27
+ CRYPTO_EXCHANGE_RATE_PROVIDER: import("@openora/core/contracts").Token<import("@openora/core/contracts").ExchangeRateProvider>;
28
+ FIAT_EXCHANGE_RATE_PROVIDER: import("@openora/core/contracts").Token<import("@openora/core/contracts").ExchangeRateProvider>;
29
+ SWAP_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").SwapAdapter>;
30
+ SWAP_WEBHOOK_VERIFIER: import("@openora/core/contracts").Token<import("@openora/core/contracts").SwapWebhookVerifier>;
31
+ GAME_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").GameAdapter>;
32
+ GEO_CHECK_COMMANDS: import("@openora/core/contracts").Token<import("@openora/core/contracts").GeoCheckCommands>;
33
+ GEO_IP_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").GeoIpAdapter>;
34
+ IDENTITY_OPTIONS: import("@openora/core/contracts").Token<import("@openora/core/contracts").IdentityServiceOptions>;
35
+ IDENTITY_READER: import("@openora/core/contracts").Token<import("@openora/core/contracts").IdentityReader, string>;
36
+ IGAMING_CONFIG: import("@openora/core/contracts").Token<{
37
+ branding: {
38
+ name: string;
39
+ themePreset?: string | undefined;
40
+ supportEmail?: string | undefined;
41
+ };
42
+ currencies: string[];
43
+ jurisdictions: string[];
44
+ blockedCountries: string[];
45
+ limits: {
46
+ maxDepositPerDay?: number | undefined;
47
+ maxDepositPerMonth?: number | undefined;
48
+ maxLossPerDay?: number | undefined;
49
+ maxStakePerBet?: number | undefined;
50
+ sessionReminderMinutes?: number | undefined;
51
+ };
52
+ providers: {
53
+ payment?: string | undefined;
54
+ kyc?: string | undefined;
55
+ geoIp?: string | undefined;
56
+ aggregator?: string | undefined;
57
+ notification?: string | undefined;
58
+ };
59
+ enabledModules?: string[] | undefined;
60
+ }, string>;
61
+ JOB_QUEUE: import("@openora/core/contracts").Token<import("@openora/core/contracts").JobQueueAdapter>;
62
+ KYC_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").KycAdapter>;
63
+ KYC_STATUS_WRITER: import("@openora/core/contracts").Token<import("@openora/core/contracts").KycStatusWriter>;
64
+ KYC_WEBHOOK_VERIFIER: import("@openora/core/contracts").Token<import("@openora/core/contracts").KycWebhookVerifier>;
65
+ LOGIN_ENFORCEMENT: import("@openora/core/contracts").Token<import("@openora/core/contracts").LoginEnforcementPort>;
66
+ MAIL_DISPATCH: import("@openora/core/contracts").Token<import("@openora/core/contracts").MailDispatchPort>;
67
+ MESSAGE_BROKER: import("@openora/core/contracts").Token<import("@openora/core/contracts").MessageBrokerAdapter>;
68
+ OUTBOX: import("@openora/core/contracts").Token<import("@openora/core/contracts").OutboxWriter>;
69
+ PAYMENT_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").PaymentAdapter>;
70
+ PAYMENT_PROVIDERS: import("@openora/core/contracts").Token<import("@openora/core/contracts").PaymentProviderRegistry>;
71
+ PAYMENT_WEBHOOK_VERIFIER: import("@openora/core/contracts").Token<import("@openora/core/contracts").PaymentWebhookVerifier>;
72
+ PLATFORM_CONFIG: import("@openora/core/contracts").Token<{
73
+ features: Record<string, boolean>;
74
+ brands: {
75
+ id: string;
76
+ name: string;
77
+ themePreset?: string | undefined;
78
+ themeOverrides?: Record<string, string> | undefined;
79
+ }[];
80
+ rgLimits: Record<string, {
81
+ maxDepositPerDay?: number | undefined;
82
+ maxDepositPerMonth?: number | undefined;
83
+ maxLossPerDay?: number | undefined;
84
+ maxStakePerBet?: number | undefined;
85
+ sessionReminderMinutes?: number | undefined;
86
+ }>;
87
+ responsibleGambling: {
88
+ limitIncreaseCooldownHours: number;
89
+ limitChangeConfirmationWindowHours: number;
90
+ };
91
+ chat: {
92
+ allowedAttachmentHosts: string[];
93
+ moderationExpiry?: {
94
+ cron: string;
95
+ } | undefined;
96
+ };
97
+ adminSecurity: {
98
+ requireTwoFactor: boolean;
99
+ bindSessionToDevice: boolean;
100
+ trustedDeviceDays: number;
101
+ ipChangePolicy: "any" | "country" | "off";
102
+ twoFactorLockout: {
103
+ maxAttempts: number;
104
+ durationMs: number;
105
+ };
106
+ };
107
+ cms: {
108
+ allowedBannerImageHosts: string[];
109
+ };
110
+ activeBrand?: string | undefined;
111
+ kyc?: {
112
+ gateWithdrawals: boolean;
113
+ provider?: string | undefined;
114
+ webhookSecretEnv?: string | undefined;
115
+ reverifyThresholds?: Record<string, string> | undefined;
116
+ } | undefined;
117
+ autoWithdrawal?: {
118
+ enabled: boolean;
119
+ dailyCapAmount?: string | undefined;
120
+ dailyCapCount?: number | undefined;
121
+ } | undefined;
122
+ wallet?: {
123
+ cryptoCurrencies?: string[] | undefined;
124
+ treasuryRefs?: Record<string, string> | undefined;
125
+ sweep?: {
126
+ cron: string;
127
+ feeMultiple: string;
128
+ batchSize: number;
129
+ concurrency: number;
130
+ unknownAfterMinutes: number;
131
+ staleRunAfterMinutes: number;
132
+ } | undefined;
133
+ reconciliation?: {
134
+ cron: string;
135
+ lookbackHours: number;
136
+ batchSize: number;
137
+ stuckAfterMinutes: number;
138
+ staleRunAfterMinutes: number;
139
+ alertThreshold: number;
140
+ } | undefined;
141
+ } | undefined;
142
+ exchangeRate?: {
143
+ pivot: string;
144
+ freshTtlMs: number;
145
+ hardMaxAgeMs: number;
146
+ providerTimeoutMs: number;
147
+ } | undefined;
148
+ registration?: {
149
+ termsVersion: string;
150
+ requireEmailVerification: boolean;
151
+ } | undefined;
152
+ notifications?: {
153
+ retention?: {
154
+ days: number;
155
+ cron: string;
156
+ } | undefined;
157
+ } | undefined;
158
+ supportedLanguages?: string[] | undefined;
159
+ displayCurrencies?: string[] | undefined;
160
+ }, string>;
161
+ PLAYER_ACTIVITY_TRACKER: import("@openora/core/contracts").Token<import("@openora/core/contracts").PlayerActivityTracker>;
162
+ PLAYER_PROVISIONING: import("@openora/core/contracts").Token<import("@openora/core/contracts").PlayerProvisioning>;
163
+ PLAYER_TAGS: import("@openora/core/contracts").Token<import("@openora/core/contracts").PlayerTags>;
164
+ PLAY_ELIGIBILITY: import("@openora/core/contracts").Token<import("@openora/core/contracts").PlayEligibilityPort>;
165
+ RATE_LIMITER: import("@openora/core/contracts").Token<import("@openora/core/contracts").RateLimiterAdapter<`register:${string}` | `login:${string}` | `enable2fa:${string}` | `verify2fa:${string}` | `disable2fa:${string}` | `pwreset-req:${string}` | `pwreset-verify:${string}` | `pwreset:${string}` | `change-password:${string}` | `email-verify:${string}` | `verify-email:${string}` | `wallet-mutation:${string}` | `wallet-webhook:${string}` | `chat-room-join:${string}` | `chat-send:${string}` | `report-access-denied:${string}`>>;
166
+ REALTIME_CLIENT_AUTHORIZER: import("@openora/core/contracts").Token<import("@openora/core/contracts").RealtimeClientAuthorizer>;
167
+ REALTIME_TRANSPORT: import("@openora/core/contracts").Token<import("@openora/core/contracts").RealtimeTransport>;
168
+ RG_LIMITS: import("@openora/core/contracts").Token<import("@openora/core/contracts").RgLimitsPort>;
169
+ RNG_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").RngAdapter>;
170
+ SESSION_COMMANDS: import("@openora/core/contracts").Token<import("@openora/core/contracts").SessionCommands>;
171
+ USER_COMMANDS: import("@openora/core/contracts").Token<import("@openora/core/contracts").UserCommands>;
172
+ SMS_ADAPTER: import("@openora/core/contracts").Token<import("@openora/core/contracts").SmsAdapter>;
173
+ SOCIAL_COMMANDS: import("@openora/core/contracts").Token<import("@openora/core/contracts").SocialCommands>;
174
+ TAG_EVALUATION_COMMANDS: import("@openora/core/contracts").Token<import("@openora/core/contracts").TagEvaluationCommands>;
175
+ WALLET_ASSET_CATALOG: import("@openora/core/contracts").Token<import("@openora/core/contracts").WalletAssetCatalog, string>;
176
+ WALLET_COMMANDS: import("@openora/core/contracts").Token<import("@openora/core/contracts").WalletCommands>;
177
+ WALLET_READER: import("@openora/core/contracts").Token<import("@openora/core/contracts").WalletReader, string>;
178
+ }>) => void;
179
+ };
180
+ export default _default;
181
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/mail/plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,wBAiE8C"}
@@ -0,0 +1,66 @@
1
+ import { ADMIN_USER_DIRECTORY, AUDIT_WRITER, EMAIL_SENDER, EMAIL_TEMPLATE_RENDERER, JOB_QUEUE, MAIL_DISPATCH, } from '@openora/core/contracts';
2
+ import { createLogger } from '@openora/core/server';
3
+ import { MailService } from './service/mail.service.js';
4
+ import { MIN_MAIL_ENCRYPTION_SECRET_LENGTH } from './service/mail-payload.service.js';
5
+ import { DefaultEmailTemplateRenderer } from './adapters/default-email-template-renderer.js';
6
+ import { StdoutEmailSender } from './adapters/stdout-email-sender.js';
7
+ import { EncryptedMailSendJobSchema, MAIL_SEND_QUEUE } from './contract/index.js';
8
+ const logger = createLogger('mail');
9
+ export default {
10
+ id: 'mail',
11
+ register(ctx) {
12
+ const encryptionSecret = process.env['AUTH_SECRET'] ?? '';
13
+ if (encryptionSecret.length < MIN_MAIL_ENCRYPTION_SECRET_LENGTH) {
14
+ throw new Error(`mail: AUTH_SECRET must be at least ${MIN_MAIL_ENCRYPTION_SECRET_LENGTH} characters - mail-send job payloads (OTPs, invitation tokens) are encrypted with it`);
15
+ }
16
+ let svcRef = null;
17
+ const mailService = (c) => (svcRef ??= new MailService({
18
+ sender: c.get(EMAIL_SENDER),
19
+ renderer: c.get(EMAIL_TEMPLATE_RENDERER),
20
+ directory: c.get(ADMIN_USER_DIRECTORY),
21
+ jobQueue: c.get(JOB_QUEUE),
22
+ audit: c.has(AUDIT_WRITER) ? c.get(AUDIT_WRITER) : null,
23
+ encryptionSecret,
24
+ }));
25
+ ctx.provide(EMAIL_SENDER, () => new StdoutEmailSender());
26
+ ctx.provide(EMAIL_TEMPLATE_RENDERER, () => new DefaultEmailTemplateRenderer());
27
+ ctx.provide(MAIL_DISPATCH, (c) => {
28
+ const svc = mailService(c);
29
+ return {
30
+ toUser: (input) => svc.enqueueToUser(input),
31
+ toAddress: (input) => svc.enqueueToAddress(input),
32
+ };
33
+ });
34
+ ctx.routers.add('mail', (c) => {
35
+ if (c.get(EMAIL_SENDER) instanceof StdoutEmailSender) {
36
+ const msg = 'mail: no EMAIL_SENDER overlay bound. StdoutEmailSender only logs metadata and never ' +
37
+ 'delivers - bind a real EMAIL_SENDER (SMTP/SES/Postmark) in an overlay loaded after the mail plugin.';
38
+ if (process.env['NODE_ENV'] === 'production') {
39
+ throw new Error(msg);
40
+ }
41
+ logger.warn(msg);
42
+ }
43
+ mailService(c);
44
+ return {};
45
+ });
46
+ ctx.jobs.worker({
47
+ queue: MAIL_SEND_QUEUE,
48
+ schema: EncryptedMailSendJobSchema,
49
+ options: { concurrency: 5 },
50
+ handler: async ({ payload, attempt }) => {
51
+ if (!svcRef) {
52
+ throw new Error('mail: service not constructed yet');
53
+ }
54
+ await svcRef.deliverEncrypted(payload, attempt);
55
+ },
56
+ onDeadLetter: (jobCtx, error) => {
57
+ if (!svcRef) {
58
+ logger.error({ err: error }, 'mail delivery exhausted retries before service init');
59
+ return;
60
+ }
61
+ return svcRef.onEncryptedDeliveryExhausted(jobCtx.payload, error, jobCtx.attempt);
62
+ },
63
+ });
64
+ },
65
+ };
66
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/mail/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type EncryptedMailSendJob, type MailSendJob } from '../contract/index.js';
2
+ export declare const MIN_MAIL_ENCRYPTION_SECRET_LENGTH = 32;
3
+ export type MailPayloadCipher = {
4
+ encrypt(job: MailSendJob): EncryptedMailSendJob;
5
+ decrypt(job: EncryptedMailSendJob): MailSendJob;
6
+ };
7
+ export declare function createMailPayloadCipher(secret: string): MailPayloadCipher;
8
+ //# sourceMappingURL=mail-payload.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-payload.service.d.ts","sourceRoot":"","sources":["../../../src/mail/service/mail-payload.service.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAI9B,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,oBAAoB,CAAC;IAChD,OAAO,CAAC,GAAG,EAAE,oBAAoB,GAAG,WAAW,CAAC;CACjD,CAAC;AAOF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAiCzE"}
@@ -0,0 +1,43 @@
1
+ import { createCipheriv, createDecipheriv, hkdfSync, randomBytes } from 'node:crypto';
2
+ import { MailSendJobSchema, } from '../contract/index.js';
3
+ const ALGORITHM = 'aes-256-gcm';
4
+ const IV_BYTES = 12;
5
+ export const MIN_MAIL_ENCRYPTION_SECRET_LENGTH = 32;
6
+ const MAIL_PAYLOAD_KEY_INFO = 'openora:mail-payload:v1';
7
+ const toKey = (secret) => Buffer.from(hkdfSync('sha256', secret, Buffer.alloc(0), MAIL_PAYLOAD_KEY_INFO, 32));
8
+ export function createMailPayloadCipher(secret) {
9
+ if (secret.length < MIN_MAIL_ENCRYPTION_SECRET_LENGTH) {
10
+ throw new Error('AUTH_SECRET must have at least 32 characters to encrypt mail jobs');
11
+ }
12
+ const key = toKey(secret);
13
+ return {
14
+ encrypt(job) {
15
+ const iv = randomBytes(IV_BYTES);
16
+ const cipher = createCipheriv(ALGORITHM, key, iv);
17
+ const ciphertext = Buffer.concat([
18
+ cipher.update(JSON.stringify(job), 'utf8'),
19
+ cipher.final(),
20
+ ]).toString('base64url');
21
+ return {
22
+ ciphertext,
23
+ iv: iv.toString('base64url'),
24
+ tag: cipher.getAuthTag().toString('base64url'),
25
+ };
26
+ },
27
+ decrypt(job) {
28
+ try {
29
+ const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(job.iv, 'base64url'));
30
+ decipher.setAuthTag(Buffer.from(job.tag, 'base64url'));
31
+ const plaintext = Buffer.concat([
32
+ decipher.update(Buffer.from(job.ciphertext, 'base64url')),
33
+ decipher.final(),
34
+ ]).toString('utf8');
35
+ return MailSendJobSchema.parse(JSON.parse(plaintext));
36
+ }
37
+ catch {
38
+ throw new Error('mail job payload could not be decrypted');
39
+ }
40
+ },
41
+ };
42
+ }
43
+ //# sourceMappingURL=mail-payload.service.js.map