@dalmore/api-contracts 0.0.0-dev.4ec8ae0 → 0.0.0-dev.56068a6

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 (190) hide show
  1. package/README.md +23 -19
  2. package/common/types/account-contact.types.ts +2 -1
  3. package/common/types/account-manager.types.ts +3 -7
  4. package/common/types/account-setting.types.ts +34 -0
  5. package/common/types/account.types.ts +1 -0
  6. package/common/types/auth.types.ts +7 -18
  7. package/common/types/bonus-tier.types.ts +9 -0
  8. package/common/types/common.types.ts +22 -0
  9. package/common/types/comply-advantage-api.types.ts +3 -3
  10. package/common/types/contact-us.types.ts +6 -2
  11. package/common/types/covered-person.types.ts +2 -1
  12. package/common/types/escrow-account.types.ts +3 -3
  13. package/common/types/individuals.types.ts +3 -2
  14. package/common/types/investor-account.types.ts +2 -1
  15. package/common/types/invite.types.ts +27 -1
  16. package/common/types/issuer-offering.types.ts +5 -8
  17. package/common/types/legal-entity.types.ts +3 -2
  18. package/common/types/mail-template.types.ts +34 -0
  19. package/common/types/note.types.ts +1 -1
  20. package/common/types/notification.types.ts +288 -2
  21. package/common/types/site-settings.types.ts +2 -1
  22. package/common/types/trade.types.ts +47 -1
  23. package/common/types/trusted-contact.types.ts +7 -7
  24. package/common/types/user.types.ts +2 -5
  25. package/common/types/webhook.types.ts +142 -0
  26. package/index.ts +10 -0
  27. package/package.json +23 -32
  28. package/contracts/compliance/account-contacts/index.ts +0 -82
  29. package/contracts/compliance/account-managers/index.ts +0 -142
  30. package/contracts/compliance/accounts/index.ts +0 -187
  31. package/contracts/compliance/activities/index.ts +0 -55
  32. package/contracts/compliance/aic/index.ts +0 -60
  33. package/contracts/compliance/api-keys/index.ts +0 -91
  34. package/contracts/compliance/assets/index.ts +0 -122
  35. package/contracts/compliance/auth/index.ts +0 -134
  36. package/contracts/compliance/batch-jobs/index.ts +0 -62
  37. package/contracts/compliance/bonus-tiers/index.ts +0 -74
  38. package/contracts/compliance/checklist/index.ts +0 -87
  39. package/contracts/compliance/checklist-items/index.ts +0 -86
  40. package/contracts/compliance/covered-persons/index.ts +0 -97
  41. package/contracts/compliance/dashboard/index.ts +0 -111
  42. package/contracts/compliance/data-records/index.ts +0 -116
  43. package/contracts/compliance/data-rooms/index.ts +0 -113
  44. package/contracts/compliance/default-theme-configs/index.ts +0 -95
  45. package/contracts/compliance/disbursement/index.ts +0 -165
  46. package/contracts/compliance/disbursement-approval-users/index.ts +0 -84
  47. package/contracts/compliance/disbursement-transactions/index.ts +0 -37
  48. package/contracts/compliance/domain-filters/index.ts +0 -117
  49. package/contracts/compliance/email-themes/index.ts +0 -284
  50. package/contracts/compliance/escrow-accounts/index.ts +0 -85
  51. package/contracts/compliance/exchange-api-keys/index.ts +0 -129
  52. package/contracts/compliance/exchange-imports/index.ts +0 -137
  53. package/contracts/compliance/files/index.ts +0 -267
  54. package/contracts/compliance/files-public/index.ts +0 -188
  55. package/contracts/compliance/health/index.ts +0 -26
  56. package/contracts/compliance/index.ts +0 -147
  57. package/contracts/compliance/individuals/index.ts +0 -57
  58. package/contracts/compliance/investor-accounts/index.ts +0 -141
  59. package/contracts/compliance/invites/index.ts +0 -137
  60. package/contracts/compliance/issuer-bank-accounts/index.ts +0 -81
  61. package/contracts/compliance/issuer-payment-methods/index.ts +0 -81
  62. package/contracts/compliance/issuers/index.ts +0 -97
  63. package/contracts/compliance/job-items/index.ts +0 -58
  64. package/contracts/compliance/jobs/index.ts +0 -59
  65. package/contracts/compliance/kyb/index.ts +0 -54
  66. package/contracts/compliance/kyc/index.ts +0 -77
  67. package/contracts/compliance/legal-entities/index.ts +0 -57
  68. package/contracts/compliance/login-histories/index.ts +0 -37
  69. package/contracts/compliance/notes/index.ts +0 -69
  70. package/contracts/compliance/notion-databases/index.ts +0 -107
  71. package/contracts/compliance/notion-pages/index.ts +0 -105
  72. package/contracts/compliance/offering-reports/index.ts +0 -149
  73. package/contracts/compliance/offerings/index.ts +0 -233
  74. package/contracts/compliance/pages/index.ts +0 -178
  75. package/contracts/compliance/payment-methods/index.ts +0 -57
  76. package/contracts/compliance/rejection-reasons/index.ts +0 -32
  77. package/contracts/compliance/review/index.ts +0 -169
  78. package/contracts/compliance/roles/index.ts +0 -34
  79. package/contracts/compliance/secondary-customers/index.ts +0 -77
  80. package/contracts/compliance/secondary-orders/index.ts +0 -60
  81. package/contracts/compliance/secondary-trades/index.ts +0 -100
  82. package/contracts/compliance/secure-requests/index.ts +0 -54
  83. package/contracts/compliance/signer/index.ts +0 -369
  84. package/contracts/compliance/site-links/index.ts +0 -128
  85. package/contracts/compliance/site-settings/index.ts +0 -669
  86. package/contracts/compliance/sites/index.ts +0 -56
  87. package/contracts/compliance/state-machine/index.ts +0 -94
  88. package/contracts/compliance/tasks/index.ts +0 -91
  89. package/contracts/compliance/third-parties/index.ts +0 -52
  90. package/contracts/compliance/trade-line-items/index.ts +0 -59
  91. package/contracts/compliance/trades/index.ts +0 -230
  92. package/contracts/compliance/transactions/index.ts +0 -161
  93. package/contracts/compliance/user-manuals/index.ts +0 -271
  94. package/contracts/compliance/user-settings/index.ts +0 -189
  95. package/contracts/compliance/users/index.ts +0 -221
  96. package/contracts/compliance/webhooks/index.ts +0 -41
  97. package/contracts/compliance-apikey/accounts/index.ts +0 -58
  98. package/contracts/compliance-apikey/index.ts +0 -14
  99. package/contracts/index.ts +0 -6
  100. package/contracts/investors/account-contacts/index.ts +0 -58
  101. package/contracts/investors/aic/index.ts +0 -59
  102. package/contracts/investors/assets/index.ts +0 -61
  103. package/contracts/investors/auth/index.ts +0 -116
  104. package/contracts/investors/bonus-tiers/index.ts +0 -55
  105. package/contracts/investors/cart/index.ts +0 -75
  106. package/contracts/investors/contact-us/index.ts +0 -48
  107. package/contracts/investors/data-records/index.ts +0 -113
  108. package/contracts/investors/data-rooms/index.ts +0 -96
  109. package/contracts/investors/files/index.ts +0 -167
  110. package/contracts/investors/files-public/index.ts +0 -185
  111. package/contracts/investors/index.ts +0 -72
  112. package/contracts/investors/individuals/index.ts +0 -121
  113. package/contracts/investors/investor-accounts/index.ts +0 -110
  114. package/contracts/investors/issuer-payment-methods/index.ts +0 -36
  115. package/contracts/investors/issuers/index.ts +0 -30
  116. package/contracts/investors/legal-entities/index.ts +0 -93
  117. package/contracts/investors/notes/index.ts +0 -69
  118. package/contracts/investors/offerings/index.ts +0 -93
  119. package/contracts/investors/pages/index.ts +0 -88
  120. package/contracts/investors/payment-methods/index.ts +0 -149
  121. package/contracts/investors/portfolios/index.ts +0 -53
  122. package/contracts/investors/sites/index.ts +0 -96
  123. package/contracts/investors/tasks/index.ts +0 -111
  124. package/contracts/investors/trade-line-items/index.ts +0 -75
  125. package/contracts/investors/trades/index.ts +0 -114
  126. package/contracts/investors/transactions/index.ts +0 -37
  127. package/contracts/investors/trusted-contacts/index.ts +0 -93
  128. package/contracts/investors/user-manuals/index.ts +0 -62
  129. package/contracts/investors/user-settings/index.ts +0 -170
  130. package/contracts/investors/users/index.ts +0 -45
  131. package/contracts/investors/webhooks/index.ts +0 -30
  132. package/contracts/issuers/account-contacts/index.ts +0 -76
  133. package/contracts/issuers/account-integrations/index.ts +0 -97
  134. package/contracts/issuers/accounts/index.ts +0 -97
  135. package/contracts/issuers/activities/index.ts +0 -54
  136. package/contracts/issuers/aic/index.ts +0 -39
  137. package/contracts/issuers/api-key-logs/index.ts +0 -53
  138. package/contracts/issuers/api-keys/index.ts +0 -93
  139. package/contracts/issuers/assets/index.ts +0 -122
  140. package/contracts/issuers/auth/index.ts +0 -152
  141. package/contracts/issuers/bonus-tiers/index.ts +0 -73
  142. package/contracts/issuers/contact-us/index.ts +0 -48
  143. package/contracts/issuers/covered-persons/index.ts +0 -136
  144. package/contracts/issuers/dashboard/index.ts +0 -72
  145. package/contracts/issuers/data-records/index.ts +0 -257
  146. package/contracts/issuers/data-rooms/index.ts +0 -134
  147. package/contracts/issuers/disbursement-approval-users/index.ts +0 -82
  148. package/contracts/issuers/disbursement-transactions/index.ts +0 -53
  149. package/contracts/issuers/disbursements/index.ts +0 -189
  150. package/contracts/issuers/email-themes/index.ts +0 -242
  151. package/contracts/issuers/escrow-accounts/index.ts +0 -81
  152. package/contracts/issuers/exchange-api-keys/index.ts +0 -144
  153. package/contracts/issuers/files/index.ts +0 -166
  154. package/contracts/issuers/files-public/index.ts +0 -166
  155. package/contracts/issuers/health/index.ts +0 -24
  156. package/contracts/issuers/index.ts +0 -112
  157. package/contracts/issuers/investor-accounts/index.ts +0 -148
  158. package/contracts/issuers/invites/index.ts +0 -129
  159. package/contracts/issuers/issuer/index.ts +0 -94
  160. package/contracts/issuers/issuer-bank-accounts/index.ts +0 -81
  161. package/contracts/issuers/issuer-payment-methods/index.ts +0 -136
  162. package/contracts/issuers/kyc/index.ts +0 -38
  163. package/contracts/issuers/login-histories/index.ts +0 -51
  164. package/contracts/issuers/notes/index.ts +0 -69
  165. package/contracts/issuers/offerings/index.ts +0 -206
  166. package/contracts/issuers/pages/index.ts +0 -138
  167. package/contracts/issuers/payment-methods/index.ts +0 -61
  168. package/contracts/issuers/portfolios/index.ts +0 -36
  169. package/contracts/issuers/rejection-reasons/index.ts +0 -32
  170. package/contracts/issuers/review/index.ts +0 -63
  171. package/contracts/issuers/secondary-customers/index.ts +0 -55
  172. package/contracts/issuers/secondary-orders/index.ts +0 -57
  173. package/contracts/issuers/secondary-trades/index.ts +0 -57
  174. package/contracts/issuers/secure-requests/index.ts +0 -34
  175. package/contracts/issuers/site-links/index.ts +0 -116
  176. package/contracts/issuers/site-settings/index.ts +0 -585
  177. package/contracts/issuers/sites/index.ts +0 -32
  178. package/contracts/issuers/tasks/index.ts +0 -111
  179. package/contracts/issuers/trades/index.ts +0 -132
  180. package/contracts/issuers/transactions/index.ts +0 -158
  181. package/contracts/issuers/user-manuals/index.ts +0 -62
  182. package/contracts/issuers/user-settings/index.ts +0 -170
  183. package/contracts/issuers/users/index.ts +0 -126
  184. package/contracts/secondaries/accounts/index.ts +0 -58
  185. package/contracts/secondaries/index.ts +0 -23
  186. package/contracts/secondaries/secondary-customers/index.ts +0 -55
  187. package/contracts/secondaries/secondary-issuers/index.ts +0 -94
  188. package/contracts/secondaries/secondary-orders/index.ts +0 -56
  189. package/contracts/secondaries/secondary-securities/index.ts +0 -95
  190. package/contracts/secondaries/secondary-trades/index.ts +0 -56
@@ -2,6 +2,12 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
2
  import { z } from 'zod';
3
3
  import { TypeID } from 'typeid-js';
4
4
  import { IBaseEntity } from './entity.types';
5
+ import { IPaginationMeta, StringToBooleanSchema } from './common.types';
6
+ import {
7
+ ActivityTypeAction,
8
+ ActivityTypeCategory,
9
+ ActivityTypeResource,
10
+ } from './activity.types';
5
11
 
6
12
  extendZodWithOpenApi(z);
7
13
 
@@ -17,6 +23,88 @@ export enum NotificationRecordStatus {
17
23
  FAILED = 'FAILED',
18
24
  }
19
25
 
26
+ export type TriggerExclusion = {
27
+ category?: ActivityTypeCategory;
28
+ resource?: ActivityTypeResource;
29
+ action?: ActivityTypeAction;
30
+ };
31
+
32
+ // Excluded notifications
33
+ export const EXCLUDED_NOTIFICATION_TRIGGERS: TriggerExclusion[] = [
34
+ // { action: ActivityTypeAction.RE_SIGN },
35
+ // { action: ActivityTypeAction.RESET_2FA },
36
+ // { action: ActivityTypeAction.LOGIN },
37
+ // { action: ActivityTypeAction.RESET_PASSWORD },
38
+ // { action: ActivityTypeAction.TWO_FACTOR_LOGIN },
39
+ // { action: ActivityTypeAction.FORGOT_PASSWORD },
40
+ // { resource: ActivityTypeResource.USERS },
41
+ // { resource: ActivityTypeResource.THEME_SETTINGS },
42
+ ];
43
+
44
+ export const ISSUER_ALLOWED_CATEGORIES: ActivityTypeCategory[] = [
45
+ ActivityTypeCategory.ISSUER,
46
+ ];
47
+
48
+ /**
49
+ * Checks if an activity type should be excluded from notifications.
50
+ *
51
+ * Each exclusion pattern can specify any combination of category, resource, and action.
52
+ * Omitted fields act as wildcards (match any value).
53
+ *
54
+ * @example
55
+ * // Excludes ALL activities with action RE_SIGN (any category, any resource)
56
+ * { action: ActivityTypeAction.RE_SIGN }
57
+ *
58
+ * @example
59
+ * // Excludes ALL USERS activities (any category, any action)
60
+ * { resource: ActivityTypeResource.USERS }
61
+ *
62
+ * @example
63
+ * // Excludes only COMPLIANCE + TRADES + CREATE (all three must match)
64
+ * { category: ActivityTypeCategory.COMPLIANCE, resource: ActivityTypeResource.TRADES, action: ActivityTypeAction.CREATE }
65
+ *
66
+ * @param category - The activity type category to check
67
+ * @param resource - The activity type resource to check
68
+ * @param action - The activity type action to check
69
+ * @param exclusions - Array of exclusion patterns (defaults to EXCLUDED_NOTIFICATION_TRIGGERS)
70
+ * @returns true if the activity type matches any exclusion pattern
71
+ */
72
+ export function isTriggerExcluded(
73
+ category: string,
74
+ resource: string,
75
+ action: string,
76
+ exclusions: TriggerExclusion[] = EXCLUDED_NOTIFICATION_TRIGGERS,
77
+ ): boolean {
78
+ return exclusions.some((exclusion) => {
79
+ const categoryMatch =
80
+ !exclusion.category || exclusion.category === category;
81
+ const resourceMatch =
82
+ !exclusion.resource || exclusion.resource === resource;
83
+ const actionMatch = !exclusion.action || exclusion.action === action;
84
+ return categoryMatch && resourceMatch && actionMatch;
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Checks if a category is allowed for notification triggers.
90
+ *
91
+ * Used to restrict which activity type categories a user can subscribe to.
92
+ * For example, issuers can only subscribe to ISSUER category triggers.
93
+ *
94
+ * @param category - The activity type category to check
95
+ * @param allowedCategories - Optional array of allowed categories. If empty or undefined, all categories are allowed.
96
+ * @returns true if the category is allowed (or if no restrictions are set)
97
+ */
98
+ export function isCategoryAllowed(
99
+ category: string,
100
+ allowedCategories?: ActivityTypeCategory[],
101
+ ): boolean {
102
+ if (!allowedCategories || allowedCategories.length === 0) {
103
+ return true;
104
+ }
105
+ return allowedCategories.includes(category as ActivityTypeCategory);
106
+ }
107
+
20
108
  export const notificationChannelIdSchema = z.string().refine(
21
109
  (value) => {
22
110
  try {
@@ -63,7 +151,10 @@ export const notificationRecordIdSchema = z.string().refine(
63
151
  );
64
152
 
65
153
  export const EmailChannelSettingsSchema = z.object({
66
- recipients: z.array(z.string().email()).min(1),
154
+ recipients: z
155
+ .array(z.string().email())
156
+ .min(1)
157
+ .max(100, 'At most 100 recipients are allowed'),
67
158
  subjectTemplate: z.string().optional(),
68
159
  });
69
160
  export type EmailChannelSettings = z.infer<typeof EmailChannelSettingsSchema>;
@@ -117,6 +208,16 @@ export type EmailNotificationPayload = z.infer<
117
208
  typeof EmailNotificationPayloadSchema
118
209
  >;
119
210
 
211
+ /**
212
+ * Payload for Slack notifications sent via Incoming Webhooks.
213
+ *
214
+ * @property webhookUrl - Slack Incoming Webhook URL
215
+ * @property channelEmail - Slack channel email integration (alternative delivery method)
216
+ * @property message - Plain text message (also serves as fallback for notifications)
217
+ * @property blocks - Optional Slack Block Kit elements for rich message formatting.
218
+ * Blocks allow structured layouts with headers, sections, images, buttons, etc.
219
+ * @see https://docs.slack.dev/messaging/creating-interactive-messages
220
+ */
120
221
  export const SlackNotificationPayloadSchema = z.object({
121
222
  webhookUrl: z.string().url().optional(),
122
223
  channelEmail: z.string().email().optional(),
@@ -212,7 +313,14 @@ export const INotificationChannelZod = IBaseEntity.extend({
212
313
  enabled: z.boolean().openapi({
213
314
  example: true,
214
315
  }),
215
- settings: NotificationChannelSettingsSchema,
316
+ settings: NotificationChannelSettingsSchema.openapi({
317
+ example: {
318
+ type: NotificationChannelType.SLACK,
319
+ config: {
320
+ webhookUrl: 'https://hooks.slack.com/test',
321
+ },
322
+ },
323
+ }),
216
324
  });
217
325
  export type INotificationChannelZod = z.infer<typeof INotificationChannelZod>;
218
326
 
@@ -234,6 +342,36 @@ export type INotificationChannelTriggerZod = z.infer<
234
342
  typeof INotificationChannelTriggerZod
235
343
  >;
236
344
 
345
+ export const IAvailableTriggerZod = z.object({
346
+ activityTypeId: z.string().openapi({
347
+ example: 'activity_type_01j5y5ghx8fvc83dmx3pznq7hv',
348
+ }),
349
+ category: z.string().openapi({
350
+ example: 'COMPLIANCE',
351
+ }),
352
+ resource: z.string().openapi({
353
+ example: 'TRADES',
354
+ }),
355
+ action: z.string().openapi({
356
+ example: 'CREATE',
357
+ }),
358
+ enabled: z.boolean().openapi({
359
+ description: 'Whether the trigger is enabled for this activity type',
360
+ example: false,
361
+ }),
362
+ trigger: INotificationChannelTriggerZod.nullable().openapi({
363
+ description: 'The configured trigger, or null if not configured',
364
+ }),
365
+ });
366
+ export type IAvailableTriggerZod = z.infer<typeof IAvailableTriggerZod>;
367
+
368
+ export const IAvailableTriggersResponse = z.object({
369
+ items: z.array(IAvailableTriggerZod),
370
+ });
371
+ export type IAvailableTriggersResponse = z.infer<
372
+ typeof IAvailableTriggersResponse
373
+ >;
374
+
237
375
  export const INotificationRecordZod = IBaseEntity.extend({
238
376
  id: notificationRecordIdSchema.openapi({
239
377
  example: 'notification_record_01j5y5ghx8fvc83dmx3pznq7hv',
@@ -266,3 +404,151 @@ export const INotificationRecordZod = IBaseEntity.extend({
266
404
  }),
267
405
  });
268
406
  export type INotificationRecordZod = z.infer<typeof INotificationRecordZod>;
407
+
408
+ export const CreateChannelInputSchema = z
409
+ .object({
410
+ accountSettingsId: z.string(),
411
+ channelType: z.nativeEnum(NotificationChannelType),
412
+ name: z
413
+ .string()
414
+ .min(1, 'Name is required')
415
+ .max(255, 'Name must be less than 255 characters'),
416
+ enabled: z.boolean().optional(),
417
+ settings: NotificationChannelSettingsSchema,
418
+ })
419
+ .refine((data) => data.channelType === data.settings.type, {
420
+ message: 'Channel type must match settings type',
421
+ path: ['settings', 'type'],
422
+ });
423
+ export type CreateChannelInput = z.infer<typeof CreateChannelInputSchema>;
424
+
425
+ export const IssuerCreateChannelInputSchema = z
426
+ .object({
427
+ channelType: z.nativeEnum(NotificationChannelType),
428
+ name: z
429
+ .string()
430
+ .min(1, 'Name is required')
431
+ .max(255, 'Name must be less than 255 characters'),
432
+ enabled: z.boolean().optional(),
433
+ settings: NotificationChannelSettingsSchema,
434
+ })
435
+ .refine((data) => data.channelType === data.settings.type, {
436
+ message: 'Channel type must match settings type',
437
+ path: ['settings', 'type'],
438
+ });
439
+ export type IssuerCreateChannelInput = z.infer<
440
+ typeof IssuerCreateChannelInputSchema
441
+ >;
442
+
443
+ export const UpdateChannelInputSchema = z.object({
444
+ name: z.string().optional(),
445
+ enabled: z.boolean().optional(),
446
+ settings: NotificationChannelSettingsSchema.optional(),
447
+ });
448
+ export type UpdateChannelInput = z.infer<typeof UpdateChannelInputSchema>;
449
+
450
+ export const CreateTriggerInputSchema = z.object({
451
+ notificationChannelId: notificationChannelIdSchema,
452
+ activityTypeId: z.string(),
453
+ enabled: z.boolean().optional(),
454
+ });
455
+ export type CreateTriggerInput = z.infer<typeof CreateTriggerInputSchema>;
456
+
457
+ export const IPaginatedNotificationChannel = z.object({
458
+ items: z.array(INotificationChannelZod),
459
+ meta: IPaginationMeta,
460
+ });
461
+ export type IPaginatedNotificationChannel = z.infer<
462
+ typeof IPaginatedNotificationChannel
463
+ >;
464
+
465
+ export const IPaginatedNotificationChannelTrigger = z.object({
466
+ items: z.array(INotificationChannelTriggerZod),
467
+ meta: IPaginationMeta,
468
+ });
469
+ export type IPaginatedNotificationChannelTrigger = z.infer<
470
+ typeof IPaginatedNotificationChannelTrigger
471
+ >;
472
+
473
+ export const IPaginatedNotificationRecord = z.object({
474
+ items: z.array(INotificationRecordZod),
475
+ meta: IPaginationMeta,
476
+ });
477
+ export type IPaginatedNotificationRecord = z.infer<
478
+ typeof IPaginatedNotificationRecord
479
+ >;
480
+
481
+ export const NotificationChannelFilters = z.object({
482
+ accountSettingsId: z.string().optional(),
483
+ channelType: z.nativeEnum(NotificationChannelType).optional(),
484
+ enabled: StringToBooleanSchema.optional(),
485
+ });
486
+ export type NotificationChannelFilters = z.infer<
487
+ typeof NotificationChannelFilters
488
+ >;
489
+
490
+ export const NotificationChannelTriggerFilters = z.object({
491
+ notificationChannelId: notificationChannelIdSchema.optional(),
492
+ activityTypeId: z.string().optional(),
493
+ enabled: StringToBooleanSchema.optional(),
494
+ });
495
+ export type NotificationChannelTriggerFilters = z.infer<
496
+ typeof NotificationChannelTriggerFilters
497
+ >;
498
+
499
+ export const NotificationRecordFilters = z.object({
500
+ notificationChannelId: notificationChannelIdSchema.optional(),
501
+ status: z.nativeEnum(NotificationRecordStatus).optional(),
502
+ });
503
+ export type NotificationRecordFilters = z.infer<
504
+ typeof NotificationRecordFilters
505
+ >;
506
+
507
+ export const notificationChannelsInclude = z.enum([
508
+ 'triggers',
509
+ 'accountSettings',
510
+ 'notificationRecords',
511
+ ]);
512
+
513
+ export const NotificationChannelsIncludeQuery = z.object({
514
+ include: z
515
+ .string()
516
+ .optional()
517
+ .transform((str) => (str ? str.split(',') : []))
518
+ .refine(
519
+ (includes) =>
520
+ includes.every((include) =>
521
+ notificationChannelsInclude.options.includes(include as any),
522
+ ),
523
+ {
524
+ message: `Invalid include value. Valid values are: ${notificationChannelsInclude.options.join(', ')}`,
525
+ },
526
+ ),
527
+ });
528
+ export type NotificationChannelsIncludeQuery = z.infer<
529
+ typeof NotificationChannelsIncludeQuery
530
+ >;
531
+
532
+ export const notificationRecordsInclude = z.enum([
533
+ 'notificationChannel',
534
+ 'activity',
535
+ ]);
536
+
537
+ export const NotificationRecordsIncludeQuery = z.object({
538
+ include: z
539
+ .string()
540
+ .optional()
541
+ .transform((str) => (str ? str.split(',') : []))
542
+ .refine(
543
+ (includes) =>
544
+ includes.every((include) =>
545
+ notificationRecordsInclude.options.includes(include as any),
546
+ ),
547
+ {
548
+ message: `Invalid include value. Valid values are: ${notificationRecordsInclude.options.join(', ')}`,
549
+ },
550
+ ),
551
+ });
552
+ export type NotificationRecordsIncludeQuery = z.infer<
553
+ typeof NotificationRecordsIncludeQuery
554
+ >;
@@ -3,6 +3,7 @@ import { z } from 'zod';
3
3
  import { fileIdSchema } from './file.types';
4
4
  import {
5
5
  AccountZod,
6
+ EmailSchema,
6
7
  HexCodeColorSchema,
7
8
  IPaginationMeta,
8
9
  SubdomainSchema,
@@ -462,7 +463,7 @@ export const GetSenderEmailZod = z.object({
462
463
  export type GetSenderEmailZod = z.infer<typeof GetSenderEmailZod>;
463
464
 
464
465
  export const PatchSenderEmailZod = z.object({
465
- senderEmail: z.string().email().openapi({ example: 'example@example.com' }),
466
+ senderEmail: EmailSchema,
466
467
  });
467
468
  export type PatchSenderEmailZod = z.infer<typeof PatchSenderEmailZod>;
468
469
 
@@ -22,12 +22,13 @@ import {
22
22
  AccountStatus,
23
23
  SavedQuery,
24
24
  } from './common.types';
25
- import { offeringIdSchema } from './offering.types';
25
+ import { IOffering, offeringIdSchema } from './offering.types';
26
26
  import { IBaseEntity } from './entity.types';
27
27
  import { extendZodWithOpenApi } from '@anatine/zod-openapi';
28
28
  import { TypeID } from 'typeid-js';
29
29
  import {
30
30
  paymentMethodIdSchema,
31
+ PaymentMethodResponse,
31
32
  PaymentMethodType,
32
33
  } from './payment-methods.types';
33
34
  import {
@@ -35,6 +36,7 @@ import {
35
36
  InvestorAccountExportFilters,
36
37
  ComplianceInvestorAccountExportFilters,
37
38
  RegisteredInvestorUserRawZod,
39
+ IInvestorAccount,
38
40
  } from './investor-account.types';
39
41
  import {
40
42
  tradeLineItemIdSchema,
@@ -132,6 +134,7 @@ export const CheckResultsSchema = z.object({
132
134
  export type CheckResults = z.infer<typeof CheckResultsSchema>;
133
135
 
134
136
  export const TradeIdPrefix = 'trade';
137
+ export const TradeSnapshotIdPrefix = 'trade_snapshot';
135
138
 
136
139
  export const tradeIdSchema = z.string().refine(
137
140
  (value) => {
@@ -170,6 +173,21 @@ export const tradeIdOrTidSchema = z.union([
170
173
  .openapi({ example: 'tid_00041061050r3gg28a1c60t3gf' }),
171
174
  ]);
172
175
 
176
+ export const tradeSnapshotIdSchema = z.string().refine(
177
+ (value) => {
178
+ try {
179
+ const tid = TypeID.fromString(value);
180
+ return tid.getType() === TradeSnapshotIdPrefix;
181
+ } catch {
182
+ return false;
183
+ }
184
+ },
185
+ {
186
+ message:
187
+ 'Invalid trade snapshot ID format. Must be a valid TypeID with "trade_snapshot" prefix. ex: trade_snapshot_00041061050r3gg28a1c60t3gf',
188
+ },
189
+ );
190
+
173
191
  export enum SaStatus {
174
192
  PENDING = BaseStatus.PENDING,
175
193
  SIGNED = BaseStatus.SIGNED,
@@ -274,9 +292,21 @@ export type TradeBalanceResultZod = z.infer<typeof TradeBalanceResultZod>;
274
292
 
275
293
  export const TradeZod = IBaseEntity.extend({
276
294
  investorAccountId: z.lazy(() => investorAccountIdSchema.nullable()),
295
+ investorAccount: z
296
+ .lazy(() => IInvestorAccount)
297
+ .optional()
298
+ .nullable(),
299
+ offering: z
300
+ .lazy(() => IOffering)
301
+ .optional()
302
+ .nullable(),
277
303
  accountId: accountIdSchema.nullable(),
278
304
  offeringId: z.lazy(() => offeringIdSchema.nullable()),
279
305
  paymentMethodId: z.lazy(() => paymentMethodIdSchema).nullable(),
306
+ paymentMethod: z
307
+ .lazy(() => PaymentMethodResponse)
308
+ .optional()
309
+ .nullable(),
280
310
  userId: z.lazy(() => userIdSchema.nullable()),
281
311
  tradeNumber: z.string(),
282
312
  ip: z.string().nullable(),
@@ -342,6 +372,21 @@ export const TradeZod = IBaseEntity.extend({
342
372
  });
343
373
  export type TradeZod = z.infer<typeof TradeZod>;
344
374
 
375
+ export enum SnapshotEvent {
376
+ COMPLIANCE_APPROVED = 'COMPLIANCE_APPROVED',
377
+ COMPLIANCE_REJECTED = 'COMPLIANCE_REJECTED',
378
+ CANCELLED = 'CANCELLED',
379
+ PLACED = 'PLACED',
380
+ SETTLED = 'SETTLED',
381
+ }
382
+
383
+ export const GetTradeSnapshotEventsResponse = z.object({
384
+ events: z.array(z.nativeEnum(SnapshotEvent)),
385
+ });
386
+ export type GetTradeSnapshotEventsResponse = z.infer<
387
+ typeof GetTradeSnapshotEventsResponse
388
+ >;
389
+
345
390
  export const IPaginatedTrade = z.object({
346
391
  items: z.array(TradeZod),
347
392
  meta: IPaginationMeta,
@@ -424,6 +469,7 @@ export const TradeFiltersZod = z.object({
424
469
  .openapi({
425
470
  example: 'issuer_01jfw4q6qef30s6fpqtsxw94ya',
426
471
  }),
472
+ snapshotEvent: z.nativeEnum(SnapshotEvent).optional(),
427
473
  offeringType: z.nativeEnum(OfferingType).optional(),
428
474
  managedBy: z.nativeEnum(ManagedByType).optional(),
429
475
  platform: z.nativeEnum(Platforms).optional(),
@@ -2,7 +2,11 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
2
  import { TypeID } from 'typeid-js';
3
3
  import { z } from 'zod';
4
4
  import { IBaseEntity } from './entity.types';
5
- import { IPaginationMeta, TrustedContactRelationship } from './common.types';
5
+ import {
6
+ EmailSchema,
7
+ IPaginationMeta,
8
+ TrustedContactRelationship,
9
+ } from './common.types';
6
10
  import { PhoneZodSchema } from './phone.type';
7
11
  import { AddressSchema } from './address.types';
8
12
  import { investorAccountIdSchema } from './investor-account.types';
@@ -68,7 +72,7 @@ export const PostTrustedContactZod = z
68
72
  .object({
69
73
  firstName: z.string().min(1).max(255).openapi({ example: 'John' }),
70
74
  lastName: z.string().min(1).max(255).openapi({ example: 'Doe' }),
71
- email: z.string().email().openapi({ example: 'john.doe@example.com' }),
75
+ email: EmailSchema.openapi({ example: 'john.doe@example.com' }),
72
76
  phone: PhoneZodSchema.nullable().optional(),
73
77
  relationship: z
74
78
  .nativeEnum(TrustedContactRelationship)
@@ -92,11 +96,7 @@ export const PatchTrustedContactZod = z
92
96
  .optional()
93
97
  .openapi({ example: 'John' }),
94
98
  lastName: z.string().min(1).max(255).optional().openapi({ example: 'Doe' }),
95
- email: z
96
- .string()
97
- .email()
98
- .optional()
99
- .openapi({ example: 'john.doe@example.com' }),
99
+ email: EmailSchema.optional(),
100
100
  phone: PhoneZodSchema.nullable().optional(),
101
101
  relationship: z.nativeEnum(TrustedContactRelationship).optional().openapi({
102
102
  example: TrustedContactRelationship.CHILD,
@@ -11,6 +11,7 @@ import {
11
11
  StringToBooleanSchema,
12
12
  UserRole,
13
13
  UserType,
14
+ EmailSchema,
14
15
  } from './common.types';
15
16
  import { dateOrString, IBaseEntity } from './entity.types';
16
17
  import { PhoneZodSchema } from './phone.type';
@@ -147,11 +148,7 @@ export const UserMeUpdateZod = z.object({
147
148
  firstName: z.string().optional(),
148
149
  lastName: z.string().optional(),
149
150
  password: z.string().min(6).optional(),
150
- email: z
151
- .string()
152
- .email()
153
- .transform((val) => val.toLowerCase())
154
- .optional(),
151
+ email: EmailSchema.optional(),
155
152
  });
156
153
 
157
154
  export const UserZod = IBaseEntity.extend({
@@ -1,6 +1,148 @@
1
1
  import { z } from 'zod';
2
2
  import { PersonaStatus } from './common.types';
3
3
 
4
+ /**
5
+ * Hook0 Webhook Provider Types
6
+ *
7
+ * Types for interacting with Hook0's webhooks-as-a-service API.
8
+ * @see https://documentation.hook0.com/api - API Reference
9
+ */
10
+
11
+ /**
12
+ * Hook0 API error response format.
13
+ * @see https://documentation.hook0.com/api
14
+ */
15
+ export const Hook0ApiErrorSchema = z.object({
16
+ type: z.string(),
17
+ status: z.number(),
18
+ title: z.string(),
19
+ detail: z.string(),
20
+ validation: z.unknown().nullable(),
21
+ id: z.string(),
22
+ });
23
+ export type Hook0ApiError = z.infer<typeof Hook0ApiErrorSchema>;
24
+
25
+ /**
26
+ * Error returned from Hook0 provider operations.
27
+ * Wraps Hook0 API errors with additional context.
28
+ */
29
+ export const Hook0ProviderErrorSchema = z.object({
30
+ message: z.string(),
31
+ statusCode: z.number().optional(),
32
+ code: z.string().optional(),
33
+ apiError: Hook0ApiErrorSchema.optional(),
34
+ });
35
+ export type Hook0ProviderError = z.infer<typeof Hook0ProviderErrorSchema>;
36
+
37
+ /**
38
+ * Hook0 subscription target configuration.
39
+ * Defines where and how webhooks are delivered.
40
+ * @see https://documentation.hook0.com/reference/subscriptionscreate
41
+ */
42
+ export const Hook0SubscriptionTargetSchema = z.object({
43
+ type: z.literal('http'),
44
+ method: z.string(),
45
+ url: z.string().url(),
46
+ headers: z.record(z.string()).optional(),
47
+ });
48
+ export type Hook0SubscriptionTarget = z.infer<
49
+ typeof Hook0SubscriptionTargetSchema
50
+ >;
51
+
52
+ /**
53
+ * Hook0 subscription response from create/get operations.
54
+ * @see https://documentation.hook0.com/reference/subscriptionscreate
55
+ * @see https://documentation.hook0.com/reference/subscriptionsget
56
+ */
57
+ export const Hook0SubscriptionResponseSchema = z.object({
58
+ subscription_id: z.string().uuid(),
59
+ application_id: z.string().uuid(),
60
+ created_at: z.string().datetime().optional(),
61
+ dedicated_workers: z.array(z.string()).optional(),
62
+ description: z.string().optional(),
63
+ event_types: z.array(z.string()).optional(),
64
+ is_enabled: z.boolean().optional(),
65
+ label_key: z.string().optional(),
66
+ label_value: z.string().optional(),
67
+ labels: z.record(z.string()).optional(),
68
+ metadata: z.record(z.string()).optional(),
69
+ secret: z.string(),
70
+ target: Hook0SubscriptionTargetSchema.optional(),
71
+ });
72
+ export type Hook0SubscriptionResponse = z.infer<
73
+ typeof Hook0SubscriptionResponseSchema
74
+ >;
75
+
76
+ /**
77
+ * Simplified subscription result returned to callers.
78
+ */
79
+ export const WebhookSubscriptionSchema = z.object({
80
+ subscriptionId: z.string(),
81
+ secret: z.string(),
82
+ });
83
+ export type WebhookSubscription = z.infer<typeof WebhookSubscriptionSchema>;
84
+
85
+ /**
86
+ * Hook0 event type response from create operation.
87
+ * @see https://documentation.hook0.com/reference/eventtypescreate
88
+ */
89
+ export const Hook0EventTypeResponseSchema = z.object({
90
+ service_name: z.string(),
91
+ resource_type_name: z.string(),
92
+ verb_name: z.string(),
93
+ event_type_name: z.string(),
94
+ });
95
+ export type Hook0EventTypeResponse = z.infer<
96
+ typeof Hook0EventTypeResponseSchema
97
+ >;
98
+
99
+ /**
100
+ * Hook0 event type list item.
101
+ * @see https://documentation.hook0.com/reference/eventtypeslist
102
+ */
103
+ export const Hook0EventTypeSchema = z.object({
104
+ name: z.string(),
105
+ service: z.string().optional(),
106
+ resource_type: z.string().optional(),
107
+ verb: z.string().optional(),
108
+ });
109
+ export type Hook0EventType = z.infer<typeof Hook0EventTypeSchema>;
110
+
111
+ /**
112
+ * Hook0 event ingestion response.
113
+ * @see https://documentation.hook0.com/api/#tag/events-ingestion/POST/api/v1/event/
114
+ */
115
+ export const Hook0EventResponseSchema = z.object({
116
+ event_id: z.string().uuid().optional(),
117
+ received_at: z.string().datetime().optional(),
118
+ });
119
+ export type Hook0EventResponse = z.infer<typeof Hook0EventResponseSchema>;
120
+
121
+ /**
122
+ * Simplified event response returned to callers.
123
+ */
124
+ export const WebhookEventResponseSchema = z.object({
125
+ eventId: z.string(),
126
+ receivedAt: z.string(),
127
+ });
128
+ export type WebhookEventResponse = z.infer<typeof WebhookEventResponseSchema>;
129
+
130
+ /**
131
+ * Payload sent when ingesting events to Hook0.
132
+ * Contains activity data to be delivered to webhook subscribers.
133
+ */
134
+ export const WebhookEventPayloadSchema = z.object({
135
+ activityId: z.string(),
136
+ activityType: z.string(),
137
+ accountId: z.string(),
138
+ targetId: z.string().nullable(),
139
+ targetTable: z.string().nullable(),
140
+ message: z.string(),
141
+ metadata: z.record(z.unknown()),
142
+ occurredAt: z.string(),
143
+ });
144
+ export type WebhookEventPayload = z.infer<typeof WebhookEventPayloadSchema>;
145
+
4
146
  export const WebhookReceived = z.object({
5
147
  received: z.boolean(),
6
148
  });
package/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @dalmore/api-contracts
3
+ * Main entry point - re-exports clients contract and types
4
+ */
5
+
6
+ // Re-export clients contract
7
+ export * from './contracts/clients/index.js';
8
+
9
+ // Re-export all common types
10
+ export * from './common/types/index.js';