@oneuptime/common 12.0.13 → 12.0.14

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 (376) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
  2. package/Models/DatabaseModels/UserCall.ts +94 -3
  3. package/Models/DatabaseModels/UserEmail.ts +94 -3
  4. package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
  5. package/Models/DatabaseModels/UserPush.ts +37 -0
  6. package/Models/DatabaseModels/UserSMS.ts +94 -3
  7. package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
  8. package/Server/API/BaseAPI.ts +79 -14
  9. package/Server/API/UserCallAPI.ts +53 -45
  10. package/Server/API/UserEmailAPI.ts +53 -44
  11. package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
  12. package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
  13. package/Server/API/UserPushAPI.ts +126 -2
  14. package/Server/API/UserSmsAPI.ts +53 -44
  15. package/Server/API/UserWhatsAppAPI.ts +53 -50
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  20. package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
  21. package/Server/Services/AnalyticsDatabaseService.ts +169 -0
  22. package/Server/Services/DatabaseService.ts +101 -0
  23. package/Server/Services/LogAggregationService.ts +5 -0
  24. package/Server/Services/PushNotificationService.ts +127 -12
  25. package/Server/Services/TeamMemberService.ts +53 -13
  26. package/Server/Services/UserCallService.ts +55 -24
  27. package/Server/Services/UserEmailService.ts +83 -17
  28. package/Server/Services/UserIncomingCallNumberService.ts +49 -85
  29. package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
  30. package/Server/Services/UserNotificationRuleService.ts +26 -0
  31. package/Server/Services/UserPushService.ts +89 -0
  32. package/Server/Services/UserSmsService.ts +50 -17
  33. package/Server/Services/UserWhatsAppService.ts +48 -15
  34. package/Server/Types/Database/QueryHelper.ts +30 -0
  35. package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
  36. package/Server/Utils/ChannelVerification.ts +510 -0
  37. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
  38. package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
  39. package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
  40. package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
  41. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
  42. package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
  43. package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
  44. package/Server/Utils/TotpAuth.ts +137 -9
  45. package/Server/Utils/UserRegistrationToken.ts +182 -0
  46. package/Server/Utils/VerificationCode.ts +134 -0
  47. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
  48. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
  49. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
  50. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
  51. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
  52. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
  53. package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
  54. package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
  55. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
  56. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
  57. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
  58. package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
  59. package/Tests/Server/API/UserSmsApi.test.ts +107 -14
  60. package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
  61. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
  62. package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
  63. package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
  64. package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
  65. package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
  66. package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
  67. package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
  68. package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
  69. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
  70. package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
  71. package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
  72. package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
  73. package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
  74. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
  75. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
  76. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
  77. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
  78. package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
  79. package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
  80. package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
  81. package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
  82. package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
  83. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
  84. package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
  85. package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
  86. package/Tests/Server/Utils/Browser.test.ts +162 -0
  87. package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
  88. package/Tests/Server/Utils/Express.test.ts +371 -0
  89. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
  90. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
  91. package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
  92. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
  93. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
  94. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
  95. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
  96. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
  97. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
  98. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
  99. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
  100. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
  101. package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
  102. package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
  103. package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
  104. package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
  105. package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
  106. package/Tests/Types/Call/CallRequest.test.ts +189 -0
  107. package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
  108. package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
  109. package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
  110. package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
  111. package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
  112. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
  113. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
  114. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
  115. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
  116. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
  117. package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
  118. package/Tests/Types/TextRandomGeneration.test.ts +211 -0
  119. package/Tests/UI/Components/Button.test.tsx +175 -1
  120. package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
  121. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
  122. package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
  123. package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
  124. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
  125. package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
  126. package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
  127. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
  128. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
  129. package/Tests/UI/Components/List.test.tsx +9 -2
  130. package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
  131. package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
  132. package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
  133. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
  134. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
  135. package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
  136. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
  137. package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
  138. package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
  139. package/Tests/UI/Components/Skeleton.test.tsx +71 -0
  140. package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
  141. package/Tests/UI/Components/Tabs.test.tsx +24 -0
  142. package/Tests/UI/Components/Toast.test.tsx +130 -7
  143. package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
  144. package/Tests/UI/Utils/Dropdown.test.ts +423 -0
  145. package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
  146. package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
  147. package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
  148. package/Tests/Utils/API.test.ts +16 -2
  149. package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
  150. package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
  151. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
  152. package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
  153. package/Types/Email/EmailTemplateType.ts +1 -0
  154. package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
  155. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
  156. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
  157. package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
  158. package/Types/Permission.ts +35 -0
  159. package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
  160. package/Types/PushNotification/PushNotificationMessage.ts +15 -0
  161. package/Types/PushNotification/PushNotificationRequest.ts +8 -16
  162. package/Types/Service/ServiceLanguage.ts +144 -0
  163. package/Types/Text.ts +111 -19
  164. package/UI/Components/Button/Button.tsx +27 -14
  165. package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
  166. package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
  167. package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
  168. package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
  169. package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
  170. package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
  171. package/UI/Components/CommandPalette/Types.ts +49 -0
  172. package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
  173. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  174. package/UI/Components/Feed/FeedItem.tsx +1 -1
  175. package/UI/Components/List/List.tsx +37 -5
  176. package/UI/Components/List/ListSkeleton.tsx +54 -0
  177. package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
  178. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
  179. package/UI/Components/Modal/Modal.tsx +2 -2
  180. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  181. package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
  182. package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
  183. package/UI/Components/Navbar/NavBar.tsx +14 -1
  184. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
  185. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
  186. package/UI/Components/SideOver/SideOver.tsx +37 -2
  187. package/UI/Components/Skeleton/Skeleton.tsx +53 -0
  188. package/UI/Components/Table/Table.tsx +74 -44
  189. package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
  190. package/UI/Components/Tabs/Tab.tsx +1 -1
  191. package/UI/Components/Toast/Toast.tsx +118 -53
  192. package/UI/Components/Toast/ToastInit.tsx +82 -32
  193. package/UI/Styles/Theme.css +40 -0
  194. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
  195. package/UI/Utils/ModelListCache.ts +188 -0
  196. package/UI/Utils/Project.ts +29 -0
  197. package/Utils/API.ts +6 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
  201. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
  203. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
  205. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
  207. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
  209. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
  211. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  212. package/build/dist/Server/API/BaseAPI.js +69 -13
  213. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  214. package/build/dist/Server/API/UserCallAPI.js +42 -38
  215. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  216. package/build/dist/Server/API/UserEmailAPI.js +42 -38
  217. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  218. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
  219. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  220. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
  221. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
  222. package/build/dist/Server/API/UserPushAPI.js +95 -2
  223. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  224. package/build/dist/Server/API/UserSmsAPI.js +42 -38
  225. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  226. package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
  227. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  236. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
  237. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
  238. package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
  239. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  240. package/build/dist/Server/Services/DatabaseService.js +74 -0
  241. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  242. package/build/dist/Server/Services/LogAggregationService.js +5 -0
  243. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  244. package/build/dist/Server/Services/PushNotificationService.js +69 -30
  245. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  246. package/build/dist/Server/Services/TeamMemberService.js +43 -7
  247. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  248. package/build/dist/Server/Services/UserCallService.js +54 -22
  249. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  250. package/build/dist/Server/Services/UserEmailService.js +78 -17
  251. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  252. package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
  253. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  254. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
  255. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
  256. package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
  257. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  258. package/build/dist/Server/Services/UserPushService.js +77 -0
  259. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  260. package/build/dist/Server/Services/UserSmsService.js +50 -17
  261. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  262. package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
  263. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  264. package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
  265. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  266. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
  267. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
  268. package/build/dist/Server/Utils/ChannelVerification.js +348 -0
  269. package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
  270. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
  271. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  272. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
  273. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  274. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
  275. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  276. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
  277. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
  278. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
  279. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
  280. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
  281. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
  282. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  283. package/build/dist/Server/Utils/TotpAuth.js +127 -8
  284. package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
  285. package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
  286. package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
  287. package/build/dist/Server/Utils/VerificationCode.js +120 -0
  288. package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
  289. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  290. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  291. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
  292. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  293. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
  294. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  295. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
  296. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  297. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
  298. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
  299. package/build/dist/Types/Permission.js +33 -0
  300. package/build/dist/Types/Permission.js.map +1 -1
  301. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
  302. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
  303. package/build/dist/Types/Service/ServiceLanguage.js +96 -0
  304. package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
  305. package/build/dist/Types/Text.js +82 -17
  306. package/build/dist/Types/Text.js.map +1 -1
  307. package/build/dist/UI/Components/Button/Button.js +22 -14
  308. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  309. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
  310. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  311. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
  312. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
  313. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
  314. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
  315. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
  316. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
  317. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
  318. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
  319. package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
  320. package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
  321. package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
  322. package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
  323. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
  324. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
  325. package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
  326. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  327. package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
  328. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  329. package/build/dist/UI/Components/List/List.js +19 -5
  330. package/build/dist/UI/Components/List/List.js.map +1 -1
  331. package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
  332. package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
  333. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
  334. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
  335. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  336. package/build/dist/UI/Components/Modal/Modal.js +2 -2
  337. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  338. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  339. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
  340. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  341. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
  342. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  343. package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
  344. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  345. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
  346. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  347. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
  348. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  349. package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
  350. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  351. package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
  352. package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
  353. package/build/dist/UI/Components/Table/Table.js +35 -24
  354. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  355. package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
  356. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
  357. package/build/dist/UI/Components/Tabs/Tab.js +1 -1
  358. package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
  359. package/build/dist/UI/Components/Toast/Toast.js +77 -23
  360. package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
  361. package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
  362. package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
  363. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
  364. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  365. package/build/dist/UI/Utils/ModelListCache.js +126 -0
  366. package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
  367. package/build/dist/UI/Utils/Project.js +24 -1
  368. package/build/dist/UI/Utils/Project.js.map +1 -1
  369. package/build/dist/Utils/API.js +6 -1
  370. package/build/dist/Utils/API.js.map +1 -1
  371. package/jest.config.json +1 -1
  372. package/package.json +2 -3
  373. package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
  374. package/Tests/__mocks__/otpauth.js +0 -30
  375. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
  376. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
@@ -588,6 +588,20 @@ export default class OnCallDutyPolicySchedule extends BaseModel {
588
588
  })
589
589
  @TableColumn({
590
590
  type: TableColumnType.ObjectID,
591
+ /*
592
+ * Read through a relation, alongside `name`, so a joined schedule row can
593
+ * say whether it would page anybody right now. An escalation rule lists
594
+ * schedules by name and has to mark the ones that are currently uncovered;
595
+ * that is one join away from the rule, and without this flag
596
+ * QueryPermission rejects the whole select rather than dropping the column
597
+ * - the escalation rule page fails to load at all.
598
+ *
599
+ * The disclosure is a user id belonging to the same project as the
600
+ * schedule, to a caller who is already reading the schedule's name off the
601
+ * same joined row. It is not an @OwnerOnlyColumn: who is on call is
602
+ * operational state the team is meant to see, not a personal credential.
603
+ */
604
+ canReadOnRelationQuery: true,
591
605
  title: "Current User ID On Roster",
592
606
  description: "User ID who is currently on roster",
593
607
  example: "c3d4e5f6-a7b8-9012-cdef-123456789012",
@@ -315,15 +315,27 @@ class UserCall extends BaseModel {
315
315
  @OwnerOnlyColumn()
316
316
  @TableColumn({
317
317
  title: "Verification Code",
318
- description: "Temporary Verification Code",
318
+ description:
319
+ "Keyed digest of the temporary verification code — never the code itself",
319
320
  isDefaultValueColumn: true,
320
321
  computed: true,
321
322
  required: true,
322
323
  type: TableColumnType.ShortText,
324
+ /*
325
+ * A row is born with NO usable code on it: a 64-character random
326
+ * placeholder that no six-digit code can ever hash to. The real code is
327
+ * generated, hashed and sent by this channel's service once the row
328
+ * exists — the row id is part of the hashed message, so the digest cannot
329
+ * be computed before the insert has assigned one.
330
+ *
331
+ * This stays a forced default rather than moving wholly into the service
332
+ * hook because the column is NOT NULL and must be satisfied on every
333
+ * create path, including those that pass props.ignoreHooks.
334
+ */
323
335
  forceGetDefaultValueOnCreate: () => {
324
- return Text.generateRandomNumber(6);
336
+ return Text.generateRandomText(64);
325
337
  },
326
- example: "123456",
338
+ example: "9f2c1b4a7d3e6058c1f0a9b8d7e6f5c4b3a291807f6e5d4c3b2a19081726354",
327
339
  })
328
340
  @Column({
329
341
  type: ColumnType.ShortText,
@@ -331,6 +343,85 @@ class UserCall extends BaseModel {
331
343
  length: ColumnLength.ShortText,
332
344
  })
333
345
  public verificationCode?: string = undefined;
346
+
347
+ @ColumnAccessControl({
348
+ create: [],
349
+ read: [],
350
+ update: [],
351
+ })
352
+ /*
353
+ * When the code currently on this row stops being accepted.
354
+ *
355
+ * NULL means there is no live code: none was ever issued, or the last one
356
+ * was used, or it was burned by the attempt limit — or the row predates
357
+ * this column, which is read the same conservative way. Without an expiry
358
+ * the six-digit code space stood open indefinitely, which is what made
359
+ * walking it worthwhile.
360
+ */
361
+ @TableColumn({
362
+ title: "Verification Code Expires At",
363
+ description: "When the verification code on this row stops being accepted",
364
+ computed: true,
365
+ type: TableColumnType.Date,
366
+ })
367
+ @Column({
368
+ type: ColumnType.Date,
369
+ nullable: true,
370
+ })
371
+ public verificationCodeExpiresAt?: Date = undefined;
372
+
373
+ @ColumnAccessControl({
374
+ create: [],
375
+ read: [],
376
+ update: [],
377
+ })
378
+ /*
379
+ * Wrong guesses made against the code currently on this row, reset to zero
380
+ * each time a code is issued.
381
+ *
382
+ * This is the counter that stops /verify being an unlimited oracle over a
383
+ * space small enough to walk in minutes. It is incremented with a single
384
+ * atomic UPDATE ... RETURNING rather than a read-modify-write, because
385
+ * requests racing each other are the normal shape of the attack.
386
+ */
387
+ @TableColumn({
388
+ title: "Verification Failed Attempts",
389
+ description:
390
+ "Incorrect verification attempts made against the current verification code",
391
+ computed: true,
392
+ type: TableColumnType.Number,
393
+ })
394
+ @Column({
395
+ type: ColumnType.Number,
396
+ nullable: false,
397
+ default: 0,
398
+ })
399
+ public verificationFailedAttempts?: number = undefined;
400
+
401
+ @ColumnAccessControl({
402
+ create: [],
403
+ read: [],
404
+ update: [],
405
+ })
406
+ /*
407
+ * When a verification code was last sent for this row.
408
+ *
409
+ * Drives the resend cooldown. Without it, "spend the five attempts, ask for
410
+ * a fresh code, repeat" costs an attacker nothing — and the resend control
411
+ * doubles as a way to send somebody unsolicited messages at whatever rate
412
+ * the network allows, at the project's expense.
413
+ */
414
+ @TableColumn({
415
+ title: "Verification Code Sent At",
416
+ description: "When a verification code was last sent for this row",
417
+ computed: true,
418
+ type: TableColumnType.Date,
419
+ })
420
+ @Column({
421
+ type: ColumnType.Date,
422
+ nullable: true,
423
+ })
424
+ public verificationCodeSentAt?: Date = undefined;
334
425
  }
335
426
 
336
427
  export default UserCall;
@@ -318,15 +318,27 @@ class UserEmail extends BaseModel {
318
318
  @OwnerOnlyColumn()
319
319
  @TableColumn({
320
320
  title: "Verification Code",
321
- description: "Temporary Verification Code",
321
+ description:
322
+ "Keyed digest of the temporary verification code — never the code itself",
322
323
  isDefaultValueColumn: true,
323
324
  computed: true,
324
325
  required: true,
325
326
  type: TableColumnType.ShortText,
327
+ /*
328
+ * A row is born with NO usable code on it: a 64-character random
329
+ * placeholder that no six-digit code can ever hash to. The real code is
330
+ * generated, hashed and sent by this channel's service once the row
331
+ * exists — the row id is part of the hashed message, so the digest cannot
332
+ * be computed before the insert has assigned one.
333
+ *
334
+ * This stays a forced default rather than moving wholly into the service
335
+ * hook because the column is NOT NULL and must be satisfied on every
336
+ * create path, including those that pass props.ignoreHooks.
337
+ */
326
338
  forceGetDefaultValueOnCreate: () => {
327
- return Text.generateRandomNumber(6);
339
+ return Text.generateRandomText(64);
328
340
  },
329
- example: "123456",
341
+ example: "9f2c1b4a7d3e6058c1f0a9b8d7e6f5c4b3a291807f6e5d4c3b2a19081726354",
330
342
  })
331
343
  @Column({
332
344
  type: ColumnType.ShortText,
@@ -334,6 +346,85 @@ class UserEmail extends BaseModel {
334
346
  length: ColumnLength.ShortText,
335
347
  })
336
348
  public verificationCode?: string = undefined;
349
+
350
+ @ColumnAccessControl({
351
+ create: [],
352
+ read: [],
353
+ update: [],
354
+ })
355
+ /*
356
+ * When the code currently on this row stops being accepted.
357
+ *
358
+ * NULL means there is no live code: none was ever issued, or the last one
359
+ * was used, or it was burned by the attempt limit — or the row predates
360
+ * this column, which is read the same conservative way. Without an expiry
361
+ * the six-digit code space stood open indefinitely, which is what made
362
+ * walking it worthwhile.
363
+ */
364
+ @TableColumn({
365
+ title: "Verification Code Expires At",
366
+ description: "When the verification code on this row stops being accepted",
367
+ computed: true,
368
+ type: TableColumnType.Date,
369
+ })
370
+ @Column({
371
+ type: ColumnType.Date,
372
+ nullable: true,
373
+ })
374
+ public verificationCodeExpiresAt?: Date = undefined;
375
+
376
+ @ColumnAccessControl({
377
+ create: [],
378
+ read: [],
379
+ update: [],
380
+ })
381
+ /*
382
+ * Wrong guesses made against the code currently on this row, reset to zero
383
+ * each time a code is issued.
384
+ *
385
+ * This is the counter that stops /verify being an unlimited oracle over a
386
+ * space small enough to walk in minutes. It is incremented with a single
387
+ * atomic UPDATE ... RETURNING rather than a read-modify-write, because
388
+ * requests racing each other are the normal shape of the attack.
389
+ */
390
+ @TableColumn({
391
+ title: "Verification Failed Attempts",
392
+ description:
393
+ "Incorrect verification attempts made against the current verification code",
394
+ computed: true,
395
+ type: TableColumnType.Number,
396
+ })
397
+ @Column({
398
+ type: ColumnType.Number,
399
+ nullable: false,
400
+ default: 0,
401
+ })
402
+ public verificationFailedAttempts?: number = undefined;
403
+
404
+ @ColumnAccessControl({
405
+ create: [],
406
+ read: [],
407
+ update: [],
408
+ })
409
+ /*
410
+ * When a verification code was last sent for this row.
411
+ *
412
+ * Drives the resend cooldown. Without it, "spend the five attempts, ask for
413
+ * a fresh code, repeat" costs an attacker nothing — and the resend control
414
+ * doubles as a way to send somebody unsolicited messages at whatever rate
415
+ * the network allows, at the project's expense.
416
+ */
417
+ @TableColumn({
418
+ title: "Verification Code Sent At",
419
+ description: "When a verification code was last sent for this row",
420
+ computed: true,
421
+ type: TableColumnType.Date,
422
+ })
423
+ @Column({
424
+ type: ColumnType.Date,
425
+ nullable: true,
426
+ })
427
+ public verificationCodeSentAt?: Date = undefined;
337
428
  }
338
429
 
339
430
  export default UserEmail;
@@ -275,15 +275,27 @@ class UserIncomingCallNumber extends BaseModel {
275
275
  })
276
276
  @TableColumn({
277
277
  title: "Verification Code",
278
- description: "Temporary Verification Code",
278
+ description:
279
+ "Keyed digest of the temporary verification code — never the code itself",
279
280
  isDefaultValueColumn: true,
280
281
  computed: true,
281
282
  required: true,
282
283
  type: TableColumnType.ShortText,
284
+ /*
285
+ * A row is born with NO usable code on it: a 64-character random
286
+ * placeholder that no six-digit code can ever hash to. The real code is
287
+ * generated, hashed and sent by this channel's service once the row
288
+ * exists — the row id is part of the hashed message, so the digest cannot
289
+ * be computed before the insert has assigned one.
290
+ *
291
+ * This stays a forced default rather than moving wholly into the service
292
+ * hook because the column is NOT NULL and must be satisfied on every
293
+ * create path, including those that pass props.ignoreHooks.
294
+ */
283
295
  forceGetDefaultValueOnCreate: () => {
284
- return Text.generateRandomNumber(6);
296
+ return Text.generateRandomText(64);
285
297
  },
286
- example: "123456",
298
+ example: "9f2c1b4a7d3e6058c1f0a9b8d7e6f5c4b3a291807f6e5d4c3b2a19081726354",
287
299
  })
288
300
  @Column({
289
301
  type: ColumnType.ShortText,
@@ -291,6 +303,85 @@ class UserIncomingCallNumber extends BaseModel {
291
303
  length: ColumnLength.ShortText,
292
304
  })
293
305
  public verificationCode?: string = undefined;
306
+
307
+ @ColumnAccessControl({
308
+ create: [],
309
+ read: [],
310
+ update: [],
311
+ })
312
+ /*
313
+ * When the code currently on this row stops being accepted.
314
+ *
315
+ * NULL means there is no live code: none was ever issued, or the last one
316
+ * was used, or it was burned by the attempt limit — or the row predates
317
+ * this column, which is read the same conservative way. Without an expiry
318
+ * the six-digit code space stood open indefinitely, which is what made
319
+ * walking it worthwhile.
320
+ */
321
+ @TableColumn({
322
+ title: "Verification Code Expires At",
323
+ description: "When the verification code on this row stops being accepted",
324
+ computed: true,
325
+ type: TableColumnType.Date,
326
+ })
327
+ @Column({
328
+ type: ColumnType.Date,
329
+ nullable: true,
330
+ })
331
+ public verificationCodeExpiresAt?: Date = undefined;
332
+
333
+ @ColumnAccessControl({
334
+ create: [],
335
+ read: [],
336
+ update: [],
337
+ })
338
+ /*
339
+ * Wrong guesses made against the code currently on this row, reset to zero
340
+ * each time a code is issued.
341
+ *
342
+ * This is the counter that stops /verify being an unlimited oracle over a
343
+ * space small enough to walk in minutes. It is incremented with a single
344
+ * atomic UPDATE ... RETURNING rather than a read-modify-write, because
345
+ * requests racing each other are the normal shape of the attack.
346
+ */
347
+ @TableColumn({
348
+ title: "Verification Failed Attempts",
349
+ description:
350
+ "Incorrect verification attempts made against the current verification code",
351
+ computed: true,
352
+ type: TableColumnType.Number,
353
+ })
354
+ @Column({
355
+ type: ColumnType.Number,
356
+ nullable: false,
357
+ default: 0,
358
+ })
359
+ public verificationFailedAttempts?: number = undefined;
360
+
361
+ @ColumnAccessControl({
362
+ create: [],
363
+ read: [],
364
+ update: [],
365
+ })
366
+ /*
367
+ * When a verification code was last sent for this row.
368
+ *
369
+ * Drives the resend cooldown. Without it, "spend the five attempts, ask for
370
+ * a fresh code, repeat" costs an attacker nothing — and the resend control
371
+ * doubles as a way to send somebody unsolicited messages at whatever rate
372
+ * the network allows, at the project's expense.
373
+ */
374
+ @TableColumn({
375
+ title: "Verification Code Sent At",
376
+ description: "When a verification code was last sent for this row",
377
+ computed: true,
378
+ type: TableColumnType.Date,
379
+ })
380
+ @Column({
381
+ type: ColumnType.Date,
382
+ nullable: true,
383
+ })
384
+ public verificationCodeSentAt?: Date = undefined;
294
385
  }
295
386
 
296
387
  export default UserIncomingCallNumber;
@@ -346,6 +346,43 @@ class UserPush extends BaseModel {
346
346
  default: false,
347
347
  })
348
348
  public isVerified?: boolean = undefined;
349
+
350
+ /*
351
+ * Whether this handset should be paged through silent mode and Do Not
352
+ * Disturb when it is on call. Per DEVICE and not per user on purpose: the
353
+ * responder's work phone on the nightstand and their tablet on the sofa are
354
+ * the same person making two different decisions, and only the phone should
355
+ * be allowed to wake the house.
356
+ *
357
+ * Off unless the responder turns it on from that device. It is the one
358
+ * setting in this product that deliberately defeats the switch a person
359
+ * flicked to be left alone, so it is opted into rather than out of, and the
360
+ * app only offers it once the OS has actually granted the capability
361
+ * (the iOS critical-alert entitlement, or Do Not Disturb access on Android).
362
+ *
363
+ * `update` is empty like every other column here: the value is written by
364
+ * UserPushAPI's critical-alerts route, which checks the row belongs to the
365
+ * caller and then writes as root. That keeps "who may change this" in one
366
+ * readable place rather than spread across the generic CRUD surface.
367
+ */
368
+ @ColumnAccessControl({
369
+ create: [Permission.CurrentUser],
370
+ read: [Permission.CurrentUser],
371
+ update: [],
372
+ })
373
+ @TableColumn({
374
+ title: "Critical Alerts Enabled",
375
+ description:
376
+ "Should on-call notifications to this device override silent mode and Do Not Disturb?",
377
+ isDefaultValueColumn: true,
378
+ type: TableColumnType.Boolean,
379
+ defaultValue: false,
380
+ })
381
+ @Column({
382
+ type: ColumnType.Boolean,
383
+ default: false,
384
+ })
385
+ public isCriticalAlertEnabled?: boolean = undefined;
349
386
  }
350
387
 
351
388
  export default UserPush;
@@ -317,15 +317,27 @@ class UserSMS extends BaseModel {
317
317
  @OwnerOnlyColumn()
318
318
  @TableColumn({
319
319
  title: "Verification Code",
320
- description: "Temporary Verification Code",
320
+ description:
321
+ "Keyed digest of the temporary verification code — never the code itself",
321
322
  isDefaultValueColumn: true,
322
323
  computed: true,
323
324
  required: true,
324
325
  type: TableColumnType.ShortText,
326
+ /*
327
+ * A row is born with NO usable code on it: a 64-character random
328
+ * placeholder that no six-digit code can ever hash to. The real code is
329
+ * generated, hashed and sent by this channel's service once the row
330
+ * exists — the row id is part of the hashed message, so the digest cannot
331
+ * be computed before the insert has assigned one.
332
+ *
333
+ * This stays a forced default rather than moving wholly into the service
334
+ * hook because the column is NOT NULL and must be satisfied on every
335
+ * create path, including those that pass props.ignoreHooks.
336
+ */
325
337
  forceGetDefaultValueOnCreate: () => {
326
- return Text.generateRandomNumber(6);
338
+ return Text.generateRandomText(64);
327
339
  },
328
- example: "123456",
340
+ example: "9f2c1b4a7d3e6058c1f0a9b8d7e6f5c4b3a291807f6e5d4c3b2a19081726354",
329
341
  })
330
342
  @Column({
331
343
  type: ColumnType.ShortText,
@@ -333,6 +345,85 @@ class UserSMS extends BaseModel {
333
345
  length: ColumnLength.ShortText,
334
346
  })
335
347
  public verificationCode?: string = undefined;
348
+
349
+ @ColumnAccessControl({
350
+ create: [],
351
+ read: [],
352
+ update: [],
353
+ })
354
+ /*
355
+ * When the code currently on this row stops being accepted.
356
+ *
357
+ * NULL means there is no live code: none was ever issued, or the last one
358
+ * was used, or it was burned by the attempt limit — or the row predates
359
+ * this column, which is read the same conservative way. Without an expiry
360
+ * the six-digit code space stood open indefinitely, which is what made
361
+ * walking it worthwhile.
362
+ */
363
+ @TableColumn({
364
+ title: "Verification Code Expires At",
365
+ description: "When the verification code on this row stops being accepted",
366
+ computed: true,
367
+ type: TableColumnType.Date,
368
+ })
369
+ @Column({
370
+ type: ColumnType.Date,
371
+ nullable: true,
372
+ })
373
+ public verificationCodeExpiresAt?: Date = undefined;
374
+
375
+ @ColumnAccessControl({
376
+ create: [],
377
+ read: [],
378
+ update: [],
379
+ })
380
+ /*
381
+ * Wrong guesses made against the code currently on this row, reset to zero
382
+ * each time a code is issued.
383
+ *
384
+ * This is the counter that stops /verify being an unlimited oracle over a
385
+ * space small enough to walk in minutes. It is incremented with a single
386
+ * atomic UPDATE ... RETURNING rather than a read-modify-write, because
387
+ * requests racing each other are the normal shape of the attack.
388
+ */
389
+ @TableColumn({
390
+ title: "Verification Failed Attempts",
391
+ description:
392
+ "Incorrect verification attempts made against the current verification code",
393
+ computed: true,
394
+ type: TableColumnType.Number,
395
+ })
396
+ @Column({
397
+ type: ColumnType.Number,
398
+ nullable: false,
399
+ default: 0,
400
+ })
401
+ public verificationFailedAttempts?: number = undefined;
402
+
403
+ @ColumnAccessControl({
404
+ create: [],
405
+ read: [],
406
+ update: [],
407
+ })
408
+ /*
409
+ * When a verification code was last sent for this row.
410
+ *
411
+ * Drives the resend cooldown. Without it, "spend the five attempts, ask for
412
+ * a fresh code, repeat" costs an attacker nothing — and the resend control
413
+ * doubles as a way to send somebody unsolicited messages at whatever rate
414
+ * the network allows, at the project's expense.
415
+ */
416
+ @TableColumn({
417
+ title: "Verification Code Sent At",
418
+ description: "When a verification code was last sent for this row",
419
+ computed: true,
420
+ type: TableColumnType.Date,
421
+ })
422
+ @Column({
423
+ type: ColumnType.Date,
424
+ nullable: true,
425
+ })
426
+ public verificationCodeSentAt?: Date = undefined;
336
427
  }
337
428
 
338
429
  export default UserSMS;
@@ -309,13 +309,25 @@ class UserWhatsApp extends BaseModel {
309
309
  @OwnerOnlyColumn()
310
310
  @TableColumn({
311
311
  title: "Verification Code",
312
- description: "Temporary Verification Code",
312
+ description:
313
+ "Keyed digest of the temporary verification code — never the code itself",
313
314
  isDefaultValueColumn: true,
314
315
  computed: true,
315
316
  required: true,
316
317
  type: TableColumnType.ShortText,
318
+ /*
319
+ * A row is born with NO usable code on it: a 64-character random
320
+ * placeholder that no six-digit code can ever hash to. The real code is
321
+ * generated, hashed and sent by this channel's service once the row
322
+ * exists — the row id is part of the hashed message, so the digest cannot
323
+ * be computed before the insert has assigned one.
324
+ *
325
+ * This stays a forced default rather than moving wholly into the service
326
+ * hook because the column is NOT NULL and must be satisfied on every
327
+ * create path, including those that pass props.ignoreHooks.
328
+ */
317
329
  forceGetDefaultValueOnCreate: () => {
318
- return Text.generateRandomNumber(6);
330
+ return Text.generateRandomText(64);
319
331
  },
320
332
  })
321
333
  @Column({
@@ -324,6 +336,85 @@ class UserWhatsApp extends BaseModel {
324
336
  length: ColumnLength.ShortText,
325
337
  })
326
338
  public verificationCode?: string = undefined;
339
+
340
+ @ColumnAccessControl({
341
+ create: [],
342
+ read: [],
343
+ update: [],
344
+ })
345
+ /*
346
+ * When the code currently on this row stops being accepted.
347
+ *
348
+ * NULL means there is no live code: none was ever issued, or the last one
349
+ * was used, or it was burned by the attempt limit — or the row predates
350
+ * this column, which is read the same conservative way. Without an expiry
351
+ * the six-digit code space stood open indefinitely, which is what made
352
+ * walking it worthwhile.
353
+ */
354
+ @TableColumn({
355
+ title: "Verification Code Expires At",
356
+ description: "When the verification code on this row stops being accepted",
357
+ computed: true,
358
+ type: TableColumnType.Date,
359
+ })
360
+ @Column({
361
+ type: ColumnType.Date,
362
+ nullable: true,
363
+ })
364
+ public verificationCodeExpiresAt?: Date = undefined;
365
+
366
+ @ColumnAccessControl({
367
+ create: [],
368
+ read: [],
369
+ update: [],
370
+ })
371
+ /*
372
+ * Wrong guesses made against the code currently on this row, reset to zero
373
+ * each time a code is issued.
374
+ *
375
+ * This is the counter that stops /verify being an unlimited oracle over a
376
+ * space small enough to walk in minutes. It is incremented with a single
377
+ * atomic UPDATE ... RETURNING rather than a read-modify-write, because
378
+ * requests racing each other are the normal shape of the attack.
379
+ */
380
+ @TableColumn({
381
+ title: "Verification Failed Attempts",
382
+ description:
383
+ "Incorrect verification attempts made against the current verification code",
384
+ computed: true,
385
+ type: TableColumnType.Number,
386
+ })
387
+ @Column({
388
+ type: ColumnType.Number,
389
+ nullable: false,
390
+ default: 0,
391
+ })
392
+ public verificationFailedAttempts?: number = undefined;
393
+
394
+ @ColumnAccessControl({
395
+ create: [],
396
+ read: [],
397
+ update: [],
398
+ })
399
+ /*
400
+ * When a verification code was last sent for this row.
401
+ *
402
+ * Drives the resend cooldown. Without it, "spend the five attempts, ask for
403
+ * a fresh code, repeat" costs an attacker nothing — and the resend control
404
+ * doubles as a way to send somebody unsolicited messages at whatever rate
405
+ * the network allows, at the project's expense.
406
+ */
407
+ @TableColumn({
408
+ title: "Verification Code Sent At",
409
+ description: "When a verification code was last sent for this row",
410
+ computed: true,
411
+ type: TableColumnType.Date,
412
+ })
413
+ @Column({
414
+ type: ColumnType.Date,
415
+ nullable: true,
416
+ })
417
+ public verificationCodeSentAt?: Date = undefined;
327
418
  }
328
419
 
329
420
  export default UserWhatsApp;